vinext 0.0.30 → 0.0.32

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 (435) hide show
  1. package/README.md +15 -7
  2. package/dist/build/prerender.d.ts +188 -0
  3. package/dist/build/prerender.js +675 -0
  4. package/dist/build/prerender.js.map +1 -0
  5. package/dist/build/report.d.ts +45 -46
  6. package/dist/build/report.js +581 -276
  7. package/dist/build/report.js.map +1 -1
  8. package/dist/build/run-prerender.d.ts +62 -0
  9. package/dist/build/run-prerender.js +183 -0
  10. package/dist/build/run-prerender.js.map +1 -0
  11. package/dist/build/server-manifest.d.ts +19 -0
  12. package/dist/build/server-manifest.js +29 -0
  13. package/dist/build/server-manifest.js.map +1 -0
  14. package/dist/build/static-export.d.ts +51 -66
  15. package/dist/build/static-export.js +51 -545
  16. package/dist/build/static-export.js.map +1 -1
  17. package/dist/check.d.ts +26 -24
  18. package/dist/check.js +681 -571
  19. package/dist/check.js.map +1 -1
  20. package/dist/cli.d.ts +1 -15
  21. package/dist/cli.js +432 -491
  22. package/dist/cli.js.map +1 -1
  23. package/dist/client/entry.d.ts +1 -2
  24. package/dist/client/entry.js +49 -62
  25. package/dist/client/entry.js.map +1 -1
  26. package/dist/client/validate-module-path.d.ts +4 -1
  27. package/dist/client/validate-module-path.js +23 -28
  28. package/dist/client/validate-module-path.js.map +1 -1
  29. package/dist/client/vinext-next-data.d.ts +15 -20
  30. package/dist/client/vinext-next-data.js +0 -1
  31. package/dist/cloudflare/index.d.ts +3 -8
  32. package/dist/cloudflare/index.js +3 -8
  33. package/dist/cloudflare/kv-cache-handler.d.ts +95 -105
  34. package/dist/cloudflare/kv-cache-handler.js +354 -380
  35. package/dist/cloudflare/kv-cache-handler.js.map +1 -1
  36. package/dist/cloudflare/tpr.d.ts +36 -34
  37. package/dist/cloudflare/tpr.js +460 -603
  38. package/dist/cloudflare/tpr.js.map +1 -1
  39. package/dist/config/config-matchers.d.ts +31 -40
  40. package/dist/config/config-matchers.js +727 -936
  41. package/dist/config/config-matchers.js.map +1 -1
  42. package/dist/config/dotenv.d.ts +18 -11
  43. package/dist/config/dotenv.js +79 -84
  44. package/dist/config/dotenv.js.map +1 -1
  45. package/dist/config/next-config.d.ts +156 -146
  46. package/dist/config/next-config.js +376 -464
  47. package/dist/config/next-config.js.map +1 -1
  48. package/dist/deploy.d.ts +87 -96
  49. package/dist/deploy.js +490 -628
  50. package/dist/deploy.js.map +1 -1
  51. package/dist/entries/app-browser-entry.d.ts +4 -1
  52. package/dist/entries/app-browser-entry.js +12 -8
  53. package/dist/entries/app-browser-entry.js.map +1 -1
  54. package/dist/entries/app-rsc-entry.d.ts +33 -20
  55. package/dist/entries/app-rsc-entry.js +444 -212
  56. package/dist/entries/app-rsc-entry.js.map +1 -1
  57. package/dist/entries/app-ssr-entry.d.ts +9 -1
  58. package/dist/entries/app-ssr-entry.js +61 -28
  59. package/dist/entries/app-ssr-entry.js.map +1 -1
  60. package/dist/entries/pages-client-entry.d.ts +6 -2
  61. package/dist/entries/pages-client-entry.js +30 -33
  62. package/dist/entries/pages-client-entry.js.map +1 -1
  63. package/dist/entries/pages-entry-helpers.d.ts +5 -1
  64. package/dist/entries/pages-entry-helpers.js +17 -14
  65. package/dist/entries/pages-entry-helpers.js.map +1 -1
  66. package/dist/entries/pages-server-entry.d.ts +6 -2
  67. package/dist/entries/pages-server-entry.js +86 -114
  68. package/dist/entries/pages-server-entry.js.map +1 -1
  69. package/dist/index.d.ts +92 -60
  70. package/dist/index.js +2151 -3133
  71. package/dist/index.js.map +1 -1
  72. package/dist/init.d.ts +40 -37
  73. package/dist/init.js +201 -258
  74. package/dist/init.js.map +1 -1
  75. package/dist/plugins/async-hooks-stub.d.ts +7 -3
  76. package/dist/plugins/async-hooks-stub.js +39 -42
  77. package/dist/plugins/async-hooks-stub.js.map +1 -1
  78. package/dist/plugins/client-reference-dedup.d.ts +7 -3
  79. package/dist/plugins/client-reference-dedup.js +63 -88
  80. package/dist/plugins/client-reference-dedup.js.map +1 -1
  81. package/dist/routing/app-router.d.ts +100 -96
  82. package/dist/routing/app-router.js +560 -670
  83. package/dist/routing/app-router.js.map +1 -1
  84. package/dist/routing/file-matcher.d.ts +18 -15
  85. package/dist/routing/file-matcher.js +65 -65
  86. package/dist/routing/file-matcher.js.map +1 -1
  87. package/dist/routing/pages-router.d.ts +23 -24
  88. package/dist/routing/pages-router.js +147 -172
  89. package/dist/routing/pages-router.js.map +1 -1
  90. package/dist/routing/route-trie.d.ts +23 -20
  91. package/dist/routing/route-trie.js +131 -151
  92. package/dist/routing/route-trie.js.map +1 -1
  93. package/dist/routing/route-validation.d.ts +5 -2
  94. package/dist/routing/route-validation.js +98 -130
  95. package/dist/routing/route-validation.js.map +1 -1
  96. package/dist/routing/utils.d.ts +10 -7
  97. package/dist/routing/utils.js +75 -111
  98. package/dist/routing/utils.js.map +1 -1
  99. package/dist/server/api-handler.d.ts +8 -13
  100. package/dist/server/api-handler.js +160 -193
  101. package/dist/server/api-handler.js.map +1 -1
  102. package/dist/server/app-router-entry.d.ts +6 -16
  103. package/dist/server/app-router-entry.js +26 -54
  104. package/dist/server/app-router-entry.js.map +1 -1
  105. package/dist/server/dev-module-runner.d.ts +11 -64
  106. package/dist/server/dev-module-runner.js +89 -101
  107. package/dist/server/dev-module-runner.js.map +1 -1
  108. package/dist/server/dev-origin-check.d.ts +12 -10
  109. package/dist/server/dev-origin-check.js +98 -108
  110. package/dist/server/dev-origin-check.js.map +1 -1
  111. package/dist/server/dev-server.d.ts +19 -15
  112. package/dist/server/dev-server.js +543 -871
  113. package/dist/server/dev-server.js.map +1 -1
  114. package/dist/server/html.d.ts +4 -1
  115. package/dist/server/html.js +25 -26
  116. package/dist/server/html.js.map +1 -1
  117. package/dist/server/image-optimization.d.ts +31 -28
  118. package/dist/server/image-optimization.js +181 -210
  119. package/dist/server/image-optimization.js.map +1 -1
  120. package/dist/server/instrumentation.d.ts +34 -59
  121. package/dist/server/instrumentation.js +112 -125
  122. package/dist/server/instrumentation.js.map +1 -1
  123. package/dist/server/isr-cache.d.ts +16 -26
  124. package/dist/server/isr-cache.js +106 -128
  125. package/dist/server/isr-cache.js.map +1 -1
  126. package/dist/server/metadata-routes.d.ts +85 -88
  127. package/dist/server/metadata-routes.js +270 -317
  128. package/dist/server/metadata-routes.js.map +1 -1
  129. package/dist/server/middleware-codegen.d.ts +7 -4
  130. package/dist/server/middleware-codegen.js +61 -61
  131. package/dist/server/middleware-codegen.js.map +1 -1
  132. package/dist/server/middleware-request-headers.d.ts +8 -6
  133. package/dist/server/middleware-request-headers.js +47 -65
  134. package/dist/server/middleware-request-headers.js.map +1 -1
  135. package/dist/server/middleware.d.ts +32 -47
  136. package/dist/server/middleware.js +261 -409
  137. package/dist/server/middleware.js.map +1 -1
  138. package/dist/server/normalize-path.d.ts +4 -1
  139. package/dist/server/normalize-path.js +33 -47
  140. package/dist/server/normalize-path.js.map +1 -1
  141. package/dist/server/pages-i18n.d.ts +38 -30
  142. package/dist/server/pages-i18n.js +112 -139
  143. package/dist/server/pages-i18n.js.map +1 -1
  144. package/dist/server/prod-server.d.ts +19 -31
  145. package/dist/server/prod-server.js +715 -945
  146. package/dist/server/prod-server.js.map +1 -1
  147. package/dist/server/request-log.d.ts +18 -12
  148. package/dist/server/request-log.js +45 -52
  149. package/dist/server/request-log.js.map +1 -1
  150. package/dist/server/request-pipeline.d.ts +9 -17
  151. package/dist/server/request-pipeline.js +133 -184
  152. package/dist/server/request-pipeline.js.map +1 -1
  153. package/dist/server/worker-utils.d.ts +4 -1
  154. package/dist/server/worker-utils.js +31 -37
  155. package/dist/server/worker-utils.js.map +1 -1
  156. package/dist/shims/amp.d.ts +5 -2
  157. package/dist/shims/amp.js +19 -15
  158. package/dist/shims/amp.js.map +1 -1
  159. package/dist/shims/app.d.ts +8 -10
  160. package/dist/shims/app.js +0 -1
  161. package/dist/shims/cache-runtime.d.ts +20 -45
  162. package/dist/shims/cache-runtime.js +271 -422
  163. package/dist/shims/cache-runtime.js.map +1 -1
  164. package/dist/shims/cache.d.ts +130 -121
  165. package/dist/shims/cache.js +339 -427
  166. package/dist/shims/cache.js.map +1 -1
  167. package/dist/shims/client-only.d.ts +1 -18
  168. package/dist/shims/client-only.js +0 -17
  169. package/dist/shims/compat-router.d.ts +6 -1
  170. package/dist/shims/compat-router.js +23 -19
  171. package/dist/shims/compat-router.js.map +1 -1
  172. package/dist/shims/config.d.ts +7 -5
  173. package/dist/shims/config.js +16 -23
  174. package/dist/shims/config.js.map +1 -1
  175. package/dist/shims/constants.d.ts +119 -118
  176. package/dist/shims/constants.js +159 -164
  177. package/dist/shims/constants.js.map +1 -1
  178. package/dist/shims/document.d.ts +20 -16
  179. package/dist/shims/document.js +41 -22
  180. package/dist/shims/document.js.map +1 -1
  181. package/dist/shims/dynamic.d.ts +13 -22
  182. package/dist/shims/dynamic.js +122 -136
  183. package/dist/shims/dynamic.js.map +1 -1
  184. package/dist/shims/error-boundary.d.ts +22 -15
  185. package/dist/shims/error-boundary.js +81 -79
  186. package/dist/shims/error-boundary.js.map +1 -1
  187. package/dist/shims/error.d.ts +11 -12
  188. package/dist/shims/error.js +35 -39
  189. package/dist/shims/error.js.map +1 -1
  190. package/dist/shims/fetch-cache.d.ts +16 -14
  191. package/dist/shims/fetch-cache.js +439 -645
  192. package/dist/shims/fetch-cache.js.map +1 -1
  193. package/dist/shims/font-google-base.d.ts +28 -26
  194. package/dist/shims/font-google-base.js +238 -325
  195. package/dist/shims/font-google-base.js.map +1 -1
  196. package/dist/shims/font-google.d.ts +3 -3
  197. package/dist/shims/font-google.generated.d.ts +1928 -1924
  198. package/dist/shims/font-google.generated.js +1928 -2133
  199. package/dist/shims/font-google.generated.js.map +1 -1
  200. package/dist/shims/font-google.js +3 -3
  201. package/dist/shims/font-local.d.ts +28 -26
  202. package/dist/shims/font-local.js +204 -260
  203. package/dist/shims/font-local.js.map +1 -1
  204. package/dist/shims/form.d.ts +13 -27
  205. package/dist/shims/form.js +128 -180
  206. package/dist/shims/form.js.map +1 -1
  207. package/dist/shims/head-state.d.ts +8 -13
  208. package/dist/shims/head-state.js +25 -42
  209. package/dist/shims/head-state.js.map +1 -1
  210. package/dist/shims/head.d.ts +17 -20
  211. package/dist/shims/head.js +194 -250
  212. package/dist/shims/head.js.map +1 -1
  213. package/dist/shims/headers.d.ts +84 -78
  214. package/dist/shims/headers.js +447 -575
  215. package/dist/shims/headers.js.map +1 -1
  216. package/dist/shims/i18n-context.d.ts +16 -20
  217. package/dist/shims/i18n-context.js +35 -48
  218. package/dist/shims/i18n-context.js.map +1 -1
  219. package/dist/shims/i18n-state.d.ts +8 -14
  220. package/dist/shims/i18n-state.js +34 -42
  221. package/dist/shims/i18n-state.js.map +1 -1
  222. package/dist/shims/image-config.d.ts +11 -8
  223. package/dist/shims/image-config.js +50 -83
  224. package/dist/shims/image-config.js.map +1 -1
  225. package/dist/shims/image.d.ts +37 -46
  226. package/dist/shims/image.js +283 -308
  227. package/dist/shims/image.js.map +1 -1
  228. package/dist/shims/internal/api-utils.d.ts +7 -4
  229. package/dist/shims/internal/api-utils.js +0 -6
  230. package/dist/shims/internal/app-router-context.d.ts +22 -17
  231. package/dist/shims/internal/app-router-context.js +17 -13
  232. package/dist/shims/internal/app-router-context.js.map +1 -1
  233. package/dist/shims/internal/cookies.d.ts +2 -9
  234. package/dist/shims/internal/cookies.js +2 -9
  235. package/dist/shims/internal/parse-cookie-header.d.ts +4 -1
  236. package/dist/shims/internal/parse-cookie-header.js +29 -29
  237. package/dist/shims/internal/parse-cookie-header.js.map +1 -1
  238. package/dist/shims/internal/router-context.d.ts +7 -1
  239. package/dist/shims/internal/router-context.js +11 -7
  240. package/dist/shims/internal/router-context.js.map +1 -1
  241. package/dist/shims/internal/utils.d.ts +40 -37
  242. package/dist/shims/internal/utils.js +24 -30
  243. package/dist/shims/internal/utils.js.map +1 -1
  244. package/dist/shims/internal/work-unit-async-storage.d.ts +6 -10
  245. package/dist/shims/internal/work-unit-async-storage.js +14 -11
  246. package/dist/shims/internal/work-unit-async-storage.js.map +1 -1
  247. package/dist/shims/layout-segment-context.d.ts +11 -14
  248. package/dist/shims/layout-segment-context.js +24 -23
  249. package/dist/shims/layout-segment-context.js.map +1 -1
  250. package/dist/shims/legacy-image.d.ts +39 -46
  251. package/dist/shims/legacy-image.js +47 -42
  252. package/dist/shims/legacy-image.js.map +1 -1
  253. package/dist/shims/link.d.ts +32 -36
  254. package/dist/shims/link.js +255 -391
  255. package/dist/shims/link.js.map +1 -1
  256. package/dist/shims/metadata.d.ts +210 -202
  257. package/dist/shims/metadata.js +545 -546
  258. package/dist/shims/metadata.js.map +1 -1
  259. package/dist/shims/navigation-state.d.ts +10 -18
  260. package/dist/shims/navigation-state.js +66 -74
  261. package/dist/shims/navigation-state.js.map +1 -1
  262. package/dist/shims/navigation.d.ts +59 -63
  263. package/dist/shims/navigation.js +505 -704
  264. package/dist/shims/navigation.js.map +1 -1
  265. package/dist/shims/og.d.ts +2 -20
  266. package/dist/shims/og.js +2 -19
  267. package/dist/shims/readonly-url-search-params.d.ts +8 -5
  268. package/dist/shims/readonly-url-search-params.js +26 -22
  269. package/dist/shims/readonly-url-search-params.js.map +1 -1
  270. package/dist/shims/request-context.d.ts +8 -5
  271. package/dist/shims/request-context.js +50 -60
  272. package/dist/shims/request-context.js.map +1 -1
  273. package/dist/shims/request-state-types.d.ts +11 -11
  274. package/dist/shims/request-state-types.js +0 -1
  275. package/dist/shims/router-state.d.ts +13 -10
  276. package/dist/shims/router-state.js +34 -43
  277. package/dist/shims/router-state.js.map +1 -1
  278. package/dist/shims/router.d.ts +81 -85
  279. package/dist/shims/router.js +506 -628
  280. package/dist/shims/router.js.map +1 -1
  281. package/dist/shims/script.d.ts +39 -48
  282. package/dist/shims/script.js +107 -160
  283. package/dist/shims/script.js.map +1 -1
  284. package/dist/shims/server-only.d.ts +1 -19
  285. package/dist/shims/server-only.js +0 -18
  286. package/dist/shims/server.d.ts +213 -164
  287. package/dist/shims/server.js +545 -478
  288. package/dist/shims/server.js.map +1 -1
  289. package/dist/shims/unified-request-context.d.ts +20 -20
  290. package/dist/shims/unified-request-context.js +81 -99
  291. package/dist/shims/unified-request-context.js.map +1 -1
  292. package/dist/shims/url-safety.d.ts +4 -1
  293. package/dist/shims/url-safety.js +15 -11
  294. package/dist/shims/url-safety.js.map +1 -1
  295. package/dist/shims/url-utils.d.ts +8 -5
  296. package/dist/shims/url-utils.js +62 -93
  297. package/dist/shims/url-utils.js.map +1 -1
  298. package/dist/shims/web-vitals.d.ts +10 -8
  299. package/dist/shims/web-vitals.js +9 -15
  300. package/dist/shims/web-vitals.js.map +1 -1
  301. package/dist/utils/base-path.d.ts +5 -2
  302. package/dist/utils/base-path.js +21 -19
  303. package/dist/utils/base-path.js.map +1 -1
  304. package/dist/utils/domain-locale.d.ts +17 -9
  305. package/dist/utils/domain-locale.js +36 -56
  306. package/dist/utils/domain-locale.js.map +1 -1
  307. package/dist/utils/hash.d.ts +4 -1
  308. package/dist/utils/hash.js +19 -17
  309. package/dist/utils/hash.js.map +1 -1
  310. package/dist/utils/manifest-paths.d.ts +6 -3
  311. package/dist/utils/manifest-paths.js +15 -16
  312. package/dist/utils/manifest-paths.js.map +1 -1
  313. package/dist/utils/project.d.ts +13 -11
  314. package/dist/utils/project.js +169 -216
  315. package/dist/utils/project.js.map +1 -1
  316. package/dist/utils/query.d.ts +8 -6
  317. package/dist/utils/query.js +57 -67
  318. package/dist/utils/query.js.map +1 -1
  319. package/package.json +10 -9
  320. package/dist/build/report.d.ts.map +0 -1
  321. package/dist/build/static-export.d.ts.map +0 -1
  322. package/dist/check.d.ts.map +0 -1
  323. package/dist/cli.d.ts.map +0 -1
  324. package/dist/client/entry.d.ts.map +0 -1
  325. package/dist/client/validate-module-path.d.ts.map +0 -1
  326. package/dist/client/vinext-next-data.d.ts.map +0 -1
  327. package/dist/client/vinext-next-data.js.map +0 -1
  328. package/dist/cloudflare/index.d.ts.map +0 -1
  329. package/dist/cloudflare/index.js.map +0 -1
  330. package/dist/cloudflare/kv-cache-handler.d.ts.map +0 -1
  331. package/dist/cloudflare/tpr.d.ts.map +0 -1
  332. package/dist/config/config-matchers.d.ts.map +0 -1
  333. package/dist/config/dotenv.d.ts.map +0 -1
  334. package/dist/config/next-config.d.ts.map +0 -1
  335. package/dist/deploy.d.ts.map +0 -1
  336. package/dist/entries/app-browser-entry.d.ts.map +0 -1
  337. package/dist/entries/app-rsc-entry.d.ts.map +0 -1
  338. package/dist/entries/app-ssr-entry.d.ts.map +0 -1
  339. package/dist/entries/pages-client-entry.d.ts.map +0 -1
  340. package/dist/entries/pages-entry-helpers.d.ts.map +0 -1
  341. package/dist/entries/pages-server-entry.d.ts.map +0 -1
  342. package/dist/index.d.ts.map +0 -1
  343. package/dist/init.d.ts.map +0 -1
  344. package/dist/plugins/async-hooks-stub.d.ts.map +0 -1
  345. package/dist/plugins/client-reference-dedup.d.ts.map +0 -1
  346. package/dist/routing/app-router.d.ts.map +0 -1
  347. package/dist/routing/file-matcher.d.ts.map +0 -1
  348. package/dist/routing/pages-router.d.ts.map +0 -1
  349. package/dist/routing/route-trie.d.ts.map +0 -1
  350. package/dist/routing/route-validation.d.ts.map +0 -1
  351. package/dist/routing/utils.d.ts.map +0 -1
  352. package/dist/server/api-handler.d.ts.map +0 -1
  353. package/dist/server/app-router-entry.d.ts.map +0 -1
  354. package/dist/server/dev-module-runner.d.ts.map +0 -1
  355. package/dist/server/dev-origin-check.d.ts.map +0 -1
  356. package/dist/server/dev-server.d.ts.map +0 -1
  357. package/dist/server/html.d.ts.map +0 -1
  358. package/dist/server/image-optimization.d.ts.map +0 -1
  359. package/dist/server/instrumentation.d.ts.map +0 -1
  360. package/dist/server/isr-cache.d.ts.map +0 -1
  361. package/dist/server/metadata-routes.d.ts.map +0 -1
  362. package/dist/server/middleware-codegen.d.ts.map +0 -1
  363. package/dist/server/middleware-request-headers.d.ts.map +0 -1
  364. package/dist/server/middleware.d.ts.map +0 -1
  365. package/dist/server/normalize-path.d.ts.map +0 -1
  366. package/dist/server/pages-i18n.d.ts.map +0 -1
  367. package/dist/server/prod-server.d.ts.map +0 -1
  368. package/dist/server/request-log.d.ts.map +0 -1
  369. package/dist/server/request-pipeline.d.ts.map +0 -1
  370. package/dist/server/worker-utils.d.ts.map +0 -1
  371. package/dist/shims/amp.d.ts.map +0 -1
  372. package/dist/shims/app.d.ts.map +0 -1
  373. package/dist/shims/app.js.map +0 -1
  374. package/dist/shims/cache-runtime.d.ts.map +0 -1
  375. package/dist/shims/cache.d.ts.map +0 -1
  376. package/dist/shims/client-only.d.ts.map +0 -1
  377. package/dist/shims/client-only.js.map +0 -1
  378. package/dist/shims/compat-router.d.ts.map +0 -1
  379. package/dist/shims/config.d.ts.map +0 -1
  380. package/dist/shims/constants.d.ts.map +0 -1
  381. package/dist/shims/document.d.ts.map +0 -1
  382. package/dist/shims/dynamic.d.ts.map +0 -1
  383. package/dist/shims/error-boundary.d.ts.map +0 -1
  384. package/dist/shims/error.d.ts.map +0 -1
  385. package/dist/shims/fetch-cache.d.ts.map +0 -1
  386. package/dist/shims/font-google-base.d.ts.map +0 -1
  387. package/dist/shims/font-google.d.ts.map +0 -1
  388. package/dist/shims/font-google.generated.d.ts.map +0 -1
  389. package/dist/shims/font-google.js.map +0 -1
  390. package/dist/shims/font-local.d.ts.map +0 -1
  391. package/dist/shims/form.d.ts.map +0 -1
  392. package/dist/shims/head-state.d.ts.map +0 -1
  393. package/dist/shims/head.d.ts.map +0 -1
  394. package/dist/shims/headers.d.ts.map +0 -1
  395. package/dist/shims/i18n-context.d.ts.map +0 -1
  396. package/dist/shims/i18n-state.d.ts.map +0 -1
  397. package/dist/shims/image-config.d.ts.map +0 -1
  398. package/dist/shims/image.d.ts.map +0 -1
  399. package/dist/shims/internal/api-utils.d.ts.map +0 -1
  400. package/dist/shims/internal/api-utils.js.map +0 -1
  401. package/dist/shims/internal/app-router-context.d.ts.map +0 -1
  402. package/dist/shims/internal/cookies.d.ts.map +0 -1
  403. package/dist/shims/internal/cookies.js.map +0 -1
  404. package/dist/shims/internal/parse-cookie-header.d.ts.map +0 -1
  405. package/dist/shims/internal/router-context.d.ts.map +0 -1
  406. package/dist/shims/internal/utils.d.ts.map +0 -1
  407. package/dist/shims/internal/work-unit-async-storage.d.ts.map +0 -1
  408. package/dist/shims/layout-segment-context.d.ts.map +0 -1
  409. package/dist/shims/legacy-image.d.ts.map +0 -1
  410. package/dist/shims/link.d.ts.map +0 -1
  411. package/dist/shims/metadata.d.ts.map +0 -1
  412. package/dist/shims/navigation-state.d.ts.map +0 -1
  413. package/dist/shims/navigation.d.ts.map +0 -1
  414. package/dist/shims/og.d.ts.map +0 -1
  415. package/dist/shims/og.js.map +0 -1
  416. package/dist/shims/readonly-url-search-params.d.ts.map +0 -1
  417. package/dist/shims/request-context.d.ts.map +0 -1
  418. package/dist/shims/request-state-types.d.ts.map +0 -1
  419. package/dist/shims/request-state-types.js.map +0 -1
  420. package/dist/shims/router-state.d.ts.map +0 -1
  421. package/dist/shims/router.d.ts.map +0 -1
  422. package/dist/shims/script.d.ts.map +0 -1
  423. package/dist/shims/server-only.d.ts.map +0 -1
  424. package/dist/shims/server-only.js.map +0 -1
  425. package/dist/shims/server.d.ts.map +0 -1
  426. package/dist/shims/unified-request-context.d.ts.map +0 -1
  427. package/dist/shims/url-safety.d.ts.map +0 -1
  428. package/dist/shims/url-utils.d.ts.map +0 -1
  429. package/dist/shims/web-vitals.d.ts.map +0 -1
  430. package/dist/utils/base-path.d.ts.map +0 -1
  431. package/dist/utils/domain-locale.d.ts.map +0 -1
  432. package/dist/utils/hash.d.ts.map +0 -1
  433. package/dist/utils/manifest-paths.d.ts.map +0 -1
  434. package/dist/utils/project.d.ts.map +0 -1
  435. package/dist/utils/query.d.ts.map +0 -1
package/dist/check.js CHANGED
@@ -1,595 +1,705 @@
1
- /**
2
- * vinext check — compatibility scanner for Next.js apps
3
- *
4
- * Scans an existing Next.js app and produces a compatibility report
5
- * showing what will work, what needs changes, and an overall score.
6
- */
7
1
  import { detectPackageManager } from "./utils/project.js";
8
2
  import fs from "node:fs";
9
3
  import path from "node:path";
10
- // ── Import support map ─────────────────────────────────────────────────────
4
+ //#region src/check.ts
5
+ /**
6
+ * vinext check — compatibility scanner for Next.js apps
7
+ *
8
+ * Scans an existing Next.js app and produces a compatibility report
9
+ * showing what will work, what needs changes, and an overall score.
10
+ */
11
11
  const IMPORT_SUPPORT = {
12
- next: { status: "supported", detail: "type-only exports (Metadata, NextPage, etc.)" },
13
- "next/link": { status: "supported" },
14
- "next/image": { status: "supported", detail: "uses @unpic/react (no local optimization yet)" },
15
- "next/router": { status: "supported" },
16
- "next/navigation": { status: "supported" },
17
- "next/headers": { status: "supported" },
18
- "next/server": { status: "supported", detail: "NextRequest/NextResponse shimmed" },
19
- "next/cache": {
20
- status: "supported",
21
- detail: "revalidateTag, revalidatePath, unstable_cache, cacheLife, cacheTag",
22
- },
23
- "next/dynamic": { status: "supported" },
24
- "next/head": { status: "supported" },
25
- "next/script": { status: "supported" },
26
- "next/font/google": {
27
- status: "partial",
28
- detail: "fonts loaded from CDN, not self-hosted at build time",
29
- },
30
- "next/font/local": {
31
- status: "supported",
32
- detail: "className and variable modes both work; no build-time subsetting",
33
- },
34
- "next/og": { status: "supported", detail: "ImageResponse via @vercel/og" },
35
- "next/config": { status: "supported" },
36
- "next/amp": { status: "unsupported", detail: "AMP is not supported" },
37
- "next/document": { status: "supported", detail: "custom _document.tsx" },
38
- "next/app": { status: "supported", detail: "custom _app.tsx" },
39
- "next/error": { status: "supported" },
40
- "next/third-parties/google": {
41
- status: "unsupported",
42
- detail: "third-party script optimization not implemented",
43
- },
44
- "server-only": { status: "supported" },
45
- "client-only": { status: "supported" },
12
+ next: {
13
+ status: "supported",
14
+ detail: "type-only exports (Metadata, NextPage, etc.)"
15
+ },
16
+ "next/link": { status: "supported" },
17
+ "next/image": {
18
+ status: "supported",
19
+ detail: "uses @unpic/react (no local optimization yet)"
20
+ },
21
+ "next/legacy/image": {
22
+ status: "supported",
23
+ detail: "pre-Next.js 13 Image API with layout prop; translated to modern Image"
24
+ },
25
+ "next/router": { status: "supported" },
26
+ "next/compat/router": {
27
+ status: "supported",
28
+ detail: "useRouter() returns null in App Router, router object in Pages Router"
29
+ },
30
+ "next/navigation": { status: "supported" },
31
+ "next/headers": { status: "supported" },
32
+ "next/server": {
33
+ status: "supported",
34
+ detail: "NextRequest/NextResponse shimmed"
35
+ },
36
+ "next/cache": {
37
+ status: "supported",
38
+ detail: "revalidateTag, revalidatePath, unstable_cache, cacheLife, cacheTag"
39
+ },
40
+ "next/dynamic": { status: "supported" },
41
+ "next/head": { status: "supported" },
42
+ "next/script": { status: "supported" },
43
+ "next/font/google": {
44
+ status: "partial",
45
+ detail: "fonts loaded from CDN, not self-hosted at build time"
46
+ },
47
+ "next/font/local": {
48
+ status: "supported",
49
+ detail: "className and variable modes both work; no build-time subsetting"
50
+ },
51
+ "next/og": {
52
+ status: "supported",
53
+ detail: "ImageResponse via @vercel/og"
54
+ },
55
+ "next/config": { status: "supported" },
56
+ "next/amp": {
57
+ status: "unsupported",
58
+ detail: "AMP is not supported"
59
+ },
60
+ "next/document": {
61
+ status: "supported",
62
+ detail: "custom _document.tsx"
63
+ },
64
+ "next/app": {
65
+ status: "supported",
66
+ detail: "custom _app.tsx"
67
+ },
68
+ "next/error": { status: "supported" },
69
+ "next/form": {
70
+ status: "supported",
71
+ detail: "Form component with client-side navigation"
72
+ },
73
+ "next/web-vitals": {
74
+ status: "supported",
75
+ detail: "reportWebVitals helper"
76
+ },
77
+ "next/constants": {
78
+ status: "supported",
79
+ detail: "PHASE_* constants"
80
+ },
81
+ "next/third-parties/google": {
82
+ status: "unsupported",
83
+ detail: "third-party script optimization not implemented"
84
+ },
85
+ "server-only": { status: "supported" },
86
+ "client-only": { status: "supported" },
87
+ "next/dist/shared/lib/router-context.shared-runtime": {
88
+ status: "supported",
89
+ detail: "RouterContext for Pages Router; used by testing utilities and older libraries"
90
+ },
91
+ "next/dist/shared/lib/app-router-context.shared-runtime": {
92
+ status: "supported",
93
+ detail: "AppRouterContext and layout contexts; used by testing utilities and UI libraries"
94
+ },
95
+ "next/dist/shared/lib/app-router-context": {
96
+ status: "supported",
97
+ detail: "AppRouterContext and layout contexts; used by testing utilities and UI libraries"
98
+ },
99
+ "next/dist/shared/lib/utils": {
100
+ status: "supported",
101
+ detail: "execOnce, getLocationOrigin and other shared utilities"
102
+ },
103
+ "next/dist/server/api-utils": {
104
+ status: "supported",
105
+ detail: "NextApiRequestCookies and Pages Router API route utilities"
106
+ },
107
+ "next/dist/server/web/spec-extension/cookies": {
108
+ status: "supported",
109
+ detail: "RequestCookies / ResponseCookies — shimmed via @edge-runtime/cookies"
110
+ },
111
+ "next/dist/compiled/@edge-runtime/cookies": {
112
+ status: "supported",
113
+ detail: "RequestCookies / ResponseCookies — shimmed via @edge-runtime/cookies"
114
+ },
115
+ "next/dist/server/app-render/work-unit-async-storage.external": {
116
+ status: "supported",
117
+ detail: "request-scoped AsyncLocalStorage for App Router server components"
118
+ },
119
+ "next/dist/client/components/work-unit-async-storage.external": {
120
+ status: "supported",
121
+ detail: "request-scoped AsyncLocalStorage for App Router server components"
122
+ },
123
+ "next/dist/client/components/request-async-storage.external": {
124
+ status: "supported",
125
+ detail: "request-scoped AsyncLocalStorage (legacy path alias)"
126
+ },
127
+ "next/dist/client/components/request-async-storage": {
128
+ status: "supported",
129
+ detail: "request-scoped AsyncLocalStorage (legacy path alias)"
130
+ },
131
+ "next/dist/client/components/navigation": {
132
+ status: "supported",
133
+ detail: "internal navigation module; re-exports next/navigation"
134
+ },
135
+ "next/dist/server/config-shared": {
136
+ status: "supported",
137
+ detail: "shared config utilities; re-exports next/dist/shared/lib/utils"
138
+ }
46
139
  };
47
- // ── Config support map ─────────────────────────────────────────────────────
48
140
  const CONFIG_SUPPORT = {
49
- basePath: { status: "supported" },
50
- trailingSlash: { status: "supported" },
51
- redirects: { status: "supported" },
52
- rewrites: { status: "supported" },
53
- headers: { status: "supported" },
54
- i18n: { status: "supported", detail: "path-prefix routing; domain routing for Pages Router" },
55
- env: { status: "supported" },
56
- images: { status: "partial", detail: "remotePatterns validated, no local optimization" },
57
- allowedDevOrigins: { status: "supported", detail: "dev server cross-origin allowlist" },
58
- output: { status: "supported", detail: "'export' and 'standalone' modes" },
59
- transpilePackages: { status: "supported", detail: "Vite handles this natively" },
60
- webpack: {
61
- status: "unsupported",
62
- detail: "Vite replaces webpack — custom webpack configs need migration",
63
- },
64
- "experimental.ppr": { status: "unsupported", detail: "partial prerendering not yet implemented" },
65
- "experimental.typedRoutes": { status: "unsupported", detail: "typed routes not implemented" },
66
- "experimental.serverActions": {
67
- status: "supported",
68
- detail: "server actions via 'use server' directive",
69
- },
70
- "i18n.domains": {
71
- status: "partial",
72
- detail: "supported for Pages Router; App Router unchanged",
73
- },
74
- reactStrictMode: { status: "supported", detail: "always enabled" },
75
- poweredByHeader: {
76
- status: "supported",
77
- detail: "not sent (matching Next.js default when disabled)",
78
- },
141
+ basePath: { status: "supported" },
142
+ trailingSlash: { status: "supported" },
143
+ redirects: { status: "supported" },
144
+ rewrites: { status: "supported" },
145
+ headers: { status: "supported" },
146
+ i18n: {
147
+ status: "supported",
148
+ detail: "path-prefix routing; domain routing for Pages Router"
149
+ },
150
+ env: { status: "supported" },
151
+ images: {
152
+ status: "partial",
153
+ detail: "remotePatterns validated, no local optimization"
154
+ },
155
+ allowedDevOrigins: {
156
+ status: "supported",
157
+ detail: "dev server cross-origin allowlist"
158
+ },
159
+ output: {
160
+ status: "supported",
161
+ detail: "'export' and 'standalone' modes"
162
+ },
163
+ transpilePackages: {
164
+ status: "supported",
165
+ detail: "Vite handles this natively"
166
+ },
167
+ webpack: {
168
+ status: "unsupported",
169
+ detail: "Vite replaces webpack custom webpack configs need migration"
170
+ },
171
+ "experimental.ppr": {
172
+ status: "unsupported",
173
+ detail: "partial prerendering not yet implemented"
174
+ },
175
+ "experimental.typedRoutes": {
176
+ status: "unsupported",
177
+ detail: "typed routes not implemented"
178
+ },
179
+ "experimental.serverActions": {
180
+ status: "supported",
181
+ detail: "server actions via 'use server' directive"
182
+ },
183
+ "i18n.domains": {
184
+ status: "partial",
185
+ detail: "supported for Pages Router; App Router unchanged"
186
+ },
187
+ reactStrictMode: {
188
+ status: "supported",
189
+ detail: "always enabled"
190
+ },
191
+ poweredByHeader: {
192
+ status: "supported",
193
+ detail: "not sent (matching Next.js default when disabled)"
194
+ }
79
195
  };
80
- // ── Library support map ────────────────────────────────────────────────────
81
196
  const LIBRARY_SUPPORT = {
82
- "next-themes": { status: "supported" },
83
- nuqs: { status: "supported" },
84
- "next-view-transitions": { status: "supported" },
85
- "@vercel/analytics": { status: "supported", detail: "analytics script injected client-side" },
86
- "next-intl": {
87
- status: "supported",
88
- detail: "auto-detected from i18n/request.{ts,tsx,js,jsx}; createNextIntlPlugin wrapper not needed",
89
- },
90
- "@clerk/nextjs": {
91
- status: "unsupported",
92
- detail: "deep Next.js middleware integration not compatible",
93
- },
94
- "@auth/nextjs": {
95
- status: "unsupported",
96
- detail: "relies on Next.js internal auth handlers; consider migrating to better-auth",
97
- },
98
- "next-auth": {
99
- status: "unsupported",
100
- detail: "relies on Next.js API route internals; consider migrating to better-auth (see https://authjs.dev/getting-started/migrate-to-better-auth)",
101
- },
102
- "better-auth": {
103
- status: "supported",
104
- detail: "uses only public next/* APIs (headers, cookies, NextRequest/NextResponse)",
105
- },
106
- "@sentry/nextjs": {
107
- status: "partial",
108
- detail: "client-side works, server integration needs manual setup",
109
- },
110
- "@t3-oss/env-nextjs": { status: "supported" },
111
- tailwindcss: { status: "supported" },
112
- "styled-components": { status: "supported", detail: "SSR via useServerInsertedHTML" },
113
- "@emotion/react": { status: "supported", detail: "SSR via useServerInsertedHTML" },
114
- "lucide-react": { status: "supported" },
115
- "framer-motion": { status: "supported" },
116
- "@radix-ui/react-dialog": { status: "supported" },
117
- "shadcn-ui": { status: "supported" },
118
- zod: { status: "supported" },
119
- "react-hook-form": { status: "supported" },
120
- prisma: { status: "supported", detail: "works on Cloudflare Workers with Prisma Accelerate" },
121
- drizzle: { status: "supported", detail: "works with D1 on Cloudflare Workers" },
197
+ "next-themes": { status: "supported" },
198
+ nuqs: { status: "supported" },
199
+ "next-view-transitions": { status: "supported" },
200
+ "@vercel/analytics": {
201
+ status: "supported",
202
+ detail: "analytics script injected client-side"
203
+ },
204
+ "next-intl": {
205
+ status: "supported",
206
+ detail: "auto-detected from i18n/request.{ts,tsx,js,jsx}; createNextIntlPlugin wrapper not needed"
207
+ },
208
+ "@clerk/nextjs": {
209
+ status: "unsupported",
210
+ detail: "deep Next.js middleware integration not compatible"
211
+ },
212
+ "@auth/nextjs": {
213
+ status: "unsupported",
214
+ detail: "relies on Next.js internal auth handlers; consider migrating to better-auth"
215
+ },
216
+ "next-auth": {
217
+ status: "unsupported",
218
+ detail: "relies on Next.js API route internals; consider migrating to better-auth (see https://authjs.dev/getting-started/migrate-to-better-auth)"
219
+ },
220
+ "better-auth": {
221
+ status: "supported",
222
+ detail: "uses only public next/* APIs (headers, cookies, NextRequest/NextResponse)"
223
+ },
224
+ "@sentry/nextjs": {
225
+ status: "partial",
226
+ detail: "client-side works, server integration needs manual setup"
227
+ },
228
+ "@t3-oss/env-nextjs": { status: "supported" },
229
+ tailwindcss: { status: "supported" },
230
+ "styled-components": {
231
+ status: "supported",
232
+ detail: "SSR via useServerInsertedHTML"
233
+ },
234
+ "@emotion/react": {
235
+ status: "supported",
236
+ detail: "SSR via useServerInsertedHTML"
237
+ },
238
+ "lucide-react": { status: "supported" },
239
+ "framer-motion": { status: "supported" },
240
+ "@radix-ui/react-dialog": { status: "supported" },
241
+ "shadcn-ui": { status: "supported" },
242
+ zod: { status: "supported" },
243
+ "react-hook-form": { status: "supported" },
244
+ prisma: {
245
+ status: "supported",
246
+ detail: "works on Cloudflare Workers with Prisma Accelerate"
247
+ },
248
+ drizzle: {
249
+ status: "supported",
250
+ detail: "works with D1 on Cloudflare Workers"
251
+ }
122
252
  };
123
- // ── Scanning functions ─────────────────────────────────────────────────────
124
253
  /**
125
- * Recursively find all source files in a directory.
126
- */
127
- function findSourceFiles(dir, extensions = [".ts", ".tsx", ".js", ".jsx", ".mjs"]) {
128
- const results = [];
129
- if (!fs.existsSync(dir))
130
- return results;
131
- const entries = fs.readdirSync(dir, { withFileTypes: true });
132
- for (const entry of entries) {
133
- const fullPath = path.join(dir, entry.name);
134
- if (entry.isDirectory()) {
135
- if (entry.name === "node_modules" ||
136
- entry.name === ".next" ||
137
- entry.name === "dist" ||
138
- entry.name === ".git")
139
- continue;
140
- results.push(...findSourceFiles(fullPath, extensions));
141
- }
142
- else if (extensions.some((ext) => entry.name.endsWith(ext))) {
143
- results.push(fullPath);
144
- }
145
- }
146
- return results;
254
+ * Recursively find all source files in a directory.
255
+ */
256
+ function findSourceFiles(dir, extensions = [
257
+ ".ts",
258
+ ".tsx",
259
+ ".js",
260
+ ".jsx",
261
+ ".mjs"
262
+ ]) {
263
+ const results = [];
264
+ if (!fs.existsSync(dir)) return results;
265
+ const entries = fs.readdirSync(dir, { withFileTypes: true });
266
+ for (const entry of entries) {
267
+ const fullPath = path.join(dir, entry.name);
268
+ if (entry.isDirectory()) {
269
+ if (entry.name === "node_modules" || entry.name === ".next" || entry.name === "dist" || entry.name === ".git") continue;
270
+ results.push(...findSourceFiles(fullPath, extensions));
271
+ } else if (extensions.some((ext) => entry.name.endsWith(ext))) results.push(fullPath);
272
+ }
273
+ return results;
147
274
  }
148
275
  /**
149
- * Scan source files for `import ... from 'next/...'` statements.
150
- */
151
- export function scanImports(root) {
152
- const files = findSourceFiles(root);
153
- const importUsage = new Map();
154
- const importRegex = /(?:import\s+(?:[\w{},\s*]+\s+from\s+)?|require\s*\()['"]([^'"]+)['"]\)?/g;
155
- // Skip `import type` and `import { type ... }` — they're erased at compile time
156
- const typeOnlyImportRegex = /import\s+type\s+/;
157
- for (const file of files) {
158
- const content = fs.readFileSync(file, "utf-8");
159
- let match;
160
- while ((match = importRegex.exec(content)) !== null) {
161
- const mod = match[1];
162
- // Skip type-only imports (no runtime effect)
163
- const lineStart = content.lastIndexOf("\n", match.index) + 1;
164
- const line = content.slice(lineStart, match.index + match[0].length);
165
- if (typeOnlyImportRegex.test(line))
166
- continue;
167
- // Only track next/* imports and server-only/client-only
168
- if (mod.startsWith("next/") ||
169
- mod === "next" ||
170
- mod === "server-only" ||
171
- mod === "client-only") {
172
- // Normalize: next/font/google -> next/font/google
173
- const normalized = mod === "next" ? "next" : mod;
174
- if (!importUsage.has(normalized))
175
- importUsage.set(normalized, []);
176
- const relFile = path.relative(root, file);
177
- const usedInFiles = importUsage.get(normalized) ?? [];
178
- if (!usedInFiles.includes(relFile)) {
179
- usedInFiles.push(relFile);
180
- }
181
- }
182
- }
183
- }
184
- const items = [];
185
- for (const [mod, usedFiles] of importUsage) {
186
- const support = IMPORT_SUPPORT[mod.startsWith("next/") && mod.endsWith(".js") ? mod.replace(/\.js$/, "") : mod];
187
- if (support) {
188
- items.push({
189
- name: mod,
190
- status: support.status,
191
- detail: support.detail,
192
- files: usedFiles,
193
- });
194
- }
195
- else {
196
- items.push({
197
- name: mod,
198
- status: "unsupported",
199
- detail: "not recognized by vinext",
200
- files: usedFiles,
201
- });
202
- }
203
- }
204
- // Sort: unsupported first, then partial, then supported
205
- items.sort((a, b) => {
206
- const order = { unsupported: 0, partial: 1, supported: 2 };
207
- return order[a.status] - order[b.status];
208
- });
209
- return items;
276
+ * Scan source files for `import ... from 'next/...'` statements.
277
+ */
278
+ function scanImports(root) {
279
+ const files = findSourceFiles(root);
280
+ const importUsage = /* @__PURE__ */ new Map();
281
+ const importRegex = /(?:import\s+(?:[\w{},\s*]+\s+from\s+)?|require\s*\()['"]([^'"]+)['"]\)?/g;
282
+ const typeOnlyImportRegex = /import\s+type\s+/;
283
+ for (const file of files) {
284
+ const content = fs.readFileSync(file, "utf-8");
285
+ let match;
286
+ while ((match = importRegex.exec(content)) !== null) {
287
+ const mod = match[1];
288
+ const lineStart = content.lastIndexOf("\n", match.index) + 1;
289
+ const line = content.slice(lineStart, match.index + match[0].length);
290
+ if (typeOnlyImportRegex.test(line)) continue;
291
+ if (mod.startsWith("next/") || mod === "next" || mod === "server-only" || mod === "client-only") {
292
+ const normalized = mod === "next" ? "next" : mod;
293
+ if (!importUsage.has(normalized)) importUsage.set(normalized, []);
294
+ const relFile = path.relative(root, file);
295
+ const usedInFiles = importUsage.get(normalized) ?? [];
296
+ if (!usedInFiles.includes(relFile)) usedInFiles.push(relFile);
297
+ }
298
+ }
299
+ }
300
+ const items = [];
301
+ for (const [mod, usedFiles] of importUsage) {
302
+ const support = IMPORT_SUPPORT[mod.startsWith("next/") && mod.endsWith(".js") ? mod.replace(/\.js$/, "") : mod];
303
+ if (support) items.push({
304
+ name: mod,
305
+ status: support.status,
306
+ detail: support.detail,
307
+ files: usedFiles
308
+ });
309
+ else items.push({
310
+ name: mod,
311
+ status: "unsupported",
312
+ detail: "not recognized by vinext",
313
+ files: usedFiles
314
+ });
315
+ }
316
+ items.sort((a, b) => {
317
+ const order = {
318
+ unsupported: 0,
319
+ partial: 1,
320
+ supported: 2
321
+ };
322
+ return order[a.status] - order[b.status];
323
+ });
324
+ return items;
210
325
  }
211
326
  /**
212
- * Analyze next.config.js/mjs/ts for supported and unsupported options.
213
- */
214
- export function analyzeConfig(root) {
215
- const configFiles = ["next.config.ts", "next.config.mjs", "next.config.js", "next.config.cjs"];
216
- let configPath = null;
217
- for (const f of configFiles) {
218
- const p = path.join(root, f);
219
- if (fs.existsSync(p)) {
220
- configPath = p;
221
- break;
222
- }
223
- }
224
- if (!configPath) {
225
- return [
226
- {
227
- name: "next.config",
228
- status: "supported",
229
- detail: "no config file found (defaults are fine)",
230
- },
231
- ];
232
- }
233
- const content = fs.readFileSync(configPath, "utf-8");
234
- const items = [];
235
- // Check for known config options by searching for property names in the config file
236
- const configOptions = [
237
- "basePath",
238
- "trailingSlash",
239
- "redirects",
240
- "rewrites",
241
- "headers",
242
- "i18n",
243
- "env",
244
- "images",
245
- "allowedDevOrigins",
246
- "output",
247
- "transpilePackages",
248
- "webpack",
249
- "reactStrictMode",
250
- "poweredByHeader",
251
- ];
252
- for (const opt of configOptions) {
253
- // Simple heuristic: check if the option name appears as a property in the config
254
- const regex = new RegExp(`\\b${opt}\\b`);
255
- if (regex.test(content)) {
256
- const support = CONFIG_SUPPORT[opt];
257
- if (support) {
258
- items.push({ name: opt, status: support.status, detail: support.detail });
259
- }
260
- else {
261
- items.push({ name: opt, status: "unsupported", detail: "not recognized" });
262
- }
263
- }
264
- }
265
- // Check for experimental options
266
- if (/experimental\s*[:=]\s*\{/.test(content)) {
267
- if (/\bppr\b/.test(content)) {
268
- items.push({ name: "experimental.ppr", ...CONFIG_SUPPORT["experimental.ppr"] });
269
- }
270
- if (/\btypedRoutes\b/.test(content)) {
271
- items.push({
272
- name: "experimental.typedRoutes",
273
- ...CONFIG_SUPPORT["experimental.typedRoutes"],
274
- });
275
- }
276
- if (/\bserverActions\b/.test(content)) {
277
- items.push({
278
- name: "experimental.serverActions",
279
- ...CONFIG_SUPPORT["experimental.serverActions"],
280
- });
281
- }
282
- }
283
- // Check for i18n.domains
284
- if (/domains\s*:/.test(content) && /i18n/.test(content)) {
285
- items.push({ name: "i18n.domains", ...CONFIG_SUPPORT["i18n.domains"] });
286
- }
287
- // Sort: unsupported first
288
- items.sort((a, b) => {
289
- const order = { unsupported: 0, partial: 1, supported: 2 };
290
- return order[a.status] - order[b.status];
291
- });
292
- return items;
327
+ * Analyze next.config.js/mjs/ts for supported and unsupported options.
328
+ */
329
+ function analyzeConfig(root) {
330
+ const configFiles = [
331
+ "next.config.ts",
332
+ "next.config.mjs",
333
+ "next.config.js",
334
+ "next.config.cjs"
335
+ ];
336
+ let configPath = null;
337
+ for (const f of configFiles) {
338
+ const p = path.join(root, f);
339
+ if (fs.existsSync(p)) {
340
+ configPath = p;
341
+ break;
342
+ }
343
+ }
344
+ if (!configPath) return [{
345
+ name: "next.config",
346
+ status: "supported",
347
+ detail: "no config file found (defaults are fine)"
348
+ }];
349
+ const content = fs.readFileSync(configPath, "utf-8");
350
+ const items = [];
351
+ for (const opt of [
352
+ "basePath",
353
+ "trailingSlash",
354
+ "redirects",
355
+ "rewrites",
356
+ "headers",
357
+ "i18n",
358
+ "env",
359
+ "images",
360
+ "allowedDevOrigins",
361
+ "output",
362
+ "transpilePackages",
363
+ "webpack",
364
+ "reactStrictMode",
365
+ "poweredByHeader"
366
+ ]) if (new RegExp(`\\b${opt}\\b`).test(content)) {
367
+ const support = CONFIG_SUPPORT[opt];
368
+ if (support) items.push({
369
+ name: opt,
370
+ status: support.status,
371
+ detail: support.detail
372
+ });
373
+ else items.push({
374
+ name: opt,
375
+ status: "unsupported",
376
+ detail: "not recognized"
377
+ });
378
+ }
379
+ if (/experimental\s*[:=]\s*\{/.test(content)) {
380
+ if (/\bppr\b/.test(content)) items.push({
381
+ name: "experimental.ppr",
382
+ ...CONFIG_SUPPORT["experimental.ppr"]
383
+ });
384
+ if (/\btypedRoutes\b/.test(content)) items.push({
385
+ name: "experimental.typedRoutes",
386
+ ...CONFIG_SUPPORT["experimental.typedRoutes"]
387
+ });
388
+ if (/\bserverActions\b/.test(content)) items.push({
389
+ name: "experimental.serverActions",
390
+ ...CONFIG_SUPPORT["experimental.serverActions"]
391
+ });
392
+ }
393
+ if (/domains\s*:/.test(content) && /i18n/.test(content)) items.push({
394
+ name: "i18n.domains",
395
+ ...CONFIG_SUPPORT["i18n.domains"]
396
+ });
397
+ items.sort((a, b) => {
398
+ const order = {
399
+ unsupported: 0,
400
+ partial: 1,
401
+ supported: 2
402
+ };
403
+ return order[a.status] - order[b.status];
404
+ });
405
+ return items;
293
406
  }
294
407
  /**
295
- * Check package.json dependencies for known libraries.
296
- */
297
- export function checkLibraries(root) {
298
- const pkgPath = path.join(root, "package.json");
299
- if (!fs.existsSync(pkgPath))
300
- return [];
301
- const pkg = JSON.parse(fs.readFileSync(pkgPath, "utf-8"));
302
- const allDeps = { ...pkg.dependencies, ...pkg.devDependencies };
303
- const items = [];
304
- for (const [lib, support] of Object.entries(LIBRARY_SUPPORT)) {
305
- if (allDeps[lib]) {
306
- items.push({
307
- name: lib,
308
- status: support.status,
309
- detail: support.detail,
310
- });
311
- }
312
- }
313
- // Sort: unsupported first
314
- items.sort((a, b) => {
315
- const order = { unsupported: 0, partial: 1, supported: 2 };
316
- return order[a.status] - order[b.status];
317
- });
318
- return items;
408
+ * Check package.json dependencies for known libraries.
409
+ */
410
+ function checkLibraries(root) {
411
+ const pkgPath = path.join(root, "package.json");
412
+ if (!fs.existsSync(pkgPath)) return [];
413
+ const pkg = JSON.parse(fs.readFileSync(pkgPath, "utf-8"));
414
+ const allDeps = {
415
+ ...pkg.dependencies,
416
+ ...pkg.devDependencies
417
+ };
418
+ const items = [];
419
+ for (const [lib, support] of Object.entries(LIBRARY_SUPPORT)) if (allDeps[lib]) items.push({
420
+ name: lib,
421
+ status: support.status,
422
+ detail: support.detail
423
+ });
424
+ items.sort((a, b) => {
425
+ const order = {
426
+ unsupported: 0,
427
+ partial: 1,
428
+ supported: 2
429
+ };
430
+ return order[a.status] - order[b.status];
431
+ });
432
+ return items;
319
433
  }
320
434
  /**
321
- * Check file conventions (pages, app directory, middleware, etc.)
322
- */
323
- export function checkConventions(root) {
324
- const items = [];
325
- // Check for pages/ and app/ at root level, then fall back to src/
326
- const pagesDir = fs.existsSync(path.join(root, "pages"))
327
- ? path.join(root, "pages")
328
- : fs.existsSync(path.join(root, "src", "pages"))
329
- ? path.join(root, "src", "pages")
330
- : null;
331
- const appDirPath = fs.existsSync(path.join(root, "app"))
332
- ? path.join(root, "app")
333
- : fs.existsSync(path.join(root, "src", "app"))
334
- ? path.join(root, "src", "app")
335
- : null;
336
- const hasPages = pagesDir !== null;
337
- const hasApp = appDirPath !== null;
338
- const hasProxy = fs.existsSync(path.join(root, "proxy.ts")) || fs.existsSync(path.join(root, "proxy.js"));
339
- const hasMiddleware = fs.existsSync(path.join(root, "middleware.ts")) ||
340
- fs.existsSync(path.join(root, "middleware.js"));
341
- if (pagesDir !== null) {
342
- const isSrc = pagesDir.includes(path.join("src", "pages"));
343
- items.push({
344
- name: isSrc ? "Pages Router (src/pages/)" : "Pages Router (pages/)",
345
- status: "supported",
346
- });
347
- // Count pages
348
- const pageFiles = findSourceFiles(pagesDir);
349
- const pages = pageFiles.filter((f) => !f.includes("/api/") &&
350
- !f.includes("_app") &&
351
- !f.includes("_document") &&
352
- !f.includes("_error"));
353
- const apiRoutes = pageFiles.filter((f) => f.includes("/api/"));
354
- items.push({ name: `${pages.length} page(s)`, status: "supported" });
355
- if (apiRoutes.length) {
356
- items.push({ name: `${apiRoutes.length} API route(s)`, status: "supported" });
357
- }
358
- // Check for _app, _document
359
- if (pageFiles.some((f) => f.includes("_app"))) {
360
- items.push({ name: "Custom _app", status: "supported" });
361
- }
362
- if (pageFiles.some((f) => f.includes("_document"))) {
363
- items.push({ name: "Custom _document", status: "supported" });
364
- }
365
- }
366
- if (appDirPath !== null) {
367
- const isSrc = appDirPath.includes(path.join("src", "app"));
368
- items.push({
369
- name: isSrc ? "App Router (src/app/)" : "App Router (app/)",
370
- status: "supported",
371
- });
372
- const appFiles = findSourceFiles(appDirPath);
373
- const pages = appFiles.filter((f) => f.endsWith("page.tsx") ||
374
- f.endsWith("page.jsx") ||
375
- f.endsWith("page.ts") ||
376
- f.endsWith("page.js"));
377
- const layouts = appFiles.filter((f) => f.endsWith("layout.tsx") ||
378
- f.endsWith("layout.jsx") ||
379
- f.endsWith("layout.ts") ||
380
- f.endsWith("layout.js"));
381
- const routes = appFiles.filter((f) => f.endsWith("route.tsx") || f.endsWith("route.ts") || f.endsWith("route.js"));
382
- const loadings = appFiles.filter((f) => f.endsWith("loading.tsx") || f.endsWith("loading.jsx"));
383
- const errors = appFiles.filter((f) => f.endsWith("error.tsx") || f.endsWith("error.jsx"));
384
- const notFounds = appFiles.filter((f) => f.endsWith("not-found.tsx") || f.endsWith("not-found.jsx"));
385
- items.push({ name: `${pages.length} page(s)`, status: "supported" });
386
- if (layouts.length)
387
- items.push({ name: `${layouts.length} layout(s)`, status: "supported" });
388
- if (routes.length)
389
- items.push({ name: `${routes.length} route handler(s)`, status: "supported" });
390
- if (loadings.length)
391
- items.push({ name: `${loadings.length} loading boundary(ies)`, status: "supported" });
392
- if (errors.length)
393
- items.push({ name: `${errors.length} error boundary(ies)`, status: "supported" });
394
- if (notFounds.length)
395
- items.push({ name: `${notFounds.length} not-found page(s)`, status: "supported" });
396
- }
397
- if (hasProxy) {
398
- items.push({ name: "proxy.ts (Next.js 16)", status: "supported" });
399
- }
400
- else if (hasMiddleware) {
401
- items.push({ name: "middleware.ts (deprecated in Next.js 16)", status: "supported" });
402
- }
403
- if (!hasPages && !hasApp) {
404
- items.push({
405
- name: "No pages/ or app/ directory found",
406
- status: "unsupported",
407
- detail: "vinext requires a pages/ or app/ directory",
408
- });
409
- }
410
- // Check for "type": "module" in package.json
411
- const pkgPath = path.join(root, "package.json");
412
- if (fs.existsSync(pkgPath)) {
413
- const pkg = JSON.parse(fs.readFileSync(pkgPath, "utf-8"));
414
- if (pkg.type !== "module") {
415
- items.push({
416
- name: 'Missing "type": "module" in package.json',
417
- status: "unsupported",
418
- detail: "required for Vite — vinext init will add it automatically",
419
- });
420
- }
421
- }
422
- // Scan for ViewTransition import from react
423
- const allSourceFiles = findSourceFiles(root);
424
- const viewTransitionRegex = /import\s+\{[^}]*\bViewTransition\b[^}]*\}\s+from\s+['"]react['"]/;
425
- const viewTransitionFiles = [];
426
- for (const file of allSourceFiles) {
427
- const content = fs.readFileSync(file, "utf-8");
428
- if (viewTransitionRegex.test(content)) {
429
- viewTransitionFiles.push(path.relative(root, file));
430
- }
431
- }
432
- if (viewTransitionFiles.length > 0) {
433
- items.push({
434
- name: "ViewTransition (React canary API)",
435
- status: "partial",
436
- detail: "vinext auto-shims with a passthrough fallback, view transitions won't animate",
437
- files: viewTransitionFiles,
438
- });
439
- }
440
- // Check PostCSS config for string-form plugins
441
- const postcssConfigs = ["postcss.config.mjs", "postcss.config.js", "postcss.config.cjs"];
442
- for (const configFile of postcssConfigs) {
443
- const configPath = path.join(root, configFile);
444
- if (fs.existsSync(configPath)) {
445
- const content = fs.readFileSync(configPath, "utf-8");
446
- // Detect string-form plugins: plugins: ["..."] or plugins: ['...']
447
- const stringPluginRegex = /plugins\s*:\s*\[[\s\S]*?(['"][^'"]+['"])[\s\S]*?\]/;
448
- const match = stringPluginRegex.exec(content);
449
- if (match) {
450
- // Check it's not require() or import() form — just bare string literals in the array
451
- const pluginsBlock = match[0];
452
- // If plugins array contains string literals not wrapped in require()
453
- if (/plugins\s*:\s*\[[\s\n]*['"]/.test(pluginsBlock)) {
454
- items.push({
455
- name: `PostCSS string-form plugins (${configFile})`,
456
- status: "partial",
457
- detail: "string-form PostCSS plugins need resolution — vinext handles this automatically",
458
- });
459
- }
460
- }
461
- break; // Only check the first config file found
462
- }
463
- }
464
- return items;
435
+ * Check file conventions (pages, app directory, middleware, etc.)
436
+ */
437
+ function checkConventions(root) {
438
+ const items = [];
439
+ const pagesDir = fs.existsSync(path.join(root, "pages")) ? path.join(root, "pages") : fs.existsSync(path.join(root, "src", "pages")) ? path.join(root, "src", "pages") : null;
440
+ const appDirPath = fs.existsSync(path.join(root, "app")) ? path.join(root, "app") : fs.existsSync(path.join(root, "src", "app")) ? path.join(root, "src", "app") : null;
441
+ const hasPages = pagesDir !== null;
442
+ const hasApp = appDirPath !== null;
443
+ const hasProxy = fs.existsSync(path.join(root, "proxy.ts")) || fs.existsSync(path.join(root, "proxy.js"));
444
+ const hasMiddleware = fs.existsSync(path.join(root, "middleware.ts")) || fs.existsSync(path.join(root, "middleware.js"));
445
+ if (pagesDir !== null) {
446
+ const isSrc = pagesDir.includes(path.join("src", "pages"));
447
+ items.push({
448
+ name: isSrc ? "Pages Router (src/pages/)" : "Pages Router (pages/)",
449
+ status: "supported"
450
+ });
451
+ const pageFiles = findSourceFiles(pagesDir);
452
+ const pages = pageFiles.filter((f) => !f.includes("/api/") && !f.includes("_app") && !f.includes("_document") && !f.includes("_error"));
453
+ const apiRoutes = pageFiles.filter((f) => f.includes("/api/"));
454
+ items.push({
455
+ name: `${pages.length} page(s)`,
456
+ status: "supported"
457
+ });
458
+ if (apiRoutes.length) items.push({
459
+ name: `${apiRoutes.length} API route(s)`,
460
+ status: "supported"
461
+ });
462
+ if (pageFiles.some((f) => f.includes("_app"))) items.push({
463
+ name: "Custom _app",
464
+ status: "supported"
465
+ });
466
+ if (pageFiles.some((f) => f.includes("_document"))) items.push({
467
+ name: "Custom _document",
468
+ status: "supported"
469
+ });
470
+ }
471
+ if (appDirPath !== null) {
472
+ const isSrc = appDirPath.includes(path.join("src", "app"));
473
+ items.push({
474
+ name: isSrc ? "App Router (src/app/)" : "App Router (app/)",
475
+ status: "supported"
476
+ });
477
+ const appFiles = findSourceFiles(appDirPath);
478
+ const pages = appFiles.filter((f) => f.endsWith("page.tsx") || f.endsWith("page.jsx") || f.endsWith("page.ts") || f.endsWith("page.js"));
479
+ const layouts = appFiles.filter((f) => f.endsWith("layout.tsx") || f.endsWith("layout.jsx") || f.endsWith("layout.ts") || f.endsWith("layout.js"));
480
+ const routes = appFiles.filter((f) => f.endsWith("route.tsx") || f.endsWith("route.ts") || f.endsWith("route.js"));
481
+ const loadings = appFiles.filter((f) => f.endsWith("loading.tsx") || f.endsWith("loading.jsx"));
482
+ const errors = appFiles.filter((f) => f.endsWith("error.tsx") || f.endsWith("error.jsx"));
483
+ const notFounds = appFiles.filter((f) => f.endsWith("not-found.tsx") || f.endsWith("not-found.jsx"));
484
+ items.push({
485
+ name: `${pages.length} page(s)`,
486
+ status: "supported"
487
+ });
488
+ if (layouts.length) items.push({
489
+ name: `${layouts.length} layout(s)`,
490
+ status: "supported"
491
+ });
492
+ if (routes.length) items.push({
493
+ name: `${routes.length} route handler(s)`,
494
+ status: "supported"
495
+ });
496
+ if (loadings.length) items.push({
497
+ name: `${loadings.length} loading boundary(ies)`,
498
+ status: "supported"
499
+ });
500
+ if (errors.length) items.push({
501
+ name: `${errors.length} error boundary(ies)`,
502
+ status: "supported"
503
+ });
504
+ if (notFounds.length) items.push({
505
+ name: `${notFounds.length} not-found page(s)`,
506
+ status: "supported"
507
+ });
508
+ }
509
+ if (hasProxy) items.push({
510
+ name: "proxy.ts (Next.js 16)",
511
+ status: "supported"
512
+ });
513
+ else if (hasMiddleware) items.push({
514
+ name: "middleware.ts (deprecated in Next.js 16)",
515
+ status: "supported"
516
+ });
517
+ if (!hasPages && !hasApp) items.push({
518
+ name: "No pages/ or app/ directory found",
519
+ status: "unsupported",
520
+ detail: "vinext requires a pages/ or app/ directory"
521
+ });
522
+ const pkgPath = path.join(root, "package.json");
523
+ if (fs.existsSync(pkgPath)) {
524
+ if (JSON.parse(fs.readFileSync(pkgPath, "utf-8")).type !== "module") items.push({
525
+ name: "Missing \"type\": \"module\" in package.json",
526
+ status: "unsupported",
527
+ detail: "required for Vite — vinext init will add it automatically"
528
+ });
529
+ }
530
+ const allSourceFiles = findSourceFiles(root);
531
+ const viewTransitionRegex = /import\s+\{[^}]*\bViewTransition\b[^}]*\}\s+from\s+['"]react['"]/;
532
+ const cjsGlobalScanRegex = /\/\/[^\n]*|\/\*[\s\S]*?\*\/|`(?:[^`\\$]|\\.|\$(?!\{))*`|"(?:[^"\\]|\\.)*"|'(?:[^'\\]|\\.)*'|\b(__dirname|__filename)\b/g;
533
+ const viewTransitionFiles = [];
534
+ const cjsGlobalFiles = [];
535
+ for (const file of allSourceFiles) {
536
+ const content = fs.readFileSync(file, "utf-8");
537
+ const rel = path.relative(root, file);
538
+ if (viewTransitionRegex.test(content)) viewTransitionFiles.push(rel);
539
+ cjsGlobalScanRegex.lastIndex = 0;
540
+ let m;
541
+ while ((m = cjsGlobalScanRegex.exec(content)) !== null) if (m[1]) {
542
+ cjsGlobalFiles.push(rel);
543
+ break;
544
+ }
545
+ }
546
+ if (viewTransitionFiles.length > 0) items.push({
547
+ name: "ViewTransition (React canary API)",
548
+ status: "partial",
549
+ detail: "vinext auto-shims with a passthrough fallback, view transitions won't animate",
550
+ files: viewTransitionFiles
551
+ });
552
+ for (const configFile of [
553
+ "postcss.config.mjs",
554
+ "postcss.config.js",
555
+ "postcss.config.cjs"
556
+ ]) {
557
+ const configPath = path.join(root, configFile);
558
+ if (fs.existsSync(configPath)) {
559
+ const content = fs.readFileSync(configPath, "utf-8");
560
+ const match = /plugins\s*:\s*\[[\s\S]*?(['"][^'"]+['"])[\s\S]*?\]/.exec(content);
561
+ if (match) {
562
+ const pluginsBlock = match[0];
563
+ if (/plugins\s*:\s*\[[\s\n]*['"]/.test(pluginsBlock)) items.push({
564
+ name: `PostCSS string-form plugins (${configFile})`,
565
+ status: "partial",
566
+ detail: "string-form PostCSS plugins need resolution vinext handles this automatically"
567
+ });
568
+ }
569
+ break;
570
+ }
571
+ }
572
+ if (cjsGlobalFiles.length > 0) items.push({
573
+ name: "__dirname / __filename (CommonJS globals)",
574
+ status: "unsupported",
575
+ detail: "CJS globals unavailable in ESM use fileURLToPath(import.meta.url) / dirname(...), or import.meta.dirname / import.meta.filename (Node 22+)",
576
+ files: cjsGlobalFiles
577
+ });
578
+ return items;
465
579
  }
466
580
  /**
467
- * Run the full compatibility check.
468
- */
469
- export function runCheck(root) {
470
- const imports = scanImports(root);
471
- const config = analyzeConfig(root);
472
- const libraries = checkLibraries(root);
473
- const conventions = checkConventions(root);
474
- const allItems = [...imports, ...config, ...libraries, ...conventions];
475
- const supported = allItems.filter((i) => i.status === "supported").length;
476
- const partial = allItems.filter((i) => i.status === "partial").length;
477
- const unsupported = allItems.filter((i) => i.status === "unsupported").length;
478
- const total = allItems.length;
479
- // Score: supported = 1, partial = 0.5, unsupported = 0
480
- const score = total > 0 ? Math.round(((supported + partial * 0.5) / total) * 100) : 100;
481
- return {
482
- imports,
483
- config,
484
- libraries,
485
- conventions,
486
- summary: { supported, partial, unsupported, total, score },
487
- };
581
+ * Run the full compatibility check.
582
+ */
583
+ function runCheck(root) {
584
+ const imports = scanImports(root);
585
+ const config = analyzeConfig(root);
586
+ const libraries = checkLibraries(root);
587
+ const conventions = checkConventions(root);
588
+ const allItems = [
589
+ ...imports,
590
+ ...config,
591
+ ...libraries,
592
+ ...conventions
593
+ ];
594
+ const supported = allItems.filter((i) => i.status === "supported").length;
595
+ const partial = allItems.filter((i) => i.status === "partial").length;
596
+ const unsupported = allItems.filter((i) => i.status === "unsupported").length;
597
+ const total = allItems.length;
598
+ return {
599
+ imports,
600
+ config,
601
+ libraries,
602
+ conventions,
603
+ summary: {
604
+ supported,
605
+ partial,
606
+ unsupported,
607
+ total,
608
+ score: total > 0 ? Math.round((supported + partial * .5) / total * 100) : 100
609
+ }
610
+ };
488
611
  }
489
612
  /**
490
- * Format the check result as a colored terminal report.
491
- */
492
- export function formatReport(result, opts) {
493
- const lines = [];
494
- const statusIcon = (s) => s === "supported"
495
- ? "\x1b[32m✓\x1b[0m"
496
- : s === "partial"
497
- ? "\x1b[33m~\x1b[0m"
498
- : "\x1b[31m✗\x1b[0m";
499
- lines.push("");
500
- lines.push(" \x1b[1mvinext compatibility report\x1b[0m");
501
- lines.push(" " + "=".repeat(40));
502
- lines.push("");
503
- // Imports
504
- if (result.imports.length > 0) {
505
- const importSupported = result.imports.filter((i) => i.status === "supported").length;
506
- lines.push(` \x1b[1mImports\x1b[0m: ${importSupported}/${result.imports.length} fully supported`);
507
- for (const item of result.imports) {
508
- const suffix = item.detail ? ` \x1b[90m— ${item.detail}\x1b[0m` : "";
509
- const fileCount = item.files
510
- ? ` \x1b[90m(${item.files.length} file${item.files.length === 1 ? "" : "s"})\x1b[0m`
511
- : "";
512
- lines.push(` ${statusIcon(item.status)} ${item.name}${fileCount}${suffix}`);
513
- }
514
- lines.push("");
515
- }
516
- // Config
517
- if (result.config.length > 0) {
518
- const configSupported = result.config.filter((i) => i.status === "supported").length;
519
- lines.push(` \x1b[1mConfig\x1b[0m: ${configSupported}/${result.config.length} options supported`);
520
- for (const item of result.config) {
521
- const suffix = item.detail ? ` \x1b[90m— ${item.detail}\x1b[0m` : "";
522
- lines.push(` ${statusIcon(item.status)} ${item.name}${suffix}`);
523
- }
524
- lines.push("");
525
- }
526
- // Libraries
527
- if (result.libraries.length > 0) {
528
- const libSupported = result.libraries.filter((i) => i.status === "supported").length;
529
- lines.push(` \x1b[1mLibraries\x1b[0m: ${libSupported}/${result.libraries.length} compatible`);
530
- for (const item of result.libraries) {
531
- const suffix = item.detail ? ` \x1b[90m— ${item.detail}\x1b[0m` : "";
532
- lines.push(` ${statusIcon(item.status)} ${item.name}${suffix}`);
533
- }
534
- lines.push("");
535
- }
536
- // Conventions
537
- if (result.conventions.length > 0) {
538
- lines.push(` \x1b[1mProject structure\x1b[0m:`);
539
- for (const item of result.conventions) {
540
- const suffix = item.detail ? ` \x1b[90m— ${item.detail}\x1b[0m` : "";
541
- lines.push(` ${statusIcon(item.status)} ${item.name}${suffix}`);
542
- }
543
- lines.push("");
544
- }
545
- // Summary
546
- const { score, supported, partial, unsupported } = result.summary;
547
- const scoreColor = score >= 90 ? "\x1b[32m" : score >= 70 ? "\x1b[33m" : "\x1b[31m";
548
- lines.push(" " + "-".repeat(40));
549
- lines.push(` \x1b[1mOverall\x1b[0m: ${scoreColor}${score}% compatible\x1b[0m (${supported} supported, ${partial} partial, ${unsupported} issues)`);
550
- if (unsupported > 0) {
551
- lines.push("");
552
- lines.push(" \x1b[1mIssues to address:\x1b[0m");
553
- const allItems = [
554
- ...result.imports,
555
- ...result.config,
556
- ...result.libraries,
557
- ...result.conventions,
558
- ];
559
- for (const item of allItems) {
560
- if (item.status === "unsupported") {
561
- lines.push(` \x1b[31m✗\x1b[0m ${item.name}${item.detail ? ` — ${item.detail}` : ""}`);
562
- }
563
- }
564
- }
565
- if (result.summary.partial > 0) {
566
- lines.push("");
567
- lines.push(" \x1b[1mPartial support (may need attention):\x1b[0m");
568
- const allItems = [
569
- ...result.imports,
570
- ...result.config,
571
- ...result.libraries,
572
- ...result.conventions,
573
- ];
574
- for (const item of allItems) {
575
- if (item.status === "partial") {
576
- lines.push(` \x1b[33m~\x1b[0m ${item.name}${item.detail ? ` — ${item.detail}` : ""}`);
577
- }
578
- }
579
- }
580
- // Actionable next steps (skip when called from init — it prints its own summary)
581
- if (!opts?.calledFromInit) {
582
- lines.push("");
583
- lines.push(" \x1b[1mRecommended next steps:\x1b[0m");
584
- lines.push(` Run \x1b[36mvinext init\x1b[0m to set up your project automatically`);
585
- lines.push("");
586
- lines.push(" Or manually:");
587
- lines.push(` 1. Add \x1b[36m"type": "module"\x1b[0m to package.json`);
588
- lines.push(` 2. Install: \x1b[36m${detectPackageManager(process.cwd())} vinext vite @vitejs/plugin-rsc\x1b[0m`);
589
- lines.push(` 3. Create vite.config.ts (see docs)`);
590
- lines.push(` 4. Run: \x1b[36mnpx vite dev\x1b[0m`);
591
- }
592
- lines.push("");
593
- return lines.join("\n");
613
+ * Format the check result as a colored terminal report.
614
+ */
615
+ function formatReport(result, opts) {
616
+ const lines = [];
617
+ const hasAppRouter = result.conventions.some((item) => item.name === "App Router (app/)" || item.name === "App Router (src/app/)");
618
+ const statusIcon = (s) => s === "supported" ? "\x1B[32m✓\x1B[0m" : s === "partial" ? "\x1B[33m~\x1B[0m" : "\x1B[31m✗\x1B[0m";
619
+ lines.push("");
620
+ lines.push(" \x1B[1mvinext compatibility report\x1B[0m");
621
+ lines.push(" " + "=".repeat(40));
622
+ lines.push("");
623
+ if (result.imports.length > 0) {
624
+ const importSupported = result.imports.filter((i) => i.status === "supported").length;
625
+ lines.push(` \x1b[1mImports\x1b[0m: ${importSupported}/${result.imports.length} fully supported`);
626
+ for (const item of result.imports) {
627
+ const suffix = item.detail ? ` \x1b[90m— ${item.detail}\x1b[0m` : "";
628
+ const fileCount = item.files ? ` \x1b[90m(${item.files.length} file${item.files.length === 1 ? "" : "s"})\x1b[0m` : "";
629
+ lines.push(` ${statusIcon(item.status)} ${item.name}${fileCount}${suffix}`);
630
+ }
631
+ lines.push("");
632
+ }
633
+ if (result.config.length > 0) {
634
+ const configSupported = result.config.filter((i) => i.status === "supported").length;
635
+ lines.push(` \x1b[1mConfig\x1b[0m: ${configSupported}/${result.config.length} options supported`);
636
+ for (const item of result.config) {
637
+ const suffix = item.detail ? ` \x1b[90m— ${item.detail}\x1b[0m` : "";
638
+ lines.push(` ${statusIcon(item.status)} ${item.name}${suffix}`);
639
+ }
640
+ lines.push("");
641
+ }
642
+ if (result.libraries.length > 0) {
643
+ const libSupported = result.libraries.filter((i) => i.status === "supported").length;
644
+ lines.push(` \x1b[1mLibraries\x1b[0m: ${libSupported}/${result.libraries.length} compatible`);
645
+ for (const item of result.libraries) {
646
+ const suffix = item.detail ? ` \x1b[90m— ${item.detail}\x1b[0m` : "";
647
+ lines.push(` ${statusIcon(item.status)} ${item.name}${suffix}`);
648
+ }
649
+ lines.push("");
650
+ }
651
+ if (result.conventions.length > 0) {
652
+ lines.push(` \x1b[1mProject structure\x1b[0m:`);
653
+ for (const item of result.conventions) {
654
+ const suffix = item.detail ? ` \x1b[90m— ${item.detail}\x1b[0m` : "";
655
+ lines.push(` ${statusIcon(item.status)} ${item.name}${suffix}`);
656
+ }
657
+ lines.push("");
658
+ }
659
+ const { score, supported, partial, unsupported } = result.summary;
660
+ const scoreColor = score >= 90 ? "\x1B[32m" : score >= 70 ? "\x1B[33m" : "\x1B[31m";
661
+ lines.push(" " + "-".repeat(40));
662
+ lines.push(` \x1b[1mOverall\x1b[0m: ${scoreColor}${score}% compatible\x1b[0m (${supported} supported, ${partial} partial, ${unsupported} issues)`);
663
+ if (unsupported > 0) {
664
+ lines.push("");
665
+ lines.push(" \x1B[1mIssues to address:\x1B[0m");
666
+ const allItems = [
667
+ ...result.imports,
668
+ ...result.config,
669
+ ...result.libraries,
670
+ ...result.conventions
671
+ ];
672
+ for (const item of allItems) if (item.status === "unsupported") {
673
+ lines.push(` \x1b[31m✗\x1b[0m ${item.name}${item.detail ? ` ${item.detail}` : ""}`);
674
+ if (item.files && item.files.length > 0) for (const f of item.files) lines.push(` \x1b[90m${f}\x1b[0m`);
675
+ }
676
+ }
677
+ if (result.summary.partial > 0) {
678
+ lines.push("");
679
+ lines.push(" \x1B[1mPartial support (may need attention):\x1B[0m");
680
+ const allItems = [
681
+ ...result.imports,
682
+ ...result.config,
683
+ ...result.libraries,
684
+ ...result.conventions
685
+ ];
686
+ for (const item of allItems) if (item.status === "partial") lines.push(` \x1b[33m~\x1b[0m ${item.name}${item.detail ? ` — ${item.detail}` : ""}`);
687
+ }
688
+ if (!opts?.calledFromInit) {
689
+ lines.push("");
690
+ lines.push(" \x1B[1mRecommended next steps:\x1B[0m");
691
+ lines.push(` Run \x1b[36mvinext init\x1b[0m to set up your project automatically`);
692
+ lines.push("");
693
+ lines.push(" Or manually:");
694
+ lines.push(` 1. Add \x1b[36m"type": "module"\x1b[0m to package.json`);
695
+ lines.push(` 2. Install: \x1b[36m${detectPackageManager(process.cwd())} vinext vite @vitejs/plugin-react${hasAppRouter ? " @vitejs/plugin-rsc react-server-dom-webpack" : ""}\x1b[0m`);
696
+ lines.push(` 3. Create vite.config.ts (see docs)`);
697
+ lines.push(` 4. Run: \x1b[36mnpx vite dev\x1b[0m`);
698
+ }
699
+ lines.push("");
700
+ return lines.join("\n");
594
701
  }
702
+ //#endregion
703
+ export { analyzeConfig, checkConventions, checkLibraries, formatReport, runCheck, scanImports };
704
+
595
705
  //# sourceMappingURL=check.js.map