vinext 0.0.29 → 0.0.31

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