@hyperfrontend/project-scope 0.2.0 → 0.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (439) hide show
  1. package/CHANGELOG.md +13 -15
  2. package/README.md +3 -4
  3. package/_dependencies/@hyperfrontend/immutable-api-utils/built-in-copy/array/index.cjs.js +7 -0
  4. package/_dependencies/@hyperfrontend/immutable-api-utils/built-in-copy/array/index.esm.js +5 -0
  5. package/_dependencies/@hyperfrontend/immutable-api-utils/built-in-copy/console/index.cjs.js +13 -0
  6. package/_dependencies/@hyperfrontend/immutable-api-utils/built-in-copy/console/index.esm.js +8 -0
  7. package/_dependencies/@hyperfrontend/immutable-api-utils/built-in-copy/date/index.cjs.js +10 -0
  8. package/_dependencies/@hyperfrontend/immutable-api-utils/built-in-copy/date/index.esm.js +8 -0
  9. package/_dependencies/@hyperfrontend/immutable-api-utils/built-in-copy/error/index.cjs.js +6 -0
  10. package/_dependencies/@hyperfrontend/immutable-api-utils/built-in-copy/error/index.esm.js +5 -0
  11. package/_dependencies/@hyperfrontend/immutable-api-utils/built-in-copy/json/index.cjs.js +7 -0
  12. package/_dependencies/@hyperfrontend/immutable-api-utils/built-in-copy/json/index.esm.js +5 -0
  13. package/_dependencies/@hyperfrontend/immutable-api-utils/built-in-copy/map/index.cjs.js +6 -0
  14. package/_dependencies/@hyperfrontend/immutable-api-utils/built-in-copy/map/index.esm.js +5 -0
  15. package/_dependencies/@hyperfrontend/immutable-api-utils/built-in-copy/math/index.cjs.js +9 -0
  16. package/_dependencies/@hyperfrontend/immutable-api-utils/built-in-copy/math/index.esm.js +6 -0
  17. package/_dependencies/@hyperfrontend/immutable-api-utils/built-in-copy/number/index.cjs.js +7 -0
  18. package/_dependencies/@hyperfrontend/immutable-api-utils/built-in-copy/number/index.esm.js +7 -0
  19. package/_dependencies/@hyperfrontend/immutable-api-utils/built-in-copy/object/index.cjs.js +15 -0
  20. package/_dependencies/@hyperfrontend/immutable-api-utils/built-in-copy/object/index.esm.js +9 -0
  21. package/_dependencies/@hyperfrontend/immutable-api-utils/built-in-copy/set/index.cjs.js +6 -0
  22. package/_dependencies/@hyperfrontend/immutable-api-utils/built-in-copy/set/index.esm.js +5 -0
  23. package/_dependencies/@hyperfrontend/logging/index.cjs.js +191 -0
  24. package/_dependencies/@hyperfrontend/logging/index.d.ts +151 -0
  25. package/_dependencies/@hyperfrontend/logging/index.esm.js +186 -0
  26. package/_shared/core/cache/index.cjs.js +135 -0
  27. package/_shared/core/cache/index.esm.js +128 -0
  28. package/_shared/core/errors/structured-errors/index.cjs.js +28 -0
  29. package/_shared/core/errors/structured-errors/index.esm.js +23 -0
  30. package/_shared/core/fs/stat/index.cjs.js +46 -0
  31. package/_shared/core/fs/stat/index.esm.js +40 -0
  32. package/_shared/core/path/join/index.cjs.js +13 -0
  33. package/_shared/core/path/join/index.esm.js +10 -0
  34. package/_shared/core/path/normalize/index.cjs.js +37 -0
  35. package/_shared/core/path/normalize/index.esm.js +31 -0
  36. package/_shared/core/path/resolve/index.cjs.js +47 -0
  37. package/_shared/core/path/resolve/index.esm.js +41 -0
  38. package/_shared/core/path/segments/index.cjs.js +38 -0
  39. package/_shared/core/path/segments/index.esm.js +31 -0
  40. package/_shared/core/patterns/glob/index.cjs.js +145 -0
  41. package/_shared/core/patterns/glob/index.esm.js +136 -0
  42. package/_shared/core/platform/detect/index.cjs.js +103 -0
  43. package/_shared/core/platform/detect/index.esm.js +95 -0
  44. package/_shared/core/platform/line-endings/index.cjs.js +52 -0
  45. package/_shared/core/platform/line-endings/index.esm.js +44 -0
  46. package/_shared/project/config/patterns/index.cjs.js +172 -0
  47. package/_shared/project/config/patterns/index.esm.js +169 -0
  48. package/_shared/tech/monorepo/pnpm-workspaces/index.cjs.js +33 -0
  49. package/_shared/tech/monorepo/pnpm-workspaces/index.esm.js +31 -0
  50. package/_shared/tech/shared-utils/detector-helpers/index.cjs.js +48 -0
  51. package/_shared/tech/shared-utils/detector-helpers/index.esm.js +43 -0
  52. package/_shared/vfs/types/index.cjs.js +14 -0
  53. package/_shared/vfs/types/index.esm.js +12 -0
  54. package/cli/index.cjs.js +1699 -2040
  55. package/cli/index.d.ts +273 -7
  56. package/cli/index.d.ts.map +1 -1
  57. package/cli/index.esm.js +1603 -1944
  58. package/core/encoding/index.cjs.js +88 -424
  59. package/core/encoding/index.d.ts +186 -3
  60. package/core/encoding/index.d.ts.map +1 -1
  61. package/core/encoding/index.esm.js +80 -415
  62. package/core/fs/index.cjs.js +231 -595
  63. package/core/fs/index.d.ts +479 -6
  64. package/core/fs/index.d.ts.map +1 -1
  65. package/core/fs/index.esm.js +221 -585
  66. package/core/index.cjs.js +518 -1804
  67. package/core/index.d.ts +486 -9
  68. package/core/index.d.ts.map +1 -1
  69. package/core/index.esm.js +501 -1784
  70. package/core/path/index.cjs.js +6 -235
  71. package/core/path/index.d.ts +306 -5
  72. package/core/path/index.d.ts.map +1 -1
  73. package/core/path/index.esm.js +4 -233
  74. package/core/platform/index.cjs.js +5 -226
  75. package/core/platform/index.d.ts +185 -3
  76. package/core/platform/index.d.ts.map +1 -1
  77. package/core/platform/index.esm.js +3 -222
  78. package/heuristics/dependencies/index.cjs.js +95 -509
  79. package/heuristics/dependencies/index.d.ts +99 -2
  80. package/heuristics/dependencies/index.d.ts.map +1 -1
  81. package/heuristics/dependencies/index.esm.js +69 -483
  82. package/heuristics/entry-points/index.cjs.js +93 -825
  83. package/heuristics/entry-points/index.d.ts +123 -2
  84. package/heuristics/entry-points/index.d.ts.map +1 -1
  85. package/heuristics/entry-points/index.esm.js +74 -806
  86. package/heuristics/framework/index.cjs.js +1482 -1473
  87. package/heuristics/framework/index.d.ts +104 -2
  88. package/heuristics/framework/index.d.ts.map +1 -1
  89. package/heuristics/framework/index.esm.js +1418 -1409
  90. package/heuristics/index.cjs.js +3207 -3383
  91. package/heuristics/index.d.ts +4 -5
  92. package/heuristics/index.d.ts.map +1 -1
  93. package/heuristics/index.esm.js +3234 -3410
  94. package/heuristics/project-type/index.cjs.js +1488 -1500
  95. package/heuristics/project-type/index.d.ts +64 -2
  96. package/heuristics/project-type/index.d.ts.map +1 -1
  97. package/heuristics/project-type/index.esm.js +1417 -1429
  98. package/index.cjs.js +3064 -3765
  99. package/index.d.ts +44 -10
  100. package/index.d.ts.map +1 -1
  101. package/index.esm.js +2923 -3612
  102. package/models/index.cjs.js +0 -1
  103. package/models/index.d.ts +20 -14
  104. package/models/index.d.ts.map +1 -1
  105. package/models/index.esm.js +0 -1
  106. package/nx/index.cjs.js +163 -606
  107. package/nx/index.d.ts +279 -4
  108. package/nx/index.d.ts.map +1 -1
  109. package/nx/index.esm.js +145 -583
  110. package/package.json +13 -12
  111. package/project/config/index.cjs.js +122 -1104
  112. package/project/config/index.d.ts +202 -4
  113. package/project/config/index.d.ts.map +1 -1
  114. package/project/config/index.esm.js +105 -1085
  115. package/project/index.cjs.js +323 -1143
  116. package/project/index.d.ts +4 -5
  117. package/project/index.d.ts.map +1 -1
  118. package/project/index.esm.js +302 -1119
  119. package/project/package/index.cjs.js +191 -483
  120. package/project/package/index.d.ts +280 -3
  121. package/project/package/index.d.ts.map +1 -1
  122. package/project/package/index.esm.js +178 -469
  123. package/project/root/index.cjs.js +107 -427
  124. package/project/root/index.d.ts +83 -2
  125. package/project/root/index.d.ts.map +1 -1
  126. package/project/root/index.esm.js +96 -416
  127. package/project/traversal/index.cjs.js +94 -645
  128. package/project/traversal/index.d.ts +165 -3
  129. package/project/traversal/index.d.ts.map +1 -1
  130. package/project/traversal/index.esm.js +80 -631
  131. package/tech/backend/index.cjs.js +221 -524
  132. package/tech/backend/index.d.ts +205 -8
  133. package/tech/backend/index.d.ts.map +1 -1
  134. package/tech/backend/index.esm.js +200 -503
  135. package/tech/build/index.cjs.js +348 -647
  136. package/tech/build/index.d.ts +276 -10
  137. package/tech/build/index.d.ts.map +1 -1
  138. package/tech/build/index.esm.js +326 -625
  139. package/tech/frontend/index.cjs.js +505 -700
  140. package/tech/frontend/index.d.ts +379 -15
  141. package/tech/frontend/index.d.ts.map +1 -1
  142. package/tech/frontend/index.esm.js +481 -676
  143. package/tech/index.cjs.js +1580 -1482
  144. package/tech/index.d.ts +55 -32
  145. package/tech/index.d.ts.map +1 -1
  146. package/tech/index.esm.js +1513 -1415
  147. package/tech/legacy/index.cjs.js +97 -474
  148. package/tech/legacy/index.d.ts +125 -7
  149. package/tech/legacy/index.d.ts.map +1 -1
  150. package/tech/legacy/index.esm.js +79 -456
  151. package/tech/linting/index.cjs.js +136 -536
  152. package/tech/linting/index.d.ts +129 -7
  153. package/tech/linting/index.d.ts.map +1 -1
  154. package/tech/linting/index.esm.js +116 -516
  155. package/tech/monorepo/index.cjs.js +244 -584
  156. package/tech/monorepo/index.d.ts +241 -10
  157. package/tech/monorepo/index.d.ts.map +1 -1
  158. package/tech/monorepo/index.esm.js +224 -564
  159. package/tech/testing/index.cjs.js +214 -582
  160. package/tech/testing/index.d.ts +176 -8
  161. package/tech/testing/index.d.ts.map +1 -1
  162. package/tech/testing/index.esm.js +196 -564
  163. package/tech/types/index.cjs.js +121 -532
  164. package/tech/types/index.d.ts +120 -2
  165. package/tech/types/index.d.ts.map +1 -1
  166. package/tech/types/index.esm.js +99 -510
  167. package/vfs/index.cjs.js +647 -1187
  168. package/vfs/index.d.ts +360 -6
  169. package/vfs/index.d.ts.map +1 -1
  170. package/vfs/index.esm.js +672 -1212
  171. package/ARCHITECTURE.md +0 -370
  172. package/analyze.d.ts +0 -33
  173. package/analyze.d.ts.map +0 -1
  174. package/cli/commands/analyze.d.ts +0 -20
  175. package/cli/commands/analyze.d.ts.map +0 -1
  176. package/cli/commands/config.d.ts +0 -20
  177. package/cli/commands/config.d.ts.map +0 -1
  178. package/cli/commands/deps.d.ts +0 -18
  179. package/cli/commands/deps.d.ts.map +0 -1
  180. package/cli/commands/tree.d.ts +0 -24
  181. package/cli/commands/tree.d.ts.map +0 -1
  182. package/cli/index.cjs.js.map +0 -1
  183. package/cli/index.esm.js.map +0 -1
  184. package/cli/run.d.ts +0 -25
  185. package/cli/run.d.ts.map +0 -1
  186. package/cli/types.d.ts +0 -55
  187. package/cli/types.d.ts.map +0 -1
  188. package/core/cache.d.ts +0 -157
  189. package/core/cache.d.ts.map +0 -1
  190. package/core/encoding/convert.d.ts +0 -32
  191. package/core/encoding/convert.d.ts.map +0 -1
  192. package/core/encoding/detect.d.ts +0 -86
  193. package/core/encoding/detect.d.ts.map +0 -1
  194. package/core/encoding/index.cjs.js.map +0 -1
  195. package/core/encoding/index.esm.js.map +0 -1
  196. package/core/errors/structured-errors.d.ts +0 -64
  197. package/core/errors/structured-errors.d.ts.map +0 -1
  198. package/core/fs/directory.d.ts +0 -88
  199. package/core/fs/directory.d.ts.map +0 -1
  200. package/core/fs/index.cjs.js.map +0 -1
  201. package/core/fs/index.esm.js.map +0 -1
  202. package/core/fs/read.d.ts +0 -86
  203. package/core/fs/read.d.ts.map +0 -1
  204. package/core/fs/stat.d.ts +0 -58
  205. package/core/fs/stat.d.ts.map +0 -1
  206. package/core/fs/traversal.d.ts +0 -26
  207. package/core/fs/traversal.d.ts.map +0 -1
  208. package/core/fs/write.d.ts +0 -75
  209. package/core/fs/write.d.ts.map +0 -1
  210. package/core/index.cjs.js.map +0 -1
  211. package/core/index.esm.js.map +0 -1
  212. package/core/logger.d.ts +0 -111
  213. package/core/logger.d.ts.map +0 -1
  214. package/core/path/index.cjs.js.map +0 -1
  215. package/core/path/index.esm.js.map +0 -1
  216. package/core/path/join.d.ts +0 -17
  217. package/core/path/join.d.ts.map +0 -1
  218. package/core/path/normalize.d.ts +0 -37
  219. package/core/path/normalize.d.ts.map +0 -1
  220. package/core/path/resolve.d.ts +0 -52
  221. package/core/path/resolve.d.ts.map +0 -1
  222. package/core/path/segments.d.ts +0 -59
  223. package/core/path/segments.d.ts.map +0 -1
  224. package/core/patterns/glob.d.ts +0 -46
  225. package/core/patterns/glob.d.ts.map +0 -1
  226. package/core/platform/detect.d.ts +0 -66
  227. package/core/platform/detect.d.ts.map +0 -1
  228. package/core/platform/index.cjs.js.map +0 -1
  229. package/core/platform/index.esm.js.map +0 -1
  230. package/core/platform/line-endings.d.ts +0 -48
  231. package/core/platform/line-endings.d.ts.map +0 -1
  232. package/heuristics/dependencies/analyze.d.ts +0 -77
  233. package/heuristics/dependencies/analyze.d.ts.map +0 -1
  234. package/heuristics/dependencies/index.cjs.js.map +0 -1
  235. package/heuristics/dependencies/index.esm.js.map +0 -1
  236. package/heuristics/entry-points/discover.d.ts +0 -86
  237. package/heuristics/entry-points/discover.d.ts.map +0 -1
  238. package/heuristics/entry-points/index.cjs.js.map +0 -1
  239. package/heuristics/entry-points/index.esm.js.map +0 -1
  240. package/heuristics/framework/identify.d.ts +0 -84
  241. package/heuristics/framework/identify.d.ts.map +0 -1
  242. package/heuristics/framework/index.cjs.js.map +0 -1
  243. package/heuristics/framework/index.esm.js.map +0 -1
  244. package/heuristics/index.cjs.js.map +0 -1
  245. package/heuristics/index.esm.js.map +0 -1
  246. package/heuristics/project-type/detect.d.ts +0 -61
  247. package/heuristics/project-type/detect.d.ts.map +0 -1
  248. package/heuristics/project-type/index.cjs.js.map +0 -1
  249. package/heuristics/project-type/index.esm.js.map +0 -1
  250. package/index.cjs.js.map +0 -1
  251. package/index.esm.js.map +0 -1
  252. package/models/index.cjs.js.map +0 -1
  253. package/models/index.esm.js.map +0 -1
  254. package/nx/detect.d.ts +0 -105
  255. package/nx/detect.d.ts.map +0 -1
  256. package/nx/devkit-loader.d.ts +0 -62
  257. package/nx/devkit-loader.d.ts.map +0 -1
  258. package/nx/index.cjs.js.map +0 -1
  259. package/nx/index.esm.js.map +0 -1
  260. package/nx/project-config.d.ts +0 -109
  261. package/nx/project-config.d.ts.map +0 -1
  262. package/project/config/detect.d.ts +0 -77
  263. package/project/config/detect.d.ts.map +0 -1
  264. package/project/config/index.cjs.js.map +0 -1
  265. package/project/config/index.esm.js.map +0 -1
  266. package/project/config/parse.d.ts +0 -53
  267. package/project/config/parse.d.ts.map +0 -1
  268. package/project/config/patterns.d.ts +0 -31
  269. package/project/config/patterns.d.ts.map +0 -1
  270. package/project/index.cjs.js.map +0 -1
  271. package/project/index.esm.js.map +0 -1
  272. package/project/package/dependencies.d.ts +0 -101
  273. package/project/package/dependencies.d.ts.map +0 -1
  274. package/project/package/index.cjs.js.map +0 -1
  275. package/project/package/index.esm.js.map +0 -1
  276. package/project/package/read.d.ts +0 -66
  277. package/project/package/read.d.ts.map +0 -1
  278. package/project/root/detect.d.ts +0 -65
  279. package/project/root/detect.d.ts.map +0 -1
  280. package/project/root/index.cjs.js.map +0 -1
  281. package/project/root/index.esm.js.map +0 -1
  282. package/project/traversal/index.cjs.js.map +0 -1
  283. package/project/traversal/index.esm.js.map +0 -1
  284. package/project/traversal/search.d.ts +0 -59
  285. package/project/traversal/search.d.ts.map +0 -1
  286. package/project/traversal/walk.d.ts +0 -63
  287. package/project/traversal/walk.d.ts.map +0 -1
  288. package/tech/backend/detect-all.d.ts +0 -13
  289. package/tech/backend/detect-all.d.ts.map +0 -1
  290. package/tech/backend/express.d.ts +0 -11
  291. package/tech/backend/express.d.ts.map +0 -1
  292. package/tech/backend/fastify.d.ts +0 -11
  293. package/tech/backend/fastify.d.ts.map +0 -1
  294. package/tech/backend/hono.d.ts +0 -11
  295. package/tech/backend/hono.d.ts.map +0 -1
  296. package/tech/backend/index.cjs.js.map +0 -1
  297. package/tech/backend/index.esm.js.map +0 -1
  298. package/tech/backend/koa.d.ts +0 -11
  299. package/tech/backend/koa.d.ts.map +0 -1
  300. package/tech/backend/nestjs.d.ts +0 -11
  301. package/tech/backend/nestjs.d.ts.map +0 -1
  302. package/tech/backend/types.d.ts +0 -31
  303. package/tech/backend/types.d.ts.map +0 -1
  304. package/tech/build/babel.d.ts +0 -13
  305. package/tech/build/babel.d.ts.map +0 -1
  306. package/tech/build/detect-all.d.ts +0 -13
  307. package/tech/build/detect-all.d.ts.map +0 -1
  308. package/tech/build/esbuild.d.ts +0 -11
  309. package/tech/build/esbuild.d.ts.map +0 -1
  310. package/tech/build/index.cjs.js.map +0 -1
  311. package/tech/build/index.esm.js.map +0 -1
  312. package/tech/build/parcel.d.ts +0 -13
  313. package/tech/build/parcel.d.ts.map +0 -1
  314. package/tech/build/rollup.d.ts +0 -13
  315. package/tech/build/rollup.d.ts.map +0 -1
  316. package/tech/build/swc.d.ts +0 -13
  317. package/tech/build/swc.d.ts.map +0 -1
  318. package/tech/build/types.d.ts +0 -31
  319. package/tech/build/types.d.ts.map +0 -1
  320. package/tech/build/vite.d.ts +0 -13
  321. package/tech/build/vite.d.ts.map +0 -1
  322. package/tech/build/webpack.d.ts +0 -13
  323. package/tech/build/webpack.d.ts.map +0 -1
  324. package/tech/frontend/angular.d.ts +0 -11
  325. package/tech/frontend/angular.d.ts.map +0 -1
  326. package/tech/frontend/astro.d.ts +0 -11
  327. package/tech/frontend/astro.d.ts.map +0 -1
  328. package/tech/frontend/detect-all.d.ts +0 -13
  329. package/tech/frontend/detect-all.d.ts.map +0 -1
  330. package/tech/frontend/gatsby.d.ts +0 -11
  331. package/tech/frontend/gatsby.d.ts.map +0 -1
  332. package/tech/frontend/index.cjs.js.map +0 -1
  333. package/tech/frontend/index.esm.js.map +0 -1
  334. package/tech/frontend/nextjs.d.ts +0 -11
  335. package/tech/frontend/nextjs.d.ts.map +0 -1
  336. package/tech/frontend/nuxt.d.ts +0 -11
  337. package/tech/frontend/nuxt.d.ts.map +0 -1
  338. package/tech/frontend/qwik.d.ts +0 -11
  339. package/tech/frontend/qwik.d.ts.map +0 -1
  340. package/tech/frontend/react.d.ts +0 -11
  341. package/tech/frontend/react.d.ts.map +0 -1
  342. package/tech/frontend/remix.d.ts +0 -11
  343. package/tech/frontend/remix.d.ts.map +0 -1
  344. package/tech/frontend/solid.d.ts +0 -11
  345. package/tech/frontend/solid.d.ts.map +0 -1
  346. package/tech/frontend/svelte.d.ts +0 -11
  347. package/tech/frontend/svelte.d.ts.map +0 -1
  348. package/tech/frontend/sveltekit.d.ts +0 -11
  349. package/tech/frontend/sveltekit.d.ts.map +0 -1
  350. package/tech/frontend/types.d.ts +0 -35
  351. package/tech/frontend/types.d.ts.map +0 -1
  352. package/tech/frontend/vue.d.ts +0 -11
  353. package/tech/frontend/vue.d.ts.map +0 -1
  354. package/tech/index.cjs.js.map +0 -1
  355. package/tech/index.esm.js.map +0 -1
  356. package/tech/legacy/angularjs.d.ts +0 -12
  357. package/tech/legacy/angularjs.d.ts.map +0 -1
  358. package/tech/legacy/backbone.d.ts +0 -11
  359. package/tech/legacy/backbone.d.ts.map +0 -1
  360. package/tech/legacy/detect-all.d.ts +0 -13
  361. package/tech/legacy/detect-all.d.ts.map +0 -1
  362. package/tech/legacy/ember.d.ts +0 -11
  363. package/tech/legacy/ember.d.ts.map +0 -1
  364. package/tech/legacy/index.cjs.js.map +0 -1
  365. package/tech/legacy/index.esm.js.map +0 -1
  366. package/tech/legacy/jquery.d.ts +0 -11
  367. package/tech/legacy/jquery.d.ts.map +0 -1
  368. package/tech/legacy/types.d.ts +0 -33
  369. package/tech/legacy/types.d.ts.map +0 -1
  370. package/tech/linting/biome.d.ts +0 -11
  371. package/tech/linting/biome.d.ts.map +0 -1
  372. package/tech/linting/detect-all.d.ts +0 -13
  373. package/tech/linting/detect-all.d.ts.map +0 -1
  374. package/tech/linting/eslint.d.ts +0 -13
  375. package/tech/linting/eslint.d.ts.map +0 -1
  376. package/tech/linting/index.cjs.js.map +0 -1
  377. package/tech/linting/index.esm.js.map +0 -1
  378. package/tech/linting/prettier.d.ts +0 -13
  379. package/tech/linting/prettier.d.ts.map +0 -1
  380. package/tech/linting/stylelint.d.ts +0 -13
  381. package/tech/linting/stylelint.d.ts.map +0 -1
  382. package/tech/linting/types.d.ts +0 -31
  383. package/tech/linting/types.d.ts.map +0 -1
  384. package/tech/monorepo/detect-all.d.ts +0 -13
  385. package/tech/monorepo/detect-all.d.ts.map +0 -1
  386. package/tech/monorepo/index.cjs.js.map +0 -1
  387. package/tech/monorepo/index.esm.js.map +0 -1
  388. package/tech/monorepo/lerna.d.ts +0 -11
  389. package/tech/monorepo/lerna.d.ts.map +0 -1
  390. package/tech/monorepo/npm-workspaces.d.ts +0 -11
  391. package/tech/monorepo/npm-workspaces.d.ts.map +0 -1
  392. package/tech/monorepo/nx.d.ts +0 -11
  393. package/tech/monorepo/nx.d.ts.map +0 -1
  394. package/tech/monorepo/pnpm-workspaces.d.ts +0 -9
  395. package/tech/monorepo/pnpm-workspaces.d.ts.map +0 -1
  396. package/tech/monorepo/rush.d.ts +0 -11
  397. package/tech/monorepo/rush.d.ts.map +0 -1
  398. package/tech/monorepo/turborepo.d.ts +0 -11
  399. package/tech/monorepo/turborepo.d.ts.map +0 -1
  400. package/tech/monorepo/types.d.ts +0 -39
  401. package/tech/monorepo/types.d.ts.map +0 -1
  402. package/tech/monorepo/yarn-workspaces.d.ts +0 -11
  403. package/tech/monorepo/yarn-workspaces.d.ts.map +0 -1
  404. package/tech/shared-utils/detector-helpers.d.ts +0 -52
  405. package/tech/shared-utils/detector-helpers.d.ts.map +0 -1
  406. package/tech/shared-utils/types.d.ts +0 -41
  407. package/tech/shared-utils/types.d.ts.map +0 -1
  408. package/tech/testing/cypress.d.ts +0 -13
  409. package/tech/testing/cypress.d.ts.map +0 -1
  410. package/tech/testing/detect-all.d.ts +0 -13
  411. package/tech/testing/detect-all.d.ts.map +0 -1
  412. package/tech/testing/index.cjs.js.map +0 -1
  413. package/tech/testing/index.esm.js.map +0 -1
  414. package/tech/testing/jest.d.ts +0 -13
  415. package/tech/testing/jest.d.ts.map +0 -1
  416. package/tech/testing/mocha.d.ts +0 -13
  417. package/tech/testing/mocha.d.ts.map +0 -1
  418. package/tech/testing/playwright.d.ts +0 -13
  419. package/tech/testing/playwright.d.ts.map +0 -1
  420. package/tech/testing/types.d.ts +0 -35
  421. package/tech/testing/types.d.ts.map +0 -1
  422. package/tech/testing/vitest.d.ts +0 -13
  423. package/tech/testing/vitest.d.ts.map +0 -1
  424. package/tech/types/detectors.d.ts +0 -67
  425. package/tech/types/detectors.d.ts.map +0 -1
  426. package/tech/types/index.cjs.js.map +0 -1
  427. package/tech/types/index.esm.js.map +0 -1
  428. package/vfs/commit.d.ts +0 -32
  429. package/vfs/commit.d.ts.map +0 -1
  430. package/vfs/diff.d.ts +0 -73
  431. package/vfs/diff.d.ts.map +0 -1
  432. package/vfs/factory.d.ts +0 -37
  433. package/vfs/factory.d.ts.map +0 -1
  434. package/vfs/fs-tree.d.ts +0 -13
  435. package/vfs/fs-tree.d.ts.map +0 -1
  436. package/vfs/index.cjs.js.map +0 -1
  437. package/vfs/index.esm.js.map +0 -1
  438. package/vfs/types.d.ts +0 -178
  439. package/vfs/types.d.ts.map +0 -1
@@ -1,567 +1,27 @@
1
1
  'use strict';
2
2
 
3
- var node_path = require('node:path');
4
- var node_fs = require('node:fs');
5
-
6
- /**
7
- * Safe copies of Map built-in via factory function.
8
- *
9
- * Since constructors cannot be safely captured via Object.assign, this module
10
- * provides a factory function that uses Reflect.construct internally.
11
- *
12
- * These references are captured at module initialization time to protect against
13
- * prototype pollution attacks. Import only what you need for tree-shaking.
14
- *
15
- * @module @hyperfrontend/immutable-api-utils/built-in-copy/map
16
- */
17
- // Capture references at module initialization time
18
- const _Map = globalThis.Map;
19
- const _Reflect$2 = globalThis.Reflect;
20
- /**
21
- * (Safe copy) Creates a new Map using the captured Map constructor.
22
- * Use this instead of `new Map()`.
23
- *
24
- * @param iterable - Optional iterable of key-value pairs.
25
- * @returns A new Map instance.
26
- */
27
- const createMap = (iterable) => _Reflect$2.construct(_Map, iterable ? [iterable] : []);
28
-
29
- /**
30
- * Safe copies of Object built-in methods.
31
- *
32
- * These references are captured at module initialization time to protect against
33
- * prototype pollution attacks. Import only what you need for tree-shaking.
34
- *
35
- * @module @hyperfrontend/immutable-api-utils/built-in-copy/object
36
- */
37
- // Capture references at module initialization time
38
- const _Object = globalThis.Object;
39
- /**
40
- * (Safe copy) Prevents modification of existing property attributes and values,
41
- * and prevents the addition of new properties.
42
- */
43
- const freeze = _Object.freeze;
44
- /**
45
- * (Safe copy) Returns the names of the enumerable string properties and methods of an object.
46
- */
47
- const keys = _Object.keys;
48
- /**
49
- * (Safe copy) Returns an array of key/values of the enumerable own properties of an object.
50
- */
51
- const entries = _Object.entries;
52
- /**
53
- * (Safe copy) Returns an array of values of the enumerable own properties of an object.
54
- */
55
- const values = _Object.values;
56
- /**
57
- * (Safe copy) Adds one or more properties to an object, and/or modifies attributes of existing properties.
58
- */
59
- const defineProperties = _Object.defineProperties;
60
-
61
- /**
62
- * Safe copies of Set built-in via factory function.
63
- *
64
- * Since constructors cannot be safely captured via Object.assign, this module
65
- * provides a factory function that uses Reflect.construct internally.
66
- *
67
- * These references are captured at module initialization time to protect against
68
- * prototype pollution attacks. Import only what you need for tree-shaking.
69
- *
70
- * @module @hyperfrontend/immutable-api-utils/built-in-copy/set
71
- */
72
- // Capture references at module initialization time
73
- const _Set = globalThis.Set;
74
- const _Reflect$1 = globalThis.Reflect;
75
- /**
76
- * (Safe copy) Creates a new Set using the captured Set constructor.
77
- * Use this instead of `new Set()`.
78
- *
79
- * @param iterable - Optional iterable of values.
80
- * @returns A new Set instance.
81
- */
82
- const createSet = (iterable) => _Reflect$1.construct(_Set, iterable ? [iterable] : []);
83
-
84
- /**
85
- * Global registry of all caches for bulk operations.
86
- */
87
- const cacheRegistry = createSet();
88
- /**
89
- * Create a cache with optional TTL and size limits.
90
- *
91
- * The cache provides a simple key-value store with:
92
- * - Optional TTL (time-to-live) for automatic expiration
93
- * - Optional maxSize for limiting cache size with FIFO eviction
94
- * - Lazy expiration (entries are checked on access)
95
- *
96
- * @param options - Cache configuration options
97
- * @returns Cache instance
98
- *
99
- * @example
100
- * ```typescript
101
- * // Basic cache
102
- * const cache = createCache<string, number>()
103
- * cache.set('answer', 42)
104
- * cache.get('answer') // 42
105
- *
106
- * // Cache with TTL (expires after 60 seconds)
107
- * const ttlCache = createCache<string, object>({ ttl: 60000 })
108
- *
109
- * // Cache with max size (evicts oldest when full)
110
- * const lruCache = createCache<string, object>({ maxSize: 100 })
111
- *
112
- * // Combined options
113
- * const configCache = createCache<string, object>({
114
- * ttl: 30000,
115
- * maxSize: 50
116
- * })
117
- * ```
118
- */
119
- function createCache(options) {
120
- const { ttl, maxSize } = options ?? {};
121
- const store = createMap();
122
- // Track insertion order for FIFO eviction
123
- const insertionOrder = [];
124
- /**
125
- * Check if an entry is expired.
126
- *
127
- * @param entry - Cache entry to check
128
- * @returns True if entry is expired
129
- */
130
- function isExpired(entry) {
131
- if (ttl === undefined)
132
- return false;
133
- // eslint-disable-next-line workspace/no-unsafe-builtin-methods -- Date.now() is needed for Jest fake timers compatibility
134
- return Date.now() - entry.timestamp > ttl;
135
- }
136
- /**
137
- * Evict oldest entries to make room for new ones.
138
- */
139
- function evictIfNeeded() {
140
- if (maxSize === undefined)
141
- return;
142
- while (store.size >= maxSize && insertionOrder.length > 0) {
143
- const oldestKey = insertionOrder.shift();
144
- if (oldestKey !== undefined) {
145
- store.delete(oldestKey);
146
- }
147
- }
148
- }
149
- /**
150
- * Remove key from insertion order tracking.
151
- *
152
- * @param key - Key to remove from order tracking
153
- */
154
- function removeFromOrder(key) {
155
- const index = insertionOrder.indexOf(key);
156
- if (index !== -1) {
157
- insertionOrder.splice(index, 1);
158
- }
159
- }
160
- const cache = {
161
- get(key) {
162
- const entry = store.get(key);
163
- if (!entry)
164
- return undefined;
165
- if (isExpired(entry)) {
166
- store.delete(key);
167
- removeFromOrder(key);
168
- return undefined;
169
- }
170
- return entry.value;
171
- },
172
- set(key, value) {
173
- // If key exists, remove from order first
174
- if (store.has(key)) {
175
- removeFromOrder(key);
176
- }
177
- else {
178
- // Evict if needed before adding new entry
179
- evictIfNeeded();
180
- }
181
- // eslint-disable-next-line workspace/no-unsafe-builtin-methods -- Date.now() is needed for Jest fake timers compatibility
182
- store.set(key, { value, timestamp: Date.now() });
183
- insertionOrder.push(key);
184
- },
185
- has(key) {
186
- const entry = store.get(key);
187
- if (!entry)
188
- return false;
189
- if (isExpired(entry)) {
190
- store.delete(key);
191
- removeFromOrder(key);
192
- return false;
193
- }
194
- return true;
195
- },
196
- delete(key) {
197
- removeFromOrder(key);
198
- return store.delete(key);
199
- },
200
- clear() {
201
- store.clear();
202
- insertionOrder.length = 0;
203
- },
204
- size() {
205
- return store.size;
206
- },
207
- keys() {
208
- return [...insertionOrder];
209
- },
210
- };
211
- // Register cache for global operations
212
- cacheRegistry.add(cache);
213
- return freeze(cache);
214
- }
215
-
216
- /**
217
- * Safe copies of Array built-in static methods.
218
- *
219
- * These references are captured at module initialization time to protect against
220
- * prototype pollution attacks. Import only what you need for tree-shaking.
221
- *
222
- * @module @hyperfrontend/immutable-api-utils/built-in-copy/array
223
- */
224
- // Capture references at module initialization time
225
- const _Array = globalThis.Array;
226
- /**
227
- * (Safe copy) Determines whether the passed value is an Array.
228
- */
229
- const isArray = _Array.isArray;
230
-
231
- /**
232
- * Safe copies of Console built-in methods.
233
- *
234
- * These references are captured at module initialization time to protect against
235
- * prototype pollution attacks. Import only what you need for tree-shaking.
236
- *
237
- * @module @hyperfrontend/immutable-api-utils/built-in-copy/console
238
- */
239
- // Capture references at module initialization time
240
- const _console = globalThis.console;
241
- /**
242
- * (Safe copy) Outputs a message to the console.
243
- */
244
- const log = _console.log.bind(_console);
245
- /**
246
- * (Safe copy) Outputs a warning message to the console.
247
- */
248
- const warn = _console.warn.bind(_console);
249
- /**
250
- * (Safe copy) Outputs an error message to the console.
251
- */
252
- const error = _console.error.bind(_console);
253
- /**
254
- * (Safe copy) Outputs an informational message to the console.
255
- */
256
- const info = _console.info.bind(_console);
257
- /**
258
- * (Safe copy) Outputs a debug message to the console.
259
- */
260
- const debug = _console.debug.bind(_console);
261
- /**
262
- * (Safe copy) Outputs a stack trace to the console.
263
- */
264
- _console.trace.bind(_console);
265
- /**
266
- * (Safe copy) Displays an interactive listing of the properties of a specified object.
267
- */
268
- _console.dir.bind(_console);
269
- /**
270
- * (Safe copy) Displays tabular data as a table.
271
- */
272
- _console.table.bind(_console);
273
- /**
274
- * (Safe copy) Writes an error message to the console if the assertion is false.
275
- */
276
- _console.assert.bind(_console);
277
- /**
278
- * (Safe copy) Clears the console.
279
- */
280
- _console.clear.bind(_console);
281
- /**
282
- * (Safe copy) Logs the number of times that this particular call to count() has been called.
283
- */
284
- _console.count.bind(_console);
285
- /**
286
- * (Safe copy) Resets the counter used with console.count().
287
- */
288
- _console.countReset.bind(_console);
289
- /**
290
- * (Safe copy) Creates a new inline group in the console.
291
- */
292
- _console.group.bind(_console);
293
- /**
294
- * (Safe copy) Creates a new inline group in the console that is initially collapsed.
295
- */
296
- _console.groupCollapsed.bind(_console);
297
- /**
298
- * (Safe copy) Exits the current inline group.
299
- */
300
- _console.groupEnd.bind(_console);
301
- /**
302
- * (Safe copy) Starts a timer with a name specified as an input parameter.
303
- */
304
- _console.time.bind(_console);
305
- /**
306
- * (Safe copy) Stops a timer that was previously started.
307
- */
308
- _console.timeEnd.bind(_console);
309
- /**
310
- * (Safe copy) Logs the current value of a timer that was previously started.
311
- */
312
- _console.timeLog.bind(_console);
313
-
314
- /**
315
- * Safe copies of JSON built-in methods.
316
- *
317
- * These references are captured at module initialization time to protect against
318
- * prototype pollution attacks. Import only what you need for tree-shaking.
319
- *
320
- * @module @hyperfrontend/immutable-api-utils/built-in-copy/json
321
- */
322
- // Capture references at module initialization time
323
- const _JSON = globalThis.JSON;
324
- /**
325
- * (Safe copy) Converts a JavaScript Object Notation (JSON) string into an object.
326
- */
327
- const parse = _JSON.parse;
328
- /**
329
- * (Safe copy) Converts a JavaScript value to a JavaScript Object Notation (JSON) string.
330
- */
331
- const stringify = _JSON.stringify;
332
-
333
- const registeredClasses = [];
334
-
335
- /**
336
- * Returns the data type of the target.
337
- * Uses native `typeof` operator, however, makes distinction between `null`, `array`, and `object`.
338
- * Also, when classes are registered via `registerClass`, it checks if objects are instance of any known registered class.
339
- *
340
- * @param target - The target to get the data type of.
341
- * @returns The data type of the target.
342
- */
343
- const getType = (target) => {
344
- if (target === null)
345
- return 'null';
346
- const nativeDataType = typeof target;
347
- if (nativeDataType === 'object') {
348
- if (isArray(target))
349
- return 'array';
350
- for (const registeredClass of registeredClasses) {
351
- if (target instanceof registeredClass)
352
- return registeredClass.name;
353
- }
354
- }
355
- return nativeDataType;
356
- };
357
-
358
- /**
359
- * Safe copies of Error built-ins via factory functions.
360
- *
361
- * Since constructors cannot be safely captured via Object.assign, this module
362
- * provides factory functions that use Reflect.construct internally.
363
- *
364
- * These references are captured at module initialization time to protect against
365
- * prototype pollution attacks. Import only what you need for tree-shaking.
366
- *
367
- * @module @hyperfrontend/immutable-api-utils/built-in-copy/error
368
- */
369
- // Capture references at module initialization time
370
- const _Error = globalThis.Error;
371
- const _Reflect = globalThis.Reflect;
372
- /**
373
- * (Safe copy) Creates a new Error using the captured Error constructor.
374
- * Use this instead of `new Error()`.
375
- *
376
- * @param message - Optional error message.
377
- * @param options - Optional error options.
378
- * @returns A new Error instance.
379
- */
380
- const createError = (message, options) => _Reflect.construct(_Error, [message, options]);
381
-
382
- /**
383
- * Safe copies of Math built-in methods.
384
- *
385
- * These references are captured at module initialization time to protect against
386
- * prototype pollution attacks. Import only what you need for tree-shaking.
387
- *
388
- * @module @hyperfrontend/immutable-api-utils/built-in-copy/math
389
- */
390
- // Capture references at module initialization time
391
- const _Math = globalThis.Math;
392
- /**
393
- * (Safe copy) Returns the smaller of zero or more numbers.
394
- */
395
- const min = _Math.min;
396
-
397
- /* eslint-disable @typescript-eslint/no-explicit-any */
398
- /**
399
- * Creates a wrapper function that only executes the wrapped function if the condition function returns true.
400
- *
401
- * @param func - The function to be conditionally executed.
402
- * @param conditionFunc - A function that returns a boolean, determining if `func` should be executed.
403
- * @returns A wrapped version of `func` that executes conditionally.
404
- */
405
- function createConditionalExecutionFunction(func, conditionFunc) {
406
- return function (...args) {
407
- if (conditionFunc()) {
408
- return func(...args);
409
- }
410
- };
411
- }
412
-
413
- /* eslint-disable @typescript-eslint/no-explicit-any */
414
- /**
415
- * Creates a wrapper function that silently ignores any errors thrown by the wrapped void function.
416
- * This function is specifically for wrapping functions that do not return a value (void functions).
417
- * Exceptions are swallowed without any logging or handling.
418
- *
419
- * @param func - The void function to be wrapped.
420
- * @returns A wrapped version of the input function that ignores errors.
421
- */
422
- function createErrorIgnoringFunction(func) {
423
- return function (...args) {
424
- try {
425
- func(...args);
426
- }
427
- catch {
428
- // Deliberately swallowing/ignoring the exception
429
- }
430
- };
431
- }
432
-
433
- /* eslint-disable @typescript-eslint/no-unused-vars */
434
- /**
435
- * A no-operation function (noop) that does nothing regardless of the arguments passed.
436
- * It is designed to be as permissive as possible in its typing without using the `Function` keyword.
437
- *
438
- * @param args - Any arguments passed to the function (ignored)
439
- */
440
- const noop = (...args) => {
441
- // Intentionally does nothing
442
- };
443
-
444
- const logLevels = ['none', 'error', 'warn', 'log', 'info', 'debug'];
445
- const priority = {
446
- error: 4,
447
- warn: 3,
448
- log: 2,
449
- info: 1,
450
- debug: 0,
451
- };
452
- /**
453
- * Validates whether a given string is a valid log level.
454
- *
455
- * @param level - The log level to validate
456
- * @returns True if the level is valid, false otherwise
457
- */
458
- function isValidLogLevel(level) {
459
- return logLevels.includes(level);
460
- }
461
- /**
462
- * Creates a log level configuration manager for controlling logging behavior.
463
- * Provides methods to get, set, and evaluate log levels based on priority.
464
- *
465
- * @param level - The initial log level (defaults to 'error')
466
- * @returns A configuration object with log level management methods
467
- * @throws {Error} When the provided level is not a valid log level
468
- */
469
- function createLogLevelConfig(level = 'error') {
470
- if (!isValidLogLevel(level)) {
471
- throw createError('Cannot create log level configuration with a valid default log level');
472
- }
473
- const state = { level };
474
- const getLogLevel = () => state.level;
475
- const setLogLevel = (level) => {
476
- if (!isValidLogLevel(level)) {
477
- throw createError(`Cannot set value '${level}' level. Expected levels are ${logLevels}.`);
478
- }
479
- state.level = level;
480
- };
481
- const shouldLog = (level) => {
482
- if (state.level === 'none' || level === 'none' || !isValidLogLevel(level)) {
483
- return false;
484
- }
485
- return priority[level] >= priority[state.level];
486
- };
487
- return freeze({
488
- getLogLevel,
489
- setLogLevel,
490
- shouldLog,
491
- });
492
- }
493
-
494
- /**
495
- * Creates a logger instance with configurable log level filtering.
496
- * Each log function is wrapped to respect the current log level setting.
497
- *
498
- * @param error - Function to handle error-level logs (required)
499
- * @param warn - Function to handle warning-level logs (optional, defaults to noop)
500
- * @param log - Function to handle standard logs (optional, defaults to noop)
501
- * @param info - Function to handle info-level logs (optional, defaults to noop)
502
- * @param debug - Function to handle debug-level logs (optional, defaults to noop)
503
- * @returns A frozen logger object with log methods and level control
504
- * @throws {ErrorLevelFn} When any provided log function is invalid
505
- */
506
- function createLogger(error, warn = noop, log = noop, info = noop, debug = noop) {
507
- if (notValidLogFn(error)) {
508
- throw createError(notFnMsg('error'));
509
- }
510
- if (notValidLogFn(warn)) {
511
- throw createError(notFnMsg('warn'));
512
- }
513
- if (notValidLogFn(log)) {
514
- throw createError(notFnMsg('log'));
515
- }
516
- if (notValidLogFn(info)) {
517
- throw createError(notFnMsg('info'));
518
- }
519
- if (notValidLogFn(debug)) {
520
- throw createError(notFnMsg('debug'));
521
- }
522
- const { setLogLevel, getLogLevel, shouldLog } = createLogLevelConfig();
523
- const wrapLogFn = (fn, level) => {
524
- if (fn === noop)
525
- return fn;
526
- const condition = () => shouldLog(level);
527
- return createConditionalExecutionFunction(createErrorIgnoringFunction(fn), condition);
528
- };
529
- return freeze({
530
- error: wrapLogFn(error, 'error'),
531
- warn: wrapLogFn(warn, 'warn'),
532
- log: wrapLogFn(log, 'log'),
533
- info: wrapLogFn(info, 'info'),
534
- debug: wrapLogFn(debug, 'debug'),
535
- setLogLevel,
536
- getLogLevel,
537
- });
538
- }
539
- /**
540
- * Validates whether a given value is a valid log function.
541
- *
542
- * @param fn - The value to validate
543
- * @returns True if the value is not a function (invalid), false if it is valid
544
- */
545
- function notValidLogFn(fn) {
546
- return getType(fn) !== 'function' && fn !== noop;
547
- }
548
- /**
549
- * Generates an error message for invalid log function parameters.
550
- *
551
- * @param label - The name of the log function that failed validation
552
- * @returns A formatted error message string
553
- */
554
- function notFnMsg(label) {
555
- return `Cannot create a logger when ${label} is not a function`;
556
- }
557
-
558
- createLogger(error, warn, log, info, debug);
3
+ const index_cjs_js$1 = require('../../_dependencies/@hyperfrontend/immutable-api-utils/built-in-copy/map/index.cjs.js');
4
+ const index_cjs_js$2 = require('../../_dependencies/@hyperfrontend/immutable-api-utils/built-in-copy/object/index.cjs.js');
5
+ const index_cjs_js = require('../../_dependencies/@hyperfrontend/immutable-api-utils/built-in-copy/set/index.cjs.js');
6
+ const index_cjs_js$5 = require('../../_dependencies/@hyperfrontend/immutable-api-utils/built-in-copy/array/index.cjs.js');
7
+ const index_cjs_js$4 = require('../../_dependencies/@hyperfrontend/immutable-api-utils/built-in-copy/console/index.cjs.js');
8
+ const index_cjs_js$6 = require('../../_dependencies/@hyperfrontend/immutable-api-utils/built-in-copy/json/index.cjs.js');
9
+ const index_cjs_js$3 = require('../../_dependencies/@hyperfrontend/logging/index.cjs.js');
10
+ const node_path = require('node:path');
11
+ const index_cjs_js$7 = require('../../_dependencies/@hyperfrontend/immutable-api-utils/built-in-copy/error/index.cjs.js');
12
+ const node_fs = require('node:fs');
13
+ const index_cjs_js$8 = require('../../_dependencies/@hyperfrontend/immutable-api-utils/built-in-copy/math/index.cjs.js');
14
+ const { isDirectory, exists } = require('../../_shared/core/fs/stat/index.cjs.js');
15
+ const { join } = require('../../_shared/core/path/join/index.cjs.js');
16
+ const { createCache } = require('../../_shared/core/cache/index.cjs.js');
17
+ const { collectAllDependencies, parseVersionString, locateConfigFile, filterScriptsByCommand } = require('../../_shared/tech/shared-utils/detector-helpers/index.cjs.js');
18
+ const { pnpmWorkspacesDetector } = require('../../_shared/tech/monorepo/pnpm-workspaces/index.cjs.js');
559
19
 
560
20
  /**
561
21
  * Global log level registry.
562
22
  * Tracks all created scoped loggers to allow global log level changes.
563
23
  */
564
- const loggerRegistry = createSet();
24
+ const loggerRegistry = index_cjs_js.createSet();
565
25
  /** Redacted placeholder for sensitive values */
566
26
  const REDACTED = '[REDACTED]';
567
27
  /**
@@ -595,17 +55,24 @@ function isSensitiveKey(key) {
595
55
  *
596
56
  * @param obj - Object to sanitize
597
57
  * @returns New object with sensitive values redacted
58
+ *
59
+ * @example Sanitizing sensitive data
60
+ * ```typescript
61
+ * const config = { apiKey: 'secret123', endpoint: 'https://api.example.com' }
62
+ * const safe = sanitize(config)
63
+ * // => { apiKey: '[REDACTED]', endpoint: 'https://api.example.com' }
64
+ * ```
598
65
  */
599
66
  function sanitize(obj) {
600
67
  if (obj === null || obj === undefined) {
601
68
  return obj;
602
69
  }
603
- if (isArray(obj)) {
70
+ if (index_cjs_js$5.isArray(obj)) {
604
71
  return obj.map((item) => sanitize(item));
605
72
  }
606
73
  if (typeof obj === 'object') {
607
74
  const result = {};
608
- for (const [key, value] of entries(obj)) {
75
+ for (const [key, value] of index_cjs_js$2.entries(obj)) {
609
76
  if (isSensitiveKey(key)) {
610
77
  result[key] = REDACTED;
611
78
  }
@@ -630,9 +97,9 @@ function sanitize(obj) {
630
97
  */
631
98
  function formatMessage(namespace, message, meta) {
632
99
  const prefix = `[${namespace}]`;
633
- if (meta && keys(meta).length > 0) {
100
+ if (meta && index_cjs_js$2.keys(meta).length > 0) {
634
101
  const sanitizedMeta = sanitize(meta);
635
- return `${prefix} ${message} ${stringify(sanitizedMeta)}`;
102
+ return `${prefix} ${message} ${index_cjs_js$6.stringify(sanitizedMeta)}`;
636
103
  }
637
104
  return `${prefix} ${message}`;
638
105
  }
@@ -645,7 +112,7 @@ function formatMessage(namespace, message, meta) {
645
112
  * @param options - Logger configuration options
646
113
  * @returns A configured scoped logger instance
647
114
  *
648
- * @example
115
+ * @example Creating a scoped logger
649
116
  * ```typescript
650
117
  * const logger = createScopedLogger('project-scope')
651
118
  * logger.setLogLevel('debug')
@@ -660,16 +127,13 @@ function formatMessage(namespace, message, meta) {
660
127
  */
661
128
  function createScopedLogger(namespace, options = {}) {
662
129
  const { level = 'error', sanitizeSecrets = true } = options;
663
- // Create wrapper functions that add namespace prefix and sanitization
664
130
  const createLogFn = (baseFn) => (message, meta) => {
665
131
  const processedMeta = sanitizeSecrets && meta ? sanitize(meta) : meta;
666
132
  baseFn(formatMessage(namespace, message, processedMeta));
667
133
  };
668
- // Create base logger with wrapped functions
669
- const baseLogger = createLogger(createLogFn(error), createLogFn(warn), createLogFn(log), createLogFn(info), createLogFn(debug));
670
- // Set initial log level (use global override if set)
134
+ const baseLogger = index_cjs_js$3.createLogger(createLogFn(index_cjs_js$4.error), createLogFn(index_cjs_js$4.warn), createLogFn(index_cjs_js$4.log), createLogFn(index_cjs_js$4.info), createLogFn(index_cjs_js$4.debug));
671
135
  baseLogger.setLogLevel(level);
672
- const scopedLogger = freeze({
136
+ const scopedLogger = index_cjs_js$2.freeze({
673
137
  error: (message, meta) => baseLogger.error(message, meta),
674
138
  warn: (message, meta) => baseLogger.warn(message, meta),
675
139
  log: (message, meta) => baseLogger.log(message, meta),
@@ -678,7 +142,6 @@ function createScopedLogger(namespace, options = {}) {
678
142
  setLogLevel: baseLogger.setLogLevel,
679
143
  getLogLevel: baseLogger.getLogLevel,
680
144
  });
681
- // Register logger for global level management
682
145
  loggerRegistry.add(scopedLogger);
683
146
  return scopedLogger;
684
147
  }
@@ -686,7 +149,7 @@ function createScopedLogger(namespace, options = {}) {
686
149
  * Default logger instance for the project-scope library.
687
150
  * Use this for general logging within the library.
688
151
  *
689
- * @example
152
+ * @example Using the default logger
690
153
  * ```typescript
691
154
  * import { logger } from '@hyperfrontend/project-scope/core'
692
155
  *
@@ -704,10 +167,19 @@ createScopedLogger('project-scope:fs');
704
167
  * @param code - The category code for this type of filesystem failure
705
168
  * @param context - Additional context including path, operation, and cause
706
169
  * @returns A configured Error object with code and context properties
170
+ *
171
+ * @example Creating a file system error
172
+ * ```typescript
173
+ * throw createFileSystemError(
174
+ * 'Cannot read file',
175
+ * 'FS_READ_ERROR',
176
+ * { path: './missing.txt', operation: 'read' }
177
+ * )
178
+ * ```
707
179
  */
708
180
  function createFileSystemError(message, code, context) {
709
- const error = createError(message);
710
- defineProperties(error, {
181
+ const error = index_cjs_js$7.createError(message);
182
+ index_cjs_js$2.defineProperties(error, {
711
183
  code: { value: code, enumerable: true },
712
184
  context: { value: context, enumerable: true },
713
185
  });
@@ -719,6 +191,14 @@ function createFileSystemError(message, code, context) {
719
191
  * @param filePath - Path to file
720
192
  * @param encoding - File encoding (default: utf-8)
721
193
  * @returns File contents or null if file doesn't exist
194
+ *
195
+ * @example Reading file if it exists
196
+ * ```typescript
197
+ * const content = readFileIfExists('./optional-config.json')
198
+ * if (content) {
199
+ * // File existed, use content
200
+ * }
201
+ * ```
722
202
  */
723
203
  function readFileIfExists(filePath, encoding = 'utf-8') {
724
204
  if (!node_fs.existsSync(filePath)) {
@@ -732,56 +212,6 @@ function readFileIfExists(filePath, encoding = 'utf-8') {
732
212
  }
733
213
  }
734
214
 
735
- createScopedLogger('project-scope:fs:write');
736
-
737
- /**
738
- * Get file stats with error handling.
739
- *
740
- * @param filePath - Path to file
741
- * @param followSymlinks - Whether to follow symlinks (default: true)
742
- * @returns File stats or null if path doesn't exist
743
- */
744
- function getFileStat(filePath, followSymlinks = true) {
745
- if (!node_fs.existsSync(filePath)) {
746
- return null;
747
- }
748
- try {
749
- const stat = followSymlinks ? node_fs.statSync(filePath) : node_fs.lstatSync(filePath);
750
- return {
751
- isFile: stat.isFile(),
752
- isDirectory: stat.isDirectory(),
753
- isSymlink: stat.isSymbolicLink(),
754
- size: stat.size,
755
- created: stat.birthtime,
756
- modified: stat.mtime,
757
- accessed: stat.atime,
758
- mode: stat.mode,
759
- };
760
- }
761
- catch {
762
- return null;
763
- }
764
- }
765
- /**
766
- * Check if path is a directory.
767
- *
768
- * @param dirPath - Path to check
769
- * @returns True if path is a directory
770
- */
771
- function isDirectory(dirPath) {
772
- const stats = getFileStat(dirPath);
773
- return stats?.isDirectory ?? false;
774
- }
775
- /**
776
- * Check if path exists.
777
- *
778
- * @param filePath - Path to check
779
- * @returns True if path exists
780
- */
781
- function exists(filePath) {
782
- return node_fs.existsSync(filePath);
783
- }
784
-
785
215
  const fsDirLogger = createScopedLogger('project-scope:fs:dir');
786
216
  /**
787
217
  * List immediate contents of a directory.
@@ -790,7 +220,7 @@ const fsDirLogger = createScopedLogger('project-scope:fs:dir');
790
220
  * @returns Array of entries with metadata for each file/directory
791
221
  * @throws {Error} If directory doesn't exist or isn't a directory
792
222
  *
793
- * @example
223
+ * @example Listing directory contents
794
224
  * ```typescript
795
225
  * import { readDirectory } from '@hyperfrontend/project-scope'
796
226
  *
@@ -831,19 +261,10 @@ function readDirectory(dirPath) {
831
261
  }
832
262
  }
833
263
 
834
- /**
835
- * Join path segments.
836
- * Uses platform-specific separators (e.g., / or \).
837
- *
838
- * @param paths - Path segments to join
839
- * @returns Joined path
840
- */
841
- function join(...paths) {
842
- return node_path.join(...paths);
843
- }
844
-
845
264
  createScopedLogger('project-scope:fs:traversal');
846
265
 
266
+ createScopedLogger('project-scope:fs:write');
267
+
847
268
  const packageLogger = createScopedLogger('project-scope:project:package');
848
269
  /**
849
270
  * Verifies that a value is an object with only string values,
@@ -855,7 +276,7 @@ const packageLogger = createScopedLogger('project-scope:project:package');
855
276
  function isStringRecord(value) {
856
277
  if (typeof value !== 'object' || value === null)
857
278
  return false;
858
- return values(value).every((v) => typeof v === 'string');
279
+ return index_cjs_js$2.values(value).every((v) => typeof v === 'string');
859
280
  }
860
281
  /**
861
282
  * Extracts and normalizes the workspaces field from package.json,
@@ -865,12 +286,12 @@ function isStringRecord(value) {
865
286
  * @returns Normalized workspace patterns or undefined if invalid
866
287
  */
867
288
  function parseWorkspaces(value) {
868
- if (isArray(value) && value.every((v) => typeof v === 'string')) {
289
+ if (index_cjs_js$5.isArray(value) && value.every((v) => typeof v === 'string')) {
869
290
  return value;
870
291
  }
871
292
  if (typeof value === 'object' && value !== null) {
872
293
  const obj = value;
873
- if (isArray(obj['packages'])) {
294
+ if (index_cjs_js$5.isArray(obj['packages'])) {
874
295
  return { packages: obj['packages'] };
875
296
  }
876
297
  }
@@ -884,7 +305,7 @@ function parseWorkspaces(value) {
884
305
  */
885
306
  function validatePackageJson(data) {
886
307
  if (typeof data !== 'object' || data === null) {
887
- throw createError('package.json must be an object');
308
+ throw index_cjs_js$7.createError('package.json must be an object');
888
309
  }
889
310
  const pkg = data;
890
311
  return {
@@ -913,6 +334,16 @@ function validatePackageJson(data) {
913
334
  *
914
335
  * @param projectPath - Project directory path or path to package.json
915
336
  * @returns Parsed package.json or null if not found
337
+ *
338
+ * @example Reading package.json if it exists
339
+ * ```typescript
340
+ * import { readPackageJsonIfExists } from '@hyperfrontend/project-scope'
341
+ *
342
+ * const pkg = readPackageJsonIfExists('/path/to/project')
343
+ * if (pkg) {
344
+ * console.log('Found:', pkg.name)
345
+ * }
346
+ * ```
916
347
  */
917
348
  function readPackageJsonIfExists(projectPath) {
918
349
  const packageJsonPath = projectPath.endsWith('package.json') ? projectPath : node_path.join(projectPath, 'package.json');
@@ -922,7 +353,7 @@ function readPackageJsonIfExists(projectPath) {
922
353
  return null;
923
354
  }
924
355
  try {
925
- const validated = validatePackageJson(parse(content));
356
+ const validated = validatePackageJson(index_cjs_js$6.parse(content));
926
357
  packageLogger.debug('Package.json loaded', { path: packageJsonPath, name: validated.name });
927
358
  return validated;
928
359
  }
@@ -933,80 +364,31 @@ function readPackageJsonIfExists(projectPath) {
933
364
  }
934
365
 
935
366
  /**
936
- * Get combined dependencies from package.json.
937
- * Merges dependencies, devDependencies, peerDependencies, and optionalDependencies.
367
+ * Detect Express in project.
938
368
  *
939
- * @param packageJson - The package.json object to extract dependencies from
940
- * @returns Combined dependencies as a single record
941
- */
942
- function collectAllDependencies(packageJson) {
943
- return {
944
- ...packageJson?.dependencies,
945
- ...packageJson?.devDependencies,
946
- ...packageJson?.peerDependencies,
947
- ...packageJson?.optionalDependencies,
948
- };
949
- }
950
- /**
951
- * Extract clean version from dependency version string.
952
- * Removes semver prefixes like ^, ~, >=, etc.
953
- * Uses character-by-character parsing to avoid ReDoS vulnerabilities.
369
+ * @param projectPath - Project directory path
370
+ * @param packageJson - Optional pre-loaded package.json
371
+ * @returns Detection result or null if not detected
372
+ * @example Detecting Express framework
373
+ * ```typescript
374
+ * const pkg = {
375
+ * dependencies: { express: '^4.18.2', cors: '^2.8.5' },
376
+ * devDependencies: { '@types/express': '^4.17.17' },
377
+ * }
954
378
  *
955
- * @param versionString - The version string with optional prefix characters
956
- * @returns The cleaned version string without prefix characters
957
- */
958
- function parseVersionString(versionString) {
959
- if (versionString === undefined || versionString === null)
960
- return undefined;
961
- // Manual parsing instead of regex to avoid ReDoS
962
- let start = 0;
963
- while (start < versionString.length) {
964
- const char = versionString[start];
965
- if (char !== '^' && char !== '~' && char !== '>' && char !== '=' && char !== '<') {
966
- break;
967
- }
968
- start++;
969
- }
970
- return versionString.slice(start);
971
- }
972
- /**
973
- * Find first matching config file in project.
974
- * Note: Name avoids similarity to fs.readFile/fs.readFileSync.
975
- *
976
- * @param projectPath - The project directory path
977
- * @param patterns - Array of config file patterns to search for
978
- * @returns The first matching config file path or undefined
979
- */
980
- function locateConfigFile(projectPath, patterns) {
981
- for (const pattern of patterns) {
982
- const fullPath = join(projectPath, pattern);
983
- if (exists(fullPath)) {
984
- return pattern;
985
- }
986
- }
987
- return undefined;
988
- }
989
- /**
990
- * Find scripts containing a specific command.
991
- *
992
- * @param scripts - The scripts object from package.json
993
- * @param command - The command string to search for
994
- * @returns Array of script names that contain the command
995
- */
996
- function filterScriptsByCommand(scripts, command) {
997
- if (!scripts)
998
- return [];
999
- return entries(scripts)
1000
- .filter(([, script]) => script.includes(command))
1001
- .map(([name]) => name);
1002
- }
1003
-
1004
- /**
1005
- * Detect Express in project.
1006
- *
1007
- * @param projectPath - Project directory path
1008
- * @param packageJson - Optional pre-loaded package.json
1009
- * @returns Detection result or null if not detected
379
+ * const result = expressDetector('/path/to/project', pkg)
380
+ * // => {
381
+ * // id: 'express',
382
+ * // name: 'Express',
383
+ * // version: '4.18.2',
384
+ * // confidence: 100,
385
+ * // detectedFrom: [
386
+ * // { type: 'package.json', field: 'dependencies.express' },
387
+ * // { type: 'package.json', field: 'dependencies.@types/express' },
388
+ * // { type: 'package.json', field: 'dependencies (express middleware)' },
389
+ * // ],
390
+ * // }
391
+ * ```
1010
392
  */
1011
393
  function expressDetector(projectPath, packageJson) {
1012
394
  const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
@@ -1019,12 +401,11 @@ function expressDetector(projectPath, packageJson) {
1019
401
  version = parseVersionString(deps['express']);
1020
402
  sources.push({ type: 'package.json', field: 'dependencies.express' });
1021
403
  }
1022
- // @types/express (indicates usage)
1023
404
  if (deps['@types/express']) {
1024
405
  confidence += 10;
1025
406
  sources.push({ type: 'package.json', field: 'dependencies.@types/express' });
1026
407
  }
1027
- const expressMiddleware = keys(deps).filter((d) => d.includes('express-') || d === 'body-parser' || d === 'cors' || d === 'helmet' || d === 'morgan');
408
+ const expressMiddleware = index_cjs_js$2.keys(deps).filter((d) => d.includes('express-') || d === 'body-parser' || d === 'cors' || d === 'helmet' || d === 'morgan');
1028
409
  if (expressMiddleware.length > 0) {
1029
410
  confidence += 10;
1030
411
  sources.push({ type: 'package.json', field: 'dependencies (express middleware)' });
@@ -1036,95 +417,117 @@ function expressDetector(projectPath, packageJson) {
1036
417
  id: 'express',
1037
418
  name: 'Express',
1038
419
  version,
1039
- confidence: min(confidence, 100),
420
+ confidence: index_cjs_js$8.min(confidence, 100),
1040
421
  detectedFrom: sources,
1041
422
  };
1042
423
  }
1043
424
 
1044
425
  /**
1045
- * Detect NestJS in project.
426
+ * Detect Fastify in project.
1046
427
  *
1047
428
  * @param projectPath - Project directory path
1048
429
  * @param packageJson - Optional pre-loaded package.json
1049
430
  * @returns Detection result or null if not detected
431
+ * @example Detecting Fastify framework
432
+ * ```typescript
433
+ * const pkg = {
434
+ * dependencies: { fastify: '^4.24.0', '@fastify/cors': '^8.4.0' },
435
+ * }
436
+ *
437
+ * const result = fastifyDetector('/path/to/project', pkg)
438
+ * // => {
439
+ * // id: 'fastify',
440
+ * // name: 'Fastify',
441
+ * // version: '4.24.0',
442
+ * // confidence: 95,
443
+ * // detectedFrom: [
444
+ * // { type: 'package.json', field: 'dependencies.fastify' },
445
+ * // { type: 'package.json', field: 'dependencies (fastify plugins)' },
446
+ * // ],
447
+ * // }
448
+ * ```
1050
449
  */
1051
- function nestDetector(projectPath, packageJson) {
450
+ function fastifyDetector(projectPath, packageJson) {
1052
451
  const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
1053
452
  const sources = [];
1054
453
  let confidence = 0;
1055
454
  let version;
1056
- let configPath;
1057
455
  const deps = collectAllDependencies(pkg);
1058
- // @nestjs/core package
1059
- if (deps['@nestjs/core']) {
1060
- confidence += 70;
1061
- version = parseVersionString(deps['@nestjs/core']);
1062
- sources.push({ type: 'package.json', field: 'dependencies.@nestjs/core' });
1063
- }
1064
- // @nestjs/common
1065
- if (deps['@nestjs/common']) {
1066
- confidence += 15;
1067
- sources.push({ type: 'package.json', field: 'dependencies.@nestjs/common' });
456
+ if (deps['fastify']) {
457
+ confidence += 80;
458
+ version = parseVersionString(deps['fastify']);
459
+ sources.push({ type: 'package.json', field: 'dependencies.fastify' });
1068
460
  }
1069
- if (exists(node_path.join(projectPath, 'nest-cli.json'))) {
461
+ const fastifyPlugins = index_cjs_js$2.keys(deps).filter((d) => d.startsWith('@fastify/') || d.startsWith('fastify-'));
462
+ if (fastifyPlugins.length > 0) {
1070
463
  confidence += 15;
1071
- configPath = 'nest-cli.json';
1072
- sources.push({ type: 'config-file', path: 'nest-cli.json' });
464
+ sources.push({ type: 'package.json', field: 'dependencies (fastify plugins)' });
1073
465
  }
1074
- const nestPackages = keys(deps).filter((d) => d.startsWith('@nestjs/'));
1075
- if (nestPackages.length > 2) {
466
+ if (deps['@types/fastify']) {
1076
467
  confidence += 5;
1077
- sources.push({ type: 'package.json', field: 'dependencies (@nestjs packages)' });
468
+ sources.push({ type: 'package.json', field: 'dependencies.@types/fastify' });
1078
469
  }
1079
470
  if (confidence === 0) {
1080
471
  return null;
1081
472
  }
1082
473
  return {
1083
- id: 'nestjs',
1084
- name: 'NestJS',
474
+ id: 'fastify',
475
+ name: 'Fastify',
1085
476
  version,
1086
- configPath,
1087
- confidence: min(confidence, 100),
477
+ confidence: index_cjs_js$8.min(confidence, 100),
1088
478
  detectedFrom: sources,
1089
479
  };
1090
480
  }
1091
481
 
1092
482
  /**
1093
- * Detect Fastify in project.
483
+ * Detect Hono in project.
1094
484
  *
1095
485
  * @param projectPath - Project directory path
1096
486
  * @param packageJson - Optional pre-loaded package.json
1097
487
  * @returns Detection result or null if not detected
488
+ * @example Detecting Hono framework
489
+ * ```typescript
490
+ * const pkg = {
491
+ * dependencies: { hono: '^3.11.0', '@hono/node-server': '^1.3.0' },
492
+ * }
493
+ *
494
+ * const result = honoDetector('/path/to/project', pkg)
495
+ * // => {
496
+ * // id: 'hono',
497
+ * // name: 'Hono',
498
+ * // version: '3.11.0',
499
+ * // confidence: 100,
500
+ * // detectedFrom: [
501
+ * // { type: 'package.json', field: 'dependencies.hono' },
502
+ * // { type: 'package.json', field: 'dependencies (@hono adapters)' },
503
+ * // ],
504
+ * // }
505
+ * ```
1098
506
  */
1099
- function fastifyDetector(projectPath, packageJson) {
507
+ function honoDetector(projectPath, packageJson) {
1100
508
  const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
1101
509
  const sources = [];
1102
510
  let confidence = 0;
1103
511
  let version;
1104
512
  const deps = collectAllDependencies(pkg);
1105
- if (deps['fastify']) {
1106
- confidence += 80;
1107
- version = parseVersionString(deps['fastify']);
1108
- sources.push({ type: 'package.json', field: 'dependencies.fastify' });
513
+ if (deps['hono']) {
514
+ confidence += 85;
515
+ version = parseVersionString(deps['hono']);
516
+ sources.push({ type: 'package.json', field: 'dependencies.hono' });
1109
517
  }
1110
- const fastifyPlugins = keys(deps).filter((d) => d.startsWith('@fastify/') || d.startsWith('fastify-'));
1111
- if (fastifyPlugins.length > 0) {
518
+ const honoAdapters = index_cjs_js$2.keys(deps).filter((d) => d.startsWith('@hono/'));
519
+ if (honoAdapters.length > 0) {
1112
520
  confidence += 15;
1113
- sources.push({ type: 'package.json', field: 'dependencies (fastify plugins)' });
1114
- }
1115
- // @types/fastify (older versions)
1116
- if (deps['@types/fastify']) {
1117
- confidence += 5;
1118
- sources.push({ type: 'package.json', field: 'dependencies.@types/fastify' });
521
+ sources.push({ type: 'package.json', field: 'dependencies (@hono adapters)' });
1119
522
  }
1120
523
  if (confidence === 0) {
1121
524
  return null;
1122
525
  }
1123
526
  return {
1124
- id: 'fastify',
1125
- name: 'Fastify',
527
+ id: 'hono',
528
+ name: 'Hono',
1126
529
  version,
1127
- confidence: min(confidence, 100),
530
+ confidence: index_cjs_js$8.min(confidence, 100),
1128
531
  detectedFrom: sources,
1129
532
  };
1130
533
  }
@@ -1135,6 +538,26 @@ function fastifyDetector(projectPath, packageJson) {
1135
538
  * @param projectPath - Project directory path
1136
539
  * @param packageJson - Optional pre-loaded package.json
1137
540
  * @returns Detection result or null if not detected
541
+ * @example Detecting Koa framework
542
+ * ```typescript
543
+ * const pkg = {
544
+ * dependencies: { koa: '^2.14.2', 'koa-router': '^12.0.0' },
545
+ * devDependencies: { '@types/koa': '^2.13.9' },
546
+ * }
547
+ *
548
+ * const result = koaDetector('/path/to/project', pkg)
549
+ * // => {
550
+ * // id: 'koa',
551
+ * // name: 'Koa',
552
+ * // version: '2.14.2',
553
+ * // confidence: 100,
554
+ * // detectedFrom: [
555
+ * // { type: 'package.json', field: 'dependencies.koa' },
556
+ * // { type: 'package.json', field: 'dependencies.@types/koa' },
557
+ * // { type: 'package.json', field: 'dependencies (koa middleware)' },
558
+ * // ],
559
+ * // }
560
+ * ```
1138
561
  */
1139
562
  function koaDetector(projectPath, packageJson) {
1140
563
  const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
@@ -1147,12 +570,11 @@ function koaDetector(projectPath, packageJson) {
1147
570
  version = parseVersionString(deps['koa']);
1148
571
  sources.push({ type: 'package.json', field: 'dependencies.koa' });
1149
572
  }
1150
- // @types/koa
1151
573
  if (deps['@types/koa']) {
1152
574
  confidence += 10;
1153
575
  sources.push({ type: 'package.json', field: 'dependencies.@types/koa' });
1154
576
  }
1155
- const koaMiddleware = keys(deps).filter((d) => d.startsWith('koa-') || d.startsWith('@koa/'));
577
+ const koaMiddleware = index_cjs_js$2.keys(deps).filter((d) => d.startsWith('koa-') || d.startsWith('@koa/'));
1156
578
  if (koaMiddleware.length > 0) {
1157
579
  confidence += 10;
1158
580
  sources.push({ type: 'package.json', field: 'dependencies (koa middleware)' });
@@ -1164,42 +586,79 @@ function koaDetector(projectPath, packageJson) {
1164
586
  id: 'koa',
1165
587
  name: 'Koa',
1166
588
  version,
1167
- confidence: min(confidence, 100),
589
+ confidence: index_cjs_js$8.min(confidence, 100),
1168
590
  detectedFrom: sources,
1169
591
  };
1170
592
  }
1171
593
 
1172
594
  /**
1173
- * Detect Hono in project.
595
+ * Detect NestJS in project.
1174
596
  *
1175
597
  * @param projectPath - Project directory path
1176
598
  * @param packageJson - Optional pre-loaded package.json
1177
599
  * @returns Detection result or null if not detected
600
+ * @example Detecting NestJS framework
601
+ * ```typescript
602
+ * // Project with nest-cli.json and NestJS packages
603
+ * const pkg = {
604
+ * dependencies: {
605
+ * '@nestjs/core': '^10.2.0',
606
+ * '@nestjs/common': '^10.2.0',
607
+ * '@nestjs/platform-express': '^10.2.0',
608
+ * },
609
+ * }
610
+ *
611
+ * const result = nestDetector('/path/to/nest-project', pkg)
612
+ * // => {
613
+ * // id: 'nestjs',
614
+ * // name: 'NestJS',
615
+ * // version: '10.2.0',
616
+ * // configPath: 'nest-cli.json', // if present
617
+ * // confidence: 100,
618
+ * // detectedFrom: [
619
+ * // { type: 'package.json', field: 'dependencies.@nestjs/core' },
620
+ * // { type: 'package.json', field: 'dependencies.@nestjs/common' },
621
+ * // { type: 'config-file', path: 'nest-cli.json' },
622
+ * // { type: 'package.json', field: 'dependencies (@nestjs packages)' },
623
+ * // ],
624
+ * // }
625
+ * ```
1178
626
  */
1179
- function honoDetector(projectPath, packageJson) {
627
+ function nestDetector(projectPath, packageJson) {
1180
628
  const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
1181
629
  const sources = [];
1182
630
  let confidence = 0;
1183
631
  let version;
632
+ let configPath;
1184
633
  const deps = collectAllDependencies(pkg);
1185
- if (deps['hono']) {
1186
- confidence += 85;
1187
- version = parseVersionString(deps['hono']);
1188
- sources.push({ type: 'package.json', field: 'dependencies.hono' });
634
+ if (deps['@nestjs/core']) {
635
+ confidence += 70;
636
+ version = parseVersionString(deps['@nestjs/core']);
637
+ sources.push({ type: 'package.json', field: 'dependencies.@nestjs/core' });
1189
638
  }
1190
- const honoAdapters = keys(deps).filter((d) => d.startsWith('@hono/'));
1191
- if (honoAdapters.length > 0) {
639
+ if (deps['@nestjs/common']) {
1192
640
  confidence += 15;
1193
- sources.push({ type: 'package.json', field: 'dependencies (@hono adapters)' });
641
+ sources.push({ type: 'package.json', field: 'dependencies.@nestjs/common' });
642
+ }
643
+ if (exists(node_path.join(projectPath, 'nest-cli.json'))) {
644
+ confidence += 15;
645
+ configPath = 'nest-cli.json';
646
+ sources.push({ type: 'config-file', path: 'nest-cli.json' });
647
+ }
648
+ const nestPackages = index_cjs_js$2.keys(deps).filter((d) => d.startsWith('@nestjs/'));
649
+ if (nestPackages.length > 2) {
650
+ confidence += 5;
651
+ sources.push({ type: 'package.json', field: 'dependencies (@nestjs packages)' });
1194
652
  }
1195
653
  if (confidence === 0) {
1196
654
  return null;
1197
655
  }
1198
656
  return {
1199
- id: 'hono',
1200
- name: 'Hono',
657
+ id: 'nestjs',
658
+ name: 'NestJS',
1201
659
  version,
1202
- confidence: min(confidence, 100),
660
+ configPath,
661
+ confidence: index_cjs_js$8.min(confidence, 100),
1203
662
  detectedFrom: sources,
1204
663
  };
1205
664
  }
@@ -1213,102 +672,194 @@ const backendDetectors = [
1213
672
  { id: 'hono', name: 'Hono', detect: honoDetector },
1214
673
  ];
1215
674
 
1216
- /** Config patterns for Webpack */
1217
- const WEBPACK_CONFIG_PATTERNS = [
1218
- 'webpack.config.js',
1219
- 'webpack.config.ts',
1220
- 'webpack.config.cjs',
1221
- 'webpack.config.mjs',
1222
- 'webpack.config.babel.js',
1223
- ];
675
+ /** Config patterns for Babel */
676
+ const BABEL_CONFIG_PATTERNS = ['babel.config.js', 'babel.config.cjs', 'babel.config.mjs', 'babel.config.json', '.babelrc', '.babelrc.json', '.babelrc.js'];
1224
677
  /**
1225
- * Detect Webpack in project.
678
+ * Detect Babel in project.
1226
679
  *
1227
680
  * @param projectPath - Project directory path
1228
681
  * @param packageJson - Optional pre-loaded package.json
1229
682
  * @returns Detection result or null if not detected
683
+ *
684
+ * @example Detecting Babel compiler
685
+ * ```typescript
686
+ * const result = babelDetector('/path/to/project', {
687
+ * name: 'my-app',
688
+ * devDependencies: { '@babel/core': '^7.23.0', '@babel/preset-env': '^7.23.0' }
689
+ * })
690
+ * // => {
691
+ * // id: 'babel',
692
+ * // name: 'Babel',
693
+ * // version: '7.23.0',
694
+ * // confidence: 60,
695
+ * // detectedFrom: [
696
+ * // { type: 'package.json', field: 'dependencies.@babel/core' },
697
+ * // { type: 'package.json', field: 'dependencies (@babel packages)' }
698
+ * // ]
699
+ * // }
700
+ * ```
1230
701
  */
1231
- function webpackDetector(projectPath, packageJson) {
702
+ function babelDetector(projectPath, packageJson) {
1232
703
  const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
1233
704
  const sources = [];
1234
705
  let confidence = 0;
1235
706
  let version;
1236
707
  const deps = collectAllDependencies(pkg);
1237
- if (deps['webpack']) {
708
+ if (deps['@babel/core']) {
1238
709
  confidence += 50;
1239
- version = parseVersionString(deps['webpack']);
1240
- sources.push({ type: 'package.json', field: 'dependencies.webpack' });
710
+ version = parseVersionString(deps['@babel/core']);
711
+ sources.push({ type: 'package.json', field: 'dependencies.@babel/core' });
1241
712
  }
1242
- const configPath = locateConfigFile(projectPath, WEBPACK_CONFIG_PATTERNS);
713
+ const configPath = locateConfigFile(projectPath, BABEL_CONFIG_PATTERNS);
1243
714
  if (configPath) {
1244
715
  confidence += 40;
1245
716
  sources.push({ type: 'config-file', path: configPath });
1246
717
  }
1247
- if (deps['webpack-cli']) {
718
+ if (pkg && 'babel' in pkg) {
719
+ confidence += 30;
720
+ sources.push({ type: 'package.json', field: 'babel' });
721
+ }
722
+ const babelPackages = index_cjs_js$2.keys(deps).filter((d) => d.startsWith('@babel/'));
723
+ if (babelPackages.length > 1) {
1248
724
  confidence += 10;
1249
- sources.push({ type: 'package.json', field: 'dependencies.webpack-cli' });
725
+ sources.push({ type: 'package.json', field: 'dependencies (@babel packages)' });
1250
726
  }
1251
- const scriptMatches = filterScriptsByCommand(pkg?.scripts, 'webpack');
727
+ if (confidence === 0) {
728
+ return null;
729
+ }
730
+ return {
731
+ id: 'babel',
732
+ name: 'Babel',
733
+ version,
734
+ configPath,
735
+ confidence: index_cjs_js$8.min(confidence, 100),
736
+ detectedFrom: sources,
737
+ };
738
+ }
739
+
740
+ /**
741
+ * Detect esbuild in project.
742
+ *
743
+ * @param projectPath - Project directory path
744
+ * @param packageJson - Optional pre-loaded package.json
745
+ * @returns Detection result or null if not detected
746
+ *
747
+ * @example Detecting esbuild bundler
748
+ * ```typescript
749
+ * const result = esbuildDetector('/path/to/project', {
750
+ * name: 'my-lib',
751
+ * devDependencies: { 'esbuild': '^0.19.0' },
752
+ * scripts: { 'build': 'esbuild src/index.ts --bundle --outfile=dist/index.js' }
753
+ * })
754
+ * // => {
755
+ * // id: 'esbuild',
756
+ * // name: 'esbuild',
757
+ * // version: '0.19.0',
758
+ * // confidence: 80,
759
+ * // detectedFrom: [
760
+ * // { type: 'package.json', field: 'dependencies.esbuild' },
761
+ * // { type: 'package.json', field: 'scripts.build' }
762
+ * // ]
763
+ * // }
764
+ * ```
765
+ */
766
+ function esbuildDetector(projectPath, packageJson) {
767
+ const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
768
+ const sources = [];
769
+ let confidence = 0;
770
+ let version;
771
+ const deps = collectAllDependencies(pkg);
772
+ if (deps['esbuild']) {
773
+ confidence += 70;
774
+ version = parseVersionString(deps['esbuild']);
775
+ sources.push({ type: 'package.json', field: 'dependencies.esbuild' });
776
+ }
777
+ const esbuildPlugins = index_cjs_js$2.keys(deps).filter((d) => d.includes('esbuild-plugin') || d.includes('esbuild-'));
778
+ if (esbuildPlugins.length > 0) {
779
+ confidence += 15;
780
+ sources.push({ type: 'package.json', field: 'dependencies (esbuild plugins)' });
781
+ }
782
+ const scriptMatches = filterScriptsByCommand(pkg?.scripts, 'esbuild');
1252
783
  for (const name of scriptMatches) {
1253
- confidence = min(confidence + 5, 100);
784
+ confidence = index_cjs_js$8.min(confidence + 10, 100);
1254
785
  sources.push({ type: 'package.json', field: `scripts.${name}` });
1255
786
  }
1256
787
  if (confidence === 0) {
1257
788
  return null;
1258
789
  }
1259
790
  return {
1260
- id: 'webpack',
1261
- name: 'Webpack',
791
+ id: 'esbuild',
792
+ name: 'esbuild',
1262
793
  version,
1263
- configPath,
1264
- confidence: min(confidence, 100),
794
+ confidence: index_cjs_js$8.min(confidence, 100),
1265
795
  detectedFrom: sources,
1266
796
  };
1267
797
  }
1268
798
 
1269
- /** Config patterns for Vite */
1270
- const VITE_CONFIG_PATTERNS = ['vite.config.js', 'vite.config.ts', 'vite.config.mjs', 'vite.config.cjs'];
799
+ /** Config patterns for Parcel */
800
+ const PARCEL_CONFIG_PATTERNS = ['.parcelrc'];
1271
801
  /**
1272
- * Detect Vite in project.
802
+ * Detect Parcel in project.
1273
803
  *
1274
804
  * @param projectPath - Project directory path
1275
805
  * @param packageJson - Optional pre-loaded package.json
1276
806
  * @returns Detection result or null if not detected
807
+ *
808
+ * @example Detecting Parcel bundler
809
+ * ```typescript
810
+ * const result = parcelDetector('/path/to/project', {
811
+ * name: 'my-app',
812
+ * devDependencies: { 'parcel': '^2.10.0' },
813
+ * scripts: { 'dev': 'parcel src/index.html', 'build': 'parcel build src/index.html' }
814
+ * })
815
+ * // => {
816
+ * // id: 'parcel',
817
+ * // name: 'Parcel',
818
+ * // version: '2.10.0',
819
+ * // confidence: 80,
820
+ * // detectedFrom: [
821
+ * // { type: 'package.json', field: 'dependencies.parcel' },
822
+ * // { type: 'package.json', field: 'scripts.dev' },
823
+ * // { type: 'package.json', field: 'scripts.build' }
824
+ * // ]
825
+ * // }
826
+ * ```
1277
827
  */
1278
- function viteDetector(projectPath, packageJson) {
828
+ function parcelDetector(projectPath, packageJson) {
1279
829
  const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
1280
830
  const sources = [];
1281
831
  let confidence = 0;
1282
832
  let version;
1283
833
  const deps = collectAllDependencies(pkg);
1284
- if (deps['vite']) {
834
+ if (deps['parcel']) {
1285
835
  confidence += 60;
1286
- version = parseVersionString(deps['vite']);
1287
- sources.push({ type: 'package.json', field: 'dependencies.vite' });
836
+ version = parseVersionString(deps['parcel']);
837
+ sources.push({ type: 'package.json', field: 'dependencies.parcel' });
1288
838
  }
1289
- const configPath = locateConfigFile(projectPath, VITE_CONFIG_PATTERNS);
839
+ if (deps['parcel-bundler']) {
840
+ confidence += 60;
841
+ version = parseVersionString(deps['parcel-bundler']);
842
+ sources.push({ type: 'package.json', field: 'dependencies.parcel-bundler' });
843
+ }
844
+ const configPath = locateConfigFile(projectPath, PARCEL_CONFIG_PATTERNS);
1290
845
  if (configPath) {
1291
- confidence += 35;
846
+ confidence += 30;
1292
847
  sources.push({ type: 'config-file', path: configPath });
1293
848
  }
1294
- if (deps['vitest']) {
1295
- confidence += 10;
1296
- sources.push({ type: 'package.json', field: 'dependencies.vitest' });
1297
- }
1298
- const vitePlugins = keys(deps).filter((d) => d.startsWith('vite-plugin-') || d.startsWith('@vitejs/'));
1299
- if (vitePlugins.length > 0) {
1300
- confidence += 10;
1301
- sources.push({ type: 'package.json', field: 'dependencies (vite plugins)' });
849
+ const scriptMatches = filterScriptsByCommand(pkg?.scripts, 'parcel');
850
+ for (const name of scriptMatches) {
851
+ confidence = index_cjs_js$8.min(confidence + 10, 100);
852
+ sources.push({ type: 'package.json', field: `scripts.${name}` });
1302
853
  }
1303
854
  if (confidence === 0) {
1304
855
  return null;
1305
856
  }
1306
857
  return {
1307
- id: 'vite',
1308
- name: 'Vite',
858
+ id: 'parcel',
859
+ name: 'Parcel',
1309
860
  version,
1310
861
  configPath,
1311
- confidence: min(confidence, 100),
862
+ confidence: index_cjs_js$8.min(confidence, 100),
1312
863
  detectedFrom: sources,
1313
864
  };
1314
865
  }
@@ -1321,6 +872,28 @@ const ROLLUP_CONFIG_PATTERNS = ['rollup.config.js', 'rollup.config.ts', 'rollup.
1321
872
  * @param projectPath - Project directory path
1322
873
  * @param packageJson - Optional pre-loaded package.json
1323
874
  * @returns Detection result or null if not detected
875
+ *
876
+ * @example Detecting Rollup bundler
877
+ * ```typescript
878
+ * const result = rollupDetector('/path/to/project', {
879
+ * name: 'my-lib',
880
+ * devDependencies: {
881
+ * 'rollup': '^4.0.0',
882
+ * '@rollup/plugin-node-resolve': '^15.0.0',
883
+ * '@rollup/plugin-commonjs': '^25.0.0'
884
+ * }
885
+ * })
886
+ * // => {
887
+ * // id: 'rollup',
888
+ * // name: 'Rollup',
889
+ * // version: '4.0.0',
890
+ * // confidence: 65,
891
+ * // detectedFrom: [
892
+ * // { type: 'package.json', field: 'dependencies.rollup' },
893
+ * // { type: 'package.json', field: 'dependencies (rollup plugins)' }
894
+ * // ]
895
+ * // }
896
+ * ```
1324
897
  */
1325
898
  function rollupDetector(projectPath, packageJson) {
1326
899
  const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
@@ -1338,14 +911,14 @@ function rollupDetector(projectPath, packageJson) {
1338
911
  confidence += 40;
1339
912
  sources.push({ type: 'config-file', path: configPath });
1340
913
  }
1341
- const rollupPlugins = keys(deps).filter((d) => d.startsWith('@rollup/') || d.startsWith('rollup-plugin-'));
914
+ const rollupPlugins = index_cjs_js$2.keys(deps).filter((d) => d.startsWith('@rollup/') || d.startsWith('rollup-plugin-'));
1342
915
  if (rollupPlugins.length > 0) {
1343
916
  confidence += 10;
1344
917
  sources.push({ type: 'package.json', field: 'dependencies (rollup plugins)' });
1345
918
  }
1346
919
  const scriptMatches = filterScriptsByCommand(pkg?.scripts, 'rollup');
1347
920
  for (const name of scriptMatches) {
1348
- confidence = min(confidence + 5, 100);
921
+ confidence = index_cjs_js$8.min(confidence + 5, 100);
1349
922
  sources.push({ type: 'package.json', field: `scripts.${name}` });
1350
923
  }
1351
924
  if (confidence === 0) {
@@ -1356,280 +929,412 @@ function rollupDetector(projectPath, packageJson) {
1356
929
  name: 'Rollup',
1357
930
  version,
1358
931
  configPath,
1359
- confidence: min(confidence, 100),
932
+ confidence: index_cjs_js$8.min(confidence, 100),
1360
933
  detectedFrom: sources,
1361
934
  };
1362
935
  }
1363
936
 
937
+ /** Config patterns for SWC */
938
+ const SWC_CONFIG_PATTERNS = ['.swcrc', 'swc.config.js'];
1364
939
  /**
1365
- * Detect esbuild in project.
940
+ * Detect SWC in project.
1366
941
  *
1367
942
  * @param projectPath - Project directory path
1368
943
  * @param packageJson - Optional pre-loaded package.json
1369
944
  * @returns Detection result or null if not detected
945
+ *
946
+ * @example Detecting SWC compiler
947
+ * ```typescript
948
+ * const result = swcDetector('/path/to/project', {
949
+ * name: 'my-app',
950
+ * devDependencies: { '@swc/core': '^1.3.0', '@swc/cli': '^0.1.0' }
951
+ * })
952
+ * // => {
953
+ * // id: 'swc',
954
+ * // name: 'SWC',
955
+ * // version: '1.3.0',
956
+ * // confidence: 70,
957
+ * // detectedFrom: [
958
+ * // { type: 'package.json', field: 'dependencies.@swc/core' },
959
+ * // { type: 'package.json', field: 'dependencies.@swc/cli' }
960
+ * // ]
961
+ * // }
962
+ * ```
1370
963
  */
1371
- function esbuildDetector(projectPath, packageJson) {
964
+ function swcDetector(projectPath, packageJson) {
1372
965
  const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
1373
966
  const sources = [];
1374
967
  let confidence = 0;
1375
968
  let version;
1376
969
  const deps = collectAllDependencies(pkg);
1377
- if (deps['esbuild']) {
1378
- confidence += 70;
1379
- version = parseVersionString(deps['esbuild']);
1380
- sources.push({ type: 'package.json', field: 'dependencies.esbuild' });
970
+ if (deps['@swc/core']) {
971
+ confidence += 60;
972
+ version = parseVersionString(deps['@swc/core']);
973
+ sources.push({ type: 'package.json', field: 'dependencies.@swc/core' });
1381
974
  }
1382
- const esbuildPlugins = keys(deps).filter((d) => d.includes('esbuild-plugin') || d.includes('esbuild-'));
1383
- if (esbuildPlugins.length > 0) {
1384
- confidence += 15;
1385
- sources.push({ type: 'package.json', field: 'dependencies (esbuild plugins)' });
975
+ const configPath = locateConfigFile(projectPath, SWC_CONFIG_PATTERNS);
976
+ if (configPath) {
977
+ confidence += 35;
978
+ sources.push({ type: 'config-file', path: configPath });
1386
979
  }
1387
- const scriptMatches = filterScriptsByCommand(pkg?.scripts, 'esbuild');
1388
- for (const name of scriptMatches) {
1389
- confidence = min(confidence + 10, 100);
1390
- sources.push({ type: 'package.json', field: `scripts.${name}` });
980
+ if (deps['@swc/cli']) {
981
+ confidence += 10;
982
+ sources.push({ type: 'package.json', field: 'dependencies.@swc/cli' });
983
+ }
984
+ const swcPlugins = index_cjs_js$2.keys(deps).filter((d) => d.startsWith('@swc/') || d.includes('swc-plugin'));
985
+ if (swcPlugins.length > 1) {
986
+ confidence += 5;
987
+ sources.push({ type: 'package.json', field: 'dependencies (@swc packages)' });
1391
988
  }
1392
989
  if (confidence === 0) {
1393
990
  return null;
1394
991
  }
1395
992
  return {
1396
- id: 'esbuild',
1397
- name: 'esbuild',
993
+ id: 'swc',
994
+ name: 'SWC',
1398
995
  version,
1399
- confidence: min(confidence, 100),
996
+ configPath,
997
+ confidence: index_cjs_js$8.min(confidence, 100),
1400
998
  detectedFrom: sources,
1401
999
  };
1402
1000
  }
1403
1001
 
1404
- /** Config patterns for Babel */
1405
- const BABEL_CONFIG_PATTERNS = ['babel.config.js', 'babel.config.cjs', 'babel.config.mjs', 'babel.config.json', '.babelrc', '.babelrc.json', '.babelrc.js'];
1002
+ /** Config patterns for Vite */
1003
+ const VITE_CONFIG_PATTERNS = ['vite.config.js', 'vite.config.ts', 'vite.config.mjs', 'vite.config.cjs'];
1406
1004
  /**
1407
- * Detect Babel in project.
1005
+ * Detect Vite in project.
1408
1006
  *
1409
1007
  * @param projectPath - Project directory path
1410
1008
  * @param packageJson - Optional pre-loaded package.json
1411
1009
  * @returns Detection result or null if not detected
1010
+ *
1011
+ * @example Detecting Vite build tool
1012
+ * ```typescript
1013
+ * const result = viteDetector('/path/to/project', {
1014
+ * name: 'my-app',
1015
+ * devDependencies: {
1016
+ * 'vite': '^5.0.0',
1017
+ * '@vitejs/plugin-react': '^4.0.0',
1018
+ * 'vitest': '^1.0.0'
1019
+ * }
1020
+ * })
1021
+ * // => {
1022
+ * // id: 'vite',
1023
+ * // name: 'Vite',
1024
+ * // version: '5.0.0',
1025
+ * // confidence: 80,
1026
+ * // detectedFrom: [
1027
+ * // { type: 'package.json', field: 'dependencies.vite' },
1028
+ * // { type: 'package.json', field: 'dependencies.vitest' },
1029
+ * // { type: 'package.json', field: 'dependencies (vite plugins)' }
1030
+ * // ]
1031
+ * // }
1032
+ * ```
1412
1033
  */
1413
- function babelDetector(projectPath, packageJson) {
1034
+ function viteDetector(projectPath, packageJson) {
1414
1035
  const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
1415
1036
  const sources = [];
1416
1037
  let confidence = 0;
1417
1038
  let version;
1418
1039
  const deps = collectAllDependencies(pkg);
1419
- if (deps['@babel/core']) {
1420
- confidence += 50;
1421
- version = parseVersionString(deps['@babel/core']);
1422
- sources.push({ type: 'package.json', field: 'dependencies.@babel/core' });
1040
+ if (deps['vite']) {
1041
+ confidence += 60;
1042
+ version = parseVersionString(deps['vite']);
1043
+ sources.push({ type: 'package.json', field: 'dependencies.vite' });
1423
1044
  }
1424
- const configPath = locateConfigFile(projectPath, BABEL_CONFIG_PATTERNS);
1045
+ const configPath = locateConfigFile(projectPath, VITE_CONFIG_PATTERNS);
1425
1046
  if (configPath) {
1426
- confidence += 40;
1047
+ confidence += 35;
1427
1048
  sources.push({ type: 'config-file', path: configPath });
1428
1049
  }
1429
- if (pkg && 'babel' in pkg) {
1430
- confidence += 30;
1431
- sources.push({ type: 'package.json', field: 'babel' });
1050
+ if (deps['vitest']) {
1051
+ confidence += 10;
1052
+ sources.push({ type: 'package.json', field: 'dependencies.vitest' });
1432
1053
  }
1433
- const babelPackages = keys(deps).filter((d) => d.startsWith('@babel/'));
1434
- if (babelPackages.length > 1) {
1054
+ const vitePlugins = index_cjs_js$2.keys(deps).filter((d) => d.startsWith('vite-plugin-') || d.startsWith('@vitejs/'));
1055
+ if (vitePlugins.length > 0) {
1435
1056
  confidence += 10;
1436
- sources.push({ type: 'package.json', field: 'dependencies (@babel packages)' });
1057
+ sources.push({ type: 'package.json', field: 'dependencies (vite plugins)' });
1437
1058
  }
1438
1059
  if (confidence === 0) {
1439
1060
  return null;
1440
1061
  }
1441
1062
  return {
1442
- id: 'babel',
1443
- name: 'Babel',
1063
+ id: 'vite',
1064
+ name: 'Vite',
1444
1065
  version,
1445
1066
  configPath,
1446
- confidence: min(confidence, 100),
1067
+ confidence: index_cjs_js$8.min(confidence, 100),
1447
1068
  detectedFrom: sources,
1448
1069
  };
1449
1070
  }
1450
1071
 
1451
- /** Config patterns for SWC */
1452
- const SWC_CONFIG_PATTERNS = ['.swcrc', 'swc.config.js'];
1072
+ /** Config patterns for Webpack */
1073
+ const WEBPACK_CONFIG_PATTERNS = [
1074
+ 'webpack.config.js',
1075
+ 'webpack.config.ts',
1076
+ 'webpack.config.cjs',
1077
+ 'webpack.config.mjs',
1078
+ 'webpack.config.babel.js',
1079
+ ];
1453
1080
  /**
1454
- * Detect SWC in project.
1081
+ * Detect Webpack in project.
1455
1082
  *
1456
1083
  * @param projectPath - Project directory path
1457
1084
  * @param packageJson - Optional pre-loaded package.json
1458
1085
  * @returns Detection result or null if not detected
1086
+ *
1087
+ * @example Detecting Webpack bundler
1088
+ * ```typescript
1089
+ * const result = webpackDetector('/path/to/project', {
1090
+ * name: 'my-app',
1091
+ * devDependencies: { 'webpack': '^5.89.0', 'webpack-cli': '^5.1.0' },
1092
+ * scripts: { 'build': 'webpack --mode production' }
1093
+ * })
1094
+ * // => {
1095
+ * // id: 'webpack',
1096
+ * // name: 'Webpack',
1097
+ * // version: '5.89.0',
1098
+ * // confidence: 65,
1099
+ * // detectedFrom: [
1100
+ * // { type: 'package.json', field: 'dependencies.webpack' },
1101
+ * // { type: 'package.json', field: 'dependencies.webpack-cli' },
1102
+ * // { type: 'package.json', field: 'scripts.build' }
1103
+ * // ]
1104
+ * // }
1105
+ * ```
1459
1106
  */
1460
- function swcDetector(projectPath, packageJson) {
1107
+ function webpackDetector(projectPath, packageJson) {
1461
1108
  const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
1462
1109
  const sources = [];
1463
1110
  let confidence = 0;
1464
1111
  let version;
1465
1112
  const deps = collectAllDependencies(pkg);
1466
- if (deps['@swc/core']) {
1467
- confidence += 60;
1468
- version = parseVersionString(deps['@swc/core']);
1469
- sources.push({ type: 'package.json', field: 'dependencies.@swc/core' });
1113
+ if (deps['webpack']) {
1114
+ confidence += 50;
1115
+ version = parseVersionString(deps['webpack']);
1116
+ sources.push({ type: 'package.json', field: 'dependencies.webpack' });
1470
1117
  }
1471
- const configPath = locateConfigFile(projectPath, SWC_CONFIG_PATTERNS);
1118
+ const configPath = locateConfigFile(projectPath, WEBPACK_CONFIG_PATTERNS);
1472
1119
  if (configPath) {
1473
- confidence += 35;
1120
+ confidence += 40;
1474
1121
  sources.push({ type: 'config-file', path: configPath });
1475
1122
  }
1476
- if (deps['@swc/cli']) {
1123
+ if (deps['webpack-cli']) {
1477
1124
  confidence += 10;
1478
- sources.push({ type: 'package.json', field: 'dependencies.@swc/cli' });
1125
+ sources.push({ type: 'package.json', field: 'dependencies.webpack-cli' });
1479
1126
  }
1480
- const swcPlugins = keys(deps).filter((d) => d.startsWith('@swc/') || d.includes('swc-plugin'));
1481
- if (swcPlugins.length > 1) {
1482
- confidence += 5;
1483
- sources.push({ type: 'package.json', field: 'dependencies (@swc packages)' });
1127
+ const scriptMatches = filterScriptsByCommand(pkg?.scripts, 'webpack');
1128
+ for (const name of scriptMatches) {
1129
+ confidence = index_cjs_js$8.min(confidence + 5, 100);
1130
+ sources.push({ type: 'package.json', field: `scripts.${name}` });
1484
1131
  }
1485
1132
  if (confidence === 0) {
1486
1133
  return null;
1487
1134
  }
1488
1135
  return {
1489
- id: 'swc',
1490
- name: 'SWC',
1136
+ id: 'webpack',
1137
+ name: 'Webpack',
1491
1138
  version,
1492
1139
  configPath,
1493
- confidence: min(confidence, 100),
1140
+ confidence: index_cjs_js$8.min(confidence, 100),
1494
1141
  detectedFrom: sources,
1495
1142
  };
1496
1143
  }
1497
1144
 
1498
- /** Config patterns for Parcel */
1499
- const PARCEL_CONFIG_PATTERNS = ['.parcelrc'];
1145
+ /** All build tool detectors */
1146
+ const buildToolDetectors = [
1147
+ { id: 'webpack', name: 'Webpack', detect: webpackDetector },
1148
+ { id: 'vite', name: 'Vite', detect: viteDetector },
1149
+ { id: 'rollup', name: 'Rollup', detect: rollupDetector },
1150
+ { id: 'esbuild', name: 'esbuild', detect: esbuildDetector },
1151
+ { id: 'babel', name: 'Babel', detect: babelDetector },
1152
+ { id: 'swc', name: 'SWC', detect: swcDetector },
1153
+ { id: 'parcel', name: 'Parcel', detect: parcelDetector },
1154
+ ];
1155
+
1500
1156
  /**
1501
- * Detect Parcel in project.
1157
+ * Detect Angular in project.
1502
1158
  *
1503
1159
  * @param projectPath - Project directory path
1504
1160
  * @param packageJson - Optional pre-loaded package.json
1505
1161
  * @returns Detection result or null if not detected
1162
+ *
1163
+ * @example Detecting Angular framework
1164
+ * ```typescript
1165
+ * const result = angularDetector('/path/to/angular-app', {
1166
+ * dependencies: { '@angular/core': '^17.0.0', '@angular/cli': '^17.0.0' }
1167
+ * })
1168
+ * // => {
1169
+ * // id: 'angular',
1170
+ * // name: 'Angular',
1171
+ * // category: 'frontend',
1172
+ * // version: '17.0.0',
1173
+ * // confidence: 85,
1174
+ * // detectedFrom: [
1175
+ * // { type: 'package.json', field: 'dependencies.@angular/core' },
1176
+ * // { type: 'package.json', field: 'dependencies.@angular/cli' }
1177
+ * // ]
1178
+ * // }
1179
+ * ```
1506
1180
  */
1507
- function parcelDetector(projectPath, packageJson) {
1181
+ function angularDetector(projectPath, packageJson) {
1508
1182
  const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
1509
1183
  const sources = [];
1510
1184
  let confidence = 0;
1511
1185
  let version;
1512
1186
  const deps = collectAllDependencies(pkg);
1513
- if (deps['parcel']) {
1514
- confidence += 60;
1515
- version = parseVersionString(deps['parcel']);
1516
- sources.push({ type: 'package.json', field: 'dependencies.parcel' });
1187
+ if (deps['@angular/core']) {
1188
+ confidence += 70;
1189
+ version = parseVersionString(deps['@angular/core']);
1190
+ sources.push({ type: 'package.json', field: 'dependencies.@angular/core' });
1517
1191
  }
1518
- if (deps['parcel-bundler']) {
1519
- confidence += 60;
1520
- version = parseVersionString(deps['parcel-bundler']);
1521
- sources.push({ type: 'package.json', field: 'dependencies.parcel-bundler' });
1192
+ if (deps['@angular/cli']) {
1193
+ confidence += 15;
1194
+ sources.push({ type: 'package.json', field: 'dependencies.@angular/cli' });
1522
1195
  }
1523
- const configPath = locateConfigFile(projectPath, PARCEL_CONFIG_PATTERNS);
1524
- if (configPath) {
1525
- confidence += 30;
1526
- sources.push({ type: 'config-file', path: configPath });
1196
+ if (exists(node_path.join(projectPath, 'angular.json'))) {
1197
+ confidence += 15;
1198
+ sources.push({ type: 'config-file', path: 'angular.json' });
1527
1199
  }
1528
- const scriptMatches = filterScriptsByCommand(pkg?.scripts, 'parcel');
1529
- for (const name of scriptMatches) {
1530
- confidence = min(confidence + 10, 100);
1531
- sources.push({ type: 'package.json', field: `scripts.${name}` });
1200
+ if (deps['angular'] && !deps['@angular/core']) {
1201
+ return {
1202
+ id: 'angularjs',
1203
+ name: 'AngularJS (Legacy)',
1204
+ category: 'frontend',
1205
+ version: parseVersionString(deps['angular']),
1206
+ confidence: 80,
1207
+ detectedFrom: [{ type: 'package.json', field: 'dependencies.angular' }],
1208
+ };
1532
1209
  }
1533
1210
  if (confidence === 0) {
1534
1211
  return null;
1535
1212
  }
1536
1213
  return {
1537
- id: 'parcel',
1538
- name: 'Parcel',
1214
+ id: 'angular',
1215
+ name: 'Angular',
1216
+ category: 'frontend',
1539
1217
  version,
1540
- configPath,
1541
- confidence: min(confidence, 100),
1218
+ confidence: index_cjs_js$8.min(confidence, 100),
1542
1219
  detectedFrom: sources,
1543
1220
  };
1544
1221
  }
1545
1222
 
1546
- /** All build tool detectors */
1547
- const buildToolDetectors = [
1548
- { id: 'webpack', name: 'Webpack', detect: webpackDetector },
1549
- { id: 'vite', name: 'Vite', detect: viteDetector },
1550
- { id: 'rollup', name: 'Rollup', detect: rollupDetector },
1551
- { id: 'esbuild', name: 'esbuild', detect: esbuildDetector },
1552
- { id: 'babel', name: 'Babel', detect: babelDetector },
1553
- { id: 'swc', name: 'SWC', detect: swcDetector },
1554
- { id: 'parcel', name: 'Parcel', detect: parcelDetector },
1555
- ];
1556
-
1557
1223
  /**
1558
- * Detect React in project.
1224
+ * Detect Astro in project.
1559
1225
  *
1560
1226
  * @param projectPath - Project directory path
1561
1227
  * @param packageJson - Optional pre-loaded package.json
1562
1228
  * @returns Detection result or null if not detected
1229
+ *
1230
+ * @example Detecting Astro framework
1231
+ * ```typescript
1232
+ * const result = astroDetector('/path/to/astro-project', {
1233
+ * dependencies: { 'astro': '^4.0.0' }
1234
+ * })
1235
+ * // => {
1236
+ * // id: 'astro',
1237
+ * // name: 'Astro',
1238
+ * // category: 'meta-framework',
1239
+ * // version: '4.0.0',
1240
+ * // confidence: 70,
1241
+ * // detectedFrom: [{ type: 'package.json', field: 'dependencies.astro' }]
1242
+ * // }
1243
+ * ```
1563
1244
  */
1564
- function reactDetector(projectPath, packageJson) {
1245
+ function astroDetector(projectPath, packageJson) {
1565
1246
  const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
1566
1247
  const sources = [];
1567
1248
  let confidence = 0;
1568
1249
  let version;
1569
- const metaFrameworks = [];
1570
1250
  const deps = collectAllDependencies(pkg);
1571
- if (deps['react']) {
1572
- confidence += 60;
1573
- version = parseVersionString(deps['react']);
1574
- sources.push({ type: 'package.json', field: 'dependencies.react' });
1575
- }
1576
- if (deps['react-dom']) {
1577
- confidence += 20;
1578
- sources.push({ type: 'package.json', field: 'dependencies.react-dom' });
1251
+ if (deps['astro']) {
1252
+ confidence += 70;
1253
+ version = parseVersionString(deps['astro']);
1254
+ sources.push({ type: 'package.json', field: 'dependencies.astro' });
1579
1255
  }
1580
- if (deps['react-native']) {
1581
- confidence += 20;
1582
- sources.push({ type: 'package.json', field: 'dependencies.react-native' });
1256
+ if (exists(node_path.join(projectPath, 'astro.config.mjs')) ||
1257
+ exists(node_path.join(projectPath, 'astro.config.ts')) ||
1258
+ exists(node_path.join(projectPath, 'astro.config.js'))) {
1259
+ confidence += 25;
1260
+ sources.push({ type: 'config-file', path: 'astro.config.*' });
1583
1261
  }
1584
- const hasJsxFiles = exists(node_path.join(projectPath, 'src', 'App.tsx')) ||
1585
- exists(node_path.join(projectPath, 'src', 'App.jsx')) ||
1586
- exists(node_path.join(projectPath, 'src', 'index.tsx')) ||
1587
- exists(node_path.join(projectPath, 'src', 'index.jsx'));
1588
- if (hasJsxFiles) {
1589
- confidence += 10;
1590
- sources.push({ type: 'directory', path: 'src/*.tsx or src/*.jsx' });
1262
+ if (exists(node_path.join(projectPath, 'src', 'pages'))) {
1263
+ confidence += 5;
1264
+ sources.push({ type: 'directory', path: 'src/pages/' });
1591
1265
  }
1592
- if (deps['next']) {
1593
- metaFrameworks.push({
1594
- id: 'nextjs',
1595
- name: 'Next.js',
1596
- category: 'meta-framework',
1597
- version: parseVersionString(deps['next']),
1598
- confidence: 90,
1599
- detectedFrom: [{ type: 'package.json', field: 'dependencies.next' }],
1600
- });
1266
+ if (confidence === 0) {
1267
+ return null;
1601
1268
  }
1269
+ return {
1270
+ id: 'astro',
1271
+ name: 'Astro',
1272
+ category: 'meta-framework',
1273
+ version,
1274
+ confidence: index_cjs_js$8.min(confidence, 100),
1275
+ detectedFrom: sources,
1276
+ };
1277
+ }
1278
+
1279
+ /**
1280
+ * Detect Gatsby in project.
1281
+ *
1282
+ * @param projectPath - Project directory path
1283
+ * @param packageJson - Optional pre-loaded package.json
1284
+ * @returns Detection result or null if not detected
1285
+ *
1286
+ * @example Detecting Gatsby framework
1287
+ * ```typescript
1288
+ * const result = gatsbyDetector('/path/to/gatsby-blog', {
1289
+ * dependencies: {
1290
+ * 'gatsby': '^5.0.0',
1291
+ * 'gatsby-plugin-image': '^3.0.0',
1292
+ * 'gatsby-source-filesystem': '^5.0.0'
1293
+ * }
1294
+ * })
1295
+ * // => {
1296
+ * // id: 'gatsby',
1297
+ * // name: 'Gatsby',
1298
+ * // category: 'meta-framework',
1299
+ * // version: '5.0.0',
1300
+ * // confidence: 75,
1301
+ * // detectedFrom: [
1302
+ * // { type: 'package.json', field: 'dependencies.gatsby' },
1303
+ * // { type: 'package.json', field: 'dependencies (gatsby plugins)' }
1304
+ * // ]
1305
+ * // }
1306
+ * ```
1307
+ */
1308
+ function gatsbyDetector(projectPath, packageJson) {
1309
+ const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
1310
+ const sources = [];
1311
+ let confidence = 0;
1312
+ let version;
1313
+ const deps = collectAllDependencies(pkg);
1602
1314
  if (deps['gatsby']) {
1603
- metaFrameworks.push({
1604
- id: 'gatsby',
1605
- name: 'Gatsby',
1606
- category: 'meta-framework',
1607
- version: parseVersionString(deps['gatsby']),
1608
- confidence: 90,
1609
- detectedFrom: [{ type: 'package.json', field: 'dependencies.gatsby' }],
1610
- });
1315
+ confidence += 70;
1316
+ version = parseVersionString(deps['gatsby']);
1317
+ sources.push({ type: 'package.json', field: 'dependencies.gatsby' });
1611
1318
  }
1612
- if (deps['@remix-run/react'] || deps['remix']) {
1613
- metaFrameworks.push({
1614
- id: 'remix',
1615
- name: 'Remix',
1616
- category: 'meta-framework',
1617
- version: parseVersionString(deps['@remix-run/react'] ?? deps['remix']),
1618
- confidence: 90,
1619
- detectedFrom: [{ type: 'package.json', field: 'dependencies.@remix-run/react' }],
1620
- });
1319
+ if (exists(node_path.join(projectPath, 'gatsby-config.js')) || exists(node_path.join(projectPath, 'gatsby-config.ts'))) {
1320
+ confidence += 25;
1321
+ sources.push({ type: 'config-file', path: 'gatsby-config.*' });
1322
+ }
1323
+ const gatsbyPlugins = index_cjs_js$2.keys(deps).filter((d) => d.startsWith('gatsby-plugin-') || d.startsWith('gatsby-source-'));
1324
+ if (gatsbyPlugins.length > 0) {
1325
+ confidence += 5;
1326
+ sources.push({ type: 'package.json', field: 'dependencies (gatsby plugins)' });
1621
1327
  }
1622
1328
  if (confidence === 0) {
1623
1329
  return null;
1624
1330
  }
1625
1331
  return {
1626
- id: 'react',
1627
- name: 'React',
1628
- category: 'frontend',
1332
+ id: 'gatsby',
1333
+ name: 'Gatsby',
1334
+ category: 'meta-framework',
1629
1335
  version,
1630
- confidence: min(confidence, 100),
1336
+ confidence: index_cjs_js$8.min(confidence, 100),
1631
1337
  detectedFrom: sources,
1632
- metaFrameworks: metaFrameworks.length > 0 ? metaFrameworks : undefined,
1633
1338
  };
1634
1339
  }
1635
1340
 
@@ -1639,6 +1344,21 @@ function reactDetector(projectPath, packageJson) {
1639
1344
  * @param projectPath - Project directory path
1640
1345
  * @param packageJson - Optional pre-loaded package.json
1641
1346
  * @returns Detection result or null if not detected
1347
+ *
1348
+ * @example Detecting Next.js framework
1349
+ * ```typescript
1350
+ * const result = nextjsDetector('/path/to/nextjs-app', {
1351
+ * dependencies: { 'next': '^14.0.0', 'react': '^18.0.0' }
1352
+ * })
1353
+ * // => {
1354
+ * // id: 'nextjs',
1355
+ * // name: 'Next.js',
1356
+ * // category: 'meta-framework',
1357
+ * // version: '14.0.0',
1358
+ * // confidence: 70,
1359
+ * // detectedFrom: [{ type: 'package.json', field: 'dependencies.next' }]
1360
+ * // }
1361
+ * ```
1642
1362
  */
1643
1363
  function nextjsDetector(projectPath, packageJson) {
1644
1364
  const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
@@ -1672,231 +1392,335 @@ function nextjsDetector(projectPath, packageJson) {
1672
1392
  name: 'Next.js',
1673
1393
  category: 'meta-framework',
1674
1394
  version,
1675
- confidence: min(confidence, 100),
1395
+ confidence: index_cjs_js$8.min(confidence, 100),
1676
1396
  detectedFrom: sources,
1677
1397
  };
1678
1398
  }
1679
1399
 
1680
1400
  /**
1681
- * Detect Remix in project.
1401
+ * Detect Nuxt in project.
1682
1402
  *
1683
1403
  * @param projectPath - Project directory path
1684
1404
  * @param packageJson - Optional pre-loaded package.json
1685
1405
  * @returns Detection result or null if not detected
1406
+ *
1407
+ * @example Detecting Nuxt framework
1408
+ * ```typescript
1409
+ * const result = nuxtDetector('/path/to/nuxt-app', {
1410
+ * dependencies: { 'nuxt': '^3.0.0', 'vue': '^3.0.0' }
1411
+ * })
1412
+ * // => {
1413
+ * // id: 'nuxt',
1414
+ * // name: 'Nuxt',
1415
+ * // category: 'meta-framework',
1416
+ * // version: '3.0.0',
1417
+ * // confidence: 70,
1418
+ * // detectedFrom: [{ type: 'package.json', field: 'dependencies.nuxt' }]
1419
+ * // }
1420
+ * ```
1686
1421
  */
1687
- function remixDetector(projectPath, packageJson) {
1422
+ function nuxtDetector(projectPath, packageJson) {
1688
1423
  const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
1689
1424
  const sources = [];
1690
1425
  let confidence = 0;
1691
1426
  let version;
1692
1427
  const deps = collectAllDependencies(pkg);
1693
- // @remix-run packages
1694
- if (deps['@remix-run/react']) {
1428
+ if (deps['nuxt'] || deps['nuxt3']) {
1695
1429
  confidence += 70;
1696
- version = parseVersionString(deps['@remix-run/react']);
1697
- sources.push({ type: 'package.json', field: 'dependencies.@remix-run/react' });
1430
+ version = parseVersionString(deps['nuxt'] ?? deps['nuxt3']);
1431
+ sources.push({ type: 'package.json', field: 'dependencies.nuxt' });
1698
1432
  }
1699
- if (deps['@remix-run/node'] || deps['@remix-run/cloudflare'] || deps['@remix-run/deno']) {
1700
- confidence += 20;
1701
- sources.push({ type: 'package.json', field: 'dependencies.@remix-run/*' });
1433
+ if (exists(node_path.join(projectPath, 'nuxt.config.js')) || exists(node_path.join(projectPath, 'nuxt.config.ts'))) {
1434
+ confidence += 25;
1435
+ sources.push({ type: 'config-file', path: 'nuxt.config.*' });
1702
1436
  }
1703
- if (exists(node_path.join(projectPath, 'remix.config.js')) || exists(node_path.join(projectPath, 'remix.config.ts'))) {
1704
- confidence += 10;
1705
- sources.push({ type: 'config-file', path: 'remix.config.*' });
1437
+ if (exists(node_path.join(projectPath, 'pages'))) {
1438
+ confidence += 5;
1439
+ sources.push({ type: 'directory', path: 'pages/' });
1706
1440
  }
1707
1441
  if (confidence === 0) {
1708
1442
  return null;
1709
1443
  }
1710
1444
  return {
1711
- id: 'remix',
1712
- name: 'Remix',
1445
+ id: 'nuxt',
1446
+ name: 'Nuxt',
1713
1447
  category: 'meta-framework',
1714
1448
  version,
1715
- confidence: min(confidence, 100),
1449
+ confidence: index_cjs_js$8.min(confidence, 100),
1716
1450
  detectedFrom: sources,
1717
1451
  };
1718
1452
  }
1719
1453
 
1720
1454
  /**
1721
- * Detect Gatsby in project.
1455
+ * Detect Qwik in project.
1722
1456
  *
1723
1457
  * @param projectPath - Project directory path
1724
1458
  * @param packageJson - Optional pre-loaded package.json
1725
1459
  * @returns Detection result or null if not detected
1460
+ *
1461
+ * @example Detecting Qwik framework
1462
+ * ```typescript
1463
+ * const result = qwikDetector('/path/to/qwik-app', {
1464
+ * dependencies: {
1465
+ * '@builder.io/qwik': '^1.0.0',
1466
+ * '@builder.io/qwik-city': '^1.0.0'
1467
+ * }
1468
+ * })
1469
+ * // => {
1470
+ * // id: 'qwik',
1471
+ * // name: 'Qwik',
1472
+ * // category: 'frontend',
1473
+ * // version: '1.0.0',
1474
+ * // confidence: 90,
1475
+ * // detectedFrom: [
1476
+ * // { type: 'package.json', field: 'dependencies.@builder.io/qwik' },
1477
+ * // { type: 'package.json', field: 'dependencies.@builder.io/qwik-city' }
1478
+ * // ]
1479
+ * // }
1480
+ * ```
1726
1481
  */
1727
- function gatsbyDetector(projectPath, packageJson) {
1482
+ function qwikDetector(projectPath, packageJson) {
1728
1483
  const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
1729
1484
  const sources = [];
1730
1485
  let confidence = 0;
1731
1486
  let version;
1732
1487
  const deps = collectAllDependencies(pkg);
1733
- if (deps['gatsby']) {
1488
+ if (deps['@builder.io/qwik']) {
1734
1489
  confidence += 70;
1735
- version = parseVersionString(deps['gatsby']);
1736
- sources.push({ type: 'package.json', field: 'dependencies.gatsby' });
1490
+ version = parseVersionString(deps['@builder.io/qwik']);
1491
+ sources.push({ type: 'package.json', field: 'dependencies.@builder.io/qwik' });
1737
1492
  }
1738
- if (exists(node_path.join(projectPath, 'gatsby-config.js')) || exists(node_path.join(projectPath, 'gatsby-config.ts'))) {
1739
- confidence += 25;
1740
- sources.push({ type: 'config-file', path: 'gatsby-config.*' });
1493
+ if (deps['@builder.io/qwik-city']) {
1494
+ confidence += 20;
1495
+ sources.push({ type: 'package.json', field: 'dependencies.@builder.io/qwik-city' });
1741
1496
  }
1742
- const gatsbyPlugins = keys(deps).filter((d) => d.startsWith('gatsby-plugin-') || d.startsWith('gatsby-source-'));
1743
- if (gatsbyPlugins.length > 0) {
1744
- confidence += 5;
1745
- sources.push({ type: 'package.json', field: 'dependencies (gatsby plugins)' });
1497
+ if (exists(node_path.join(projectPath, 'qwik.config.ts')) || exists(node_path.join(projectPath, 'qwik.config.js'))) {
1498
+ confidence += 10;
1499
+ sources.push({ type: 'config-file', path: 'qwik.config.*' });
1746
1500
  }
1747
1501
  if (confidence === 0) {
1748
1502
  return null;
1749
1503
  }
1750
1504
  return {
1751
- id: 'gatsby',
1752
- name: 'Gatsby',
1753
- category: 'meta-framework',
1505
+ id: 'qwik',
1506
+ name: 'Qwik',
1507
+ category: 'frontend',
1754
1508
  version,
1755
- confidence: min(confidence, 100),
1509
+ confidence: index_cjs_js$8.min(confidence, 100),
1756
1510
  detectedFrom: sources,
1757
1511
  };
1758
1512
  }
1759
1513
 
1760
1514
  /**
1761
- * Detect Vue in project.
1515
+ * Detect React in project.
1762
1516
  *
1763
1517
  * @param projectPath - Project directory path
1764
1518
  * @param packageJson - Optional pre-loaded package.json
1765
1519
  * @returns Detection result or null if not detected
1520
+ *
1521
+ * @example Detecting React library
1522
+ * ```typescript
1523
+ * const result = reactDetector('/path/to/react-app', {
1524
+ * dependencies: { 'react': '^18.0.0', 'react-dom': '^18.0.0' }
1525
+ * })
1526
+ * // => {
1527
+ * // id: 'react',
1528
+ * // name: 'React',
1529
+ * // category: 'frontend',
1530
+ * // version: '18.0.0',
1531
+ * // confidence: 80,
1532
+ * // detectedFrom: [
1533
+ * // { type: 'package.json', field: 'dependencies.react' },
1534
+ * // { type: 'package.json', field: 'dependencies.react-dom' }
1535
+ * // ]
1536
+ * // }
1537
+ * ```
1766
1538
  */
1767
- function vueDetector(projectPath, packageJson) {
1539
+ function reactDetector(projectPath, packageJson) {
1768
1540
  const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
1769
1541
  const sources = [];
1770
1542
  let confidence = 0;
1771
1543
  let version;
1772
1544
  const metaFrameworks = [];
1773
1545
  const deps = collectAllDependencies(pkg);
1774
- if (deps['vue']) {
1775
- confidence += 70;
1776
- version = parseVersionString(deps['vue']);
1777
- sources.push({ type: 'package.json', field: 'dependencies.vue' });
1546
+ if (deps['react']) {
1547
+ confidence += 60;
1548
+ version = parseVersionString(deps['react']);
1549
+ sources.push({ type: 'package.json', field: 'dependencies.react' });
1778
1550
  }
1779
- if (deps['@vue/cli-service']) {
1780
- confidence += 15;
1781
- sources.push({ type: 'package.json', field: 'dependencies.@vue/cli-service' });
1551
+ if (deps['react-dom']) {
1552
+ confidence += 20;
1553
+ sources.push({ type: 'package.json', field: 'dependencies.react-dom' });
1782
1554
  }
1783
- const hasVueFiles = exists(node_path.join(projectPath, 'src', 'App.vue')) || exists(node_path.join(projectPath, 'src', 'main.vue'));
1784
- if (hasVueFiles) {
1555
+ if (deps['react-native']) {
1556
+ confidence += 20;
1557
+ sources.push({ type: 'package.json', field: 'dependencies.react-native' });
1558
+ }
1559
+ const hasJsxFiles = exists(node_path.join(projectPath, 'src', 'App.tsx')) ||
1560
+ exists(node_path.join(projectPath, 'src', 'App.jsx')) ||
1561
+ exists(node_path.join(projectPath, 'src', 'index.tsx')) ||
1562
+ exists(node_path.join(projectPath, 'src', 'index.jsx'));
1563
+ if (hasJsxFiles) {
1785
1564
  confidence += 10;
1786
- sources.push({ type: 'directory', path: 'src/*.vue' });
1565
+ sources.push({ type: 'directory', path: 'src/*.tsx or src/*.jsx' });
1787
1566
  }
1788
- if (exists(node_path.join(projectPath, 'vue.config.js'))) {
1789
- confidence += 5;
1790
- sources.push({ type: 'config-file', path: 'vue.config.js' });
1567
+ if (deps['next']) {
1568
+ metaFrameworks.push({
1569
+ id: 'nextjs',
1570
+ name: 'Next.js',
1571
+ category: 'meta-framework',
1572
+ version: parseVersionString(deps['next']),
1573
+ confidence: 90,
1574
+ detectedFrom: [{ type: 'package.json', field: 'dependencies.next' }],
1575
+ });
1791
1576
  }
1792
- if (deps['nuxt'] || deps['nuxt3']) {
1577
+ if (deps['gatsby']) {
1793
1578
  metaFrameworks.push({
1794
- id: 'nuxt',
1795
- name: 'Nuxt',
1579
+ id: 'gatsby',
1580
+ name: 'Gatsby',
1796
1581
  category: 'meta-framework',
1797
- version: parseVersionString(deps['nuxt'] ?? deps['nuxt3']),
1582
+ version: parseVersionString(deps['gatsby']),
1798
1583
  confidence: 90,
1799
- detectedFrom: [{ type: 'package.json', field: 'dependencies.nuxt' }],
1584
+ detectedFrom: [{ type: 'package.json', field: 'dependencies.gatsby' }],
1585
+ });
1586
+ }
1587
+ if (deps['@remix-run/react'] || deps['remix']) {
1588
+ metaFrameworks.push({
1589
+ id: 'remix',
1590
+ name: 'Remix',
1591
+ category: 'meta-framework',
1592
+ version: parseVersionString(deps['@remix-run/react'] ?? deps['remix']),
1593
+ confidence: 90,
1594
+ detectedFrom: [{ type: 'package.json', field: 'dependencies.@remix-run/react' }],
1800
1595
  });
1801
1596
  }
1802
1597
  if (confidence === 0) {
1803
1598
  return null;
1804
1599
  }
1805
1600
  return {
1806
- id: 'vue',
1807
- name: 'Vue',
1601
+ id: 'react',
1602
+ name: 'React',
1808
1603
  category: 'frontend',
1809
1604
  version,
1810
- confidence: min(confidence, 100),
1605
+ confidence: index_cjs_js$8.min(confidence, 100),
1811
1606
  detectedFrom: sources,
1812
1607
  metaFrameworks: metaFrameworks.length > 0 ? metaFrameworks : undefined,
1813
1608
  };
1814
1609
  }
1815
1610
 
1816
1611
  /**
1817
- * Detect Nuxt in project.
1612
+ * Detect Remix in project.
1818
1613
  *
1819
1614
  * @param projectPath - Project directory path
1820
1615
  * @param packageJson - Optional pre-loaded package.json
1821
1616
  * @returns Detection result or null if not detected
1617
+ *
1618
+ * @example Detecting Remix framework
1619
+ * ```typescript
1620
+ * const result = remixDetector('/path/to/remix-app', {
1621
+ * dependencies: {
1622
+ * '@remix-run/react': '^2.0.0',
1623
+ * '@remix-run/node': '^2.0.0'
1624
+ * }
1625
+ * })
1626
+ * // => {
1627
+ * // id: 'remix',
1628
+ * // name: 'Remix',
1629
+ * // category: 'meta-framework',
1630
+ * // version: '2.0.0',
1631
+ * // confidence: 90,
1632
+ * // detectedFrom: [
1633
+ * // { type: 'package.json', field: 'dependencies.@remix-run/react' },
1634
+ * // { type: 'package.json', field: 'dependencies.@remix-run/*' }
1635
+ * // ]
1636
+ * // }
1637
+ * ```
1822
1638
  */
1823
- function nuxtDetector(projectPath, packageJson) {
1639
+ function remixDetector(projectPath, packageJson) {
1824
1640
  const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
1825
1641
  const sources = [];
1826
1642
  let confidence = 0;
1827
1643
  let version;
1828
1644
  const deps = collectAllDependencies(pkg);
1829
- if (deps['nuxt'] || deps['nuxt3']) {
1645
+ if (deps['@remix-run/react']) {
1830
1646
  confidence += 70;
1831
- version = parseVersionString(deps['nuxt'] ?? deps['nuxt3']);
1832
- sources.push({ type: 'package.json', field: 'dependencies.nuxt' });
1647
+ version = parseVersionString(deps['@remix-run/react']);
1648
+ sources.push({ type: 'package.json', field: 'dependencies.@remix-run/react' });
1833
1649
  }
1834
- if (exists(node_path.join(projectPath, 'nuxt.config.js')) || exists(node_path.join(projectPath, 'nuxt.config.ts'))) {
1835
- confidence += 25;
1836
- sources.push({ type: 'config-file', path: 'nuxt.config.*' });
1650
+ if (deps['@remix-run/node'] || deps['@remix-run/cloudflare'] || deps['@remix-run/deno']) {
1651
+ confidence += 20;
1652
+ sources.push({ type: 'package.json', field: 'dependencies.@remix-run/*' });
1837
1653
  }
1838
- if (exists(node_path.join(projectPath, 'pages'))) {
1839
- confidence += 5;
1840
- sources.push({ type: 'directory', path: 'pages/' });
1654
+ if (exists(node_path.join(projectPath, 'remix.config.js')) || exists(node_path.join(projectPath, 'remix.config.ts'))) {
1655
+ confidence += 10;
1656
+ sources.push({ type: 'config-file', path: 'remix.config.*' });
1841
1657
  }
1842
1658
  if (confidence === 0) {
1843
1659
  return null;
1844
1660
  }
1845
1661
  return {
1846
- id: 'nuxt',
1847
- name: 'Nuxt',
1662
+ id: 'remix',
1663
+ name: 'Remix',
1848
1664
  category: 'meta-framework',
1849
1665
  version,
1850
- confidence: min(confidence, 100),
1666
+ confidence: index_cjs_js$8.min(confidence, 100),
1851
1667
  detectedFrom: sources,
1852
1668
  };
1853
1669
  }
1854
1670
 
1855
1671
  /**
1856
- * Detect Angular in project.
1672
+ * Detect Solid in project.
1857
1673
  *
1858
1674
  * @param projectPath - Project directory path
1859
1675
  * @param packageJson - Optional pre-loaded package.json
1860
1676
  * @returns Detection result or null if not detected
1677
+ *
1678
+ * @example Detecting Solid.js framework
1679
+ * ```typescript
1680
+ * const result = solidDetector('/path/to/solid-app', {
1681
+ * dependencies: { 'solid-js': '^1.8.0', 'vite-plugin-solid': '^2.0.0' }
1682
+ * })
1683
+ * // => {
1684
+ * // id: 'solid',
1685
+ * // name: 'Solid',
1686
+ * // category: 'frontend',
1687
+ * // version: '1.8.0',
1688
+ * // confidence: 90,
1689
+ * // detectedFrom: [
1690
+ * // { type: 'package.json', field: 'dependencies.solid-js' },
1691
+ * // { type: 'package.json', field: 'dependencies.vite-plugin-solid' }
1692
+ * // ]
1693
+ * // }
1694
+ * ```
1861
1695
  */
1862
- function angularDetector(projectPath, packageJson) {
1696
+ function solidDetector(projectPath, packageJson) {
1863
1697
  const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
1864
1698
  const sources = [];
1865
1699
  let confidence = 0;
1866
1700
  let version;
1867
1701
  const deps = collectAllDependencies(pkg);
1868
- if (deps['@angular/core']) {
1702
+ if (deps['solid-js']) {
1869
1703
  confidence += 70;
1870
- version = parseVersionString(deps['@angular/core']);
1871
- sources.push({ type: 'package.json', field: 'dependencies.@angular/core' });
1872
- }
1873
- if (deps['@angular/cli']) {
1874
- confidence += 15;
1875
- sources.push({ type: 'package.json', field: 'dependencies.@angular/cli' });
1704
+ version = parseVersionString(deps['solid-js']);
1705
+ sources.push({ type: 'package.json', field: 'dependencies.solid-js' });
1876
1706
  }
1877
- if (exists(node_path.join(projectPath, 'angular.json'))) {
1878
- confidence += 15;
1879
- sources.push({ type: 'config-file', path: 'angular.json' });
1707
+ if (deps['vite-plugin-solid']) {
1708
+ confidence += 20;
1709
+ sources.push({ type: 'package.json', field: 'dependencies.vite-plugin-solid' });
1880
1710
  }
1881
- if (deps['angular'] && !deps['@angular/core']) {
1882
- return {
1883
- id: 'angularjs',
1884
- name: 'AngularJS (Legacy)',
1885
- category: 'frontend',
1886
- version: parseVersionString(deps['angular']),
1887
- confidence: 80,
1888
- detectedFrom: [{ type: 'package.json', field: 'dependencies.angular' }],
1889
- };
1711
+ if (deps['solid-start'] || deps['@solidjs/start']) {
1712
+ confidence += 10;
1713
+ sources.push({ type: 'package.json', field: 'dependencies.solid-start' });
1890
1714
  }
1891
1715
  if (confidence === 0) {
1892
1716
  return null;
1893
1717
  }
1894
1718
  return {
1895
- id: 'angular',
1896
- name: 'Angular',
1719
+ id: 'solid',
1720
+ name: 'Solid',
1897
1721
  category: 'frontend',
1898
1722
  version,
1899
- confidence: min(confidence, 100),
1723
+ confidence: index_cjs_js$8.min(confidence, 100),
1900
1724
  detectedFrom: sources,
1901
1725
  };
1902
1726
  }
@@ -1907,6 +1731,21 @@ function angularDetector(projectPath, packageJson) {
1907
1731
  * @param projectPath - Project directory path
1908
1732
  * @param packageJson - Optional pre-loaded package.json
1909
1733
  * @returns Detection result or null if not detected
1734
+ *
1735
+ * @example Detecting Svelte framework
1736
+ * ```typescript
1737
+ * const result = svelteDetector('/path/to/svelte-app', {
1738
+ * devDependencies: { 'svelte': '^4.0.0' }
1739
+ * })
1740
+ * // => {
1741
+ * // id: 'svelte',
1742
+ * // name: 'Svelte',
1743
+ * // category: 'frontend',
1744
+ * // version: '4.0.0',
1745
+ * // confidence: 70,
1746
+ * // detectedFrom: [{ type: 'package.json', field: 'dependencies.svelte' }]
1747
+ * // }
1748
+ * ```
1910
1749
  */
1911
1750
  function svelteDetector(projectPath, packageJson) {
1912
1751
  const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
@@ -1947,7 +1786,7 @@ function svelteDetector(projectPath, packageJson) {
1947
1786
  name: 'Svelte',
1948
1787
  category: 'frontend',
1949
1788
  version,
1950
- confidence: min(confidence, 100),
1789
+ confidence: index_cjs_js$8.min(confidence, 100),
1951
1790
  detectedFrom: sources,
1952
1791
  metaFrameworks: metaFrameworks.length > 0 ? metaFrameworks : undefined,
1953
1792
  };
@@ -1959,6 +1798,21 @@ function svelteDetector(projectPath, packageJson) {
1959
1798
  * @param projectPath - Project directory path
1960
1799
  * @param packageJson - Optional pre-loaded package.json
1961
1800
  * @returns Detection result or null if not detected
1801
+ *
1802
+ * @example Detecting SvelteKit framework
1803
+ * ```typescript
1804
+ * const result = sveltekitDetector('/path/to/sveltekit-app', {
1805
+ * devDependencies: { '@sveltejs/kit': '^2.0.0', 'svelte': '^4.0.0' }
1806
+ * })
1807
+ * // => {
1808
+ * // id: 'sveltekit',
1809
+ * // name: 'SvelteKit',
1810
+ * // category: 'meta-framework',
1811
+ * // version: '2.0.0',
1812
+ * // confidence: 70,
1813
+ * // detectedFrom: [{ type: 'package.json', field: 'dependencies.@sveltejs/kit' }]
1814
+ * // }
1815
+ * ```
1962
1816
  */
1963
1817
  function sveltekitDetector(projectPath, packageJson) {
1964
1818
  const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
@@ -1966,7 +1820,6 @@ function sveltekitDetector(projectPath, packageJson) {
1966
1820
  let confidence = 0;
1967
1821
  let version;
1968
1822
  const deps = collectAllDependencies(pkg);
1969
- // @sveltejs/kit package
1970
1823
  if (deps['@sveltejs/kit']) {
1971
1824
  confidence += 70;
1972
1825
  version = parseVersionString(deps['@sveltejs/kit']);
@@ -1988,129 +1841,82 @@ function sveltekitDetector(projectPath, packageJson) {
1988
1841
  name: 'SvelteKit',
1989
1842
  category: 'meta-framework',
1990
1843
  version,
1991
- confidence: min(confidence, 100),
1844
+ confidence: index_cjs_js$8.min(confidence, 100),
1992
1845
  detectedFrom: sources,
1993
1846
  };
1994
1847
  }
1995
1848
 
1996
1849
  /**
1997
- * Detect Solid in project.
1850
+ * Detect Vue in project.
1998
1851
  *
1999
1852
  * @param projectPath - Project directory path
2000
1853
  * @param packageJson - Optional pre-loaded package.json
2001
1854
  * @returns Detection result or null if not detected
2002
- */
2003
- function solidDetector(projectPath, packageJson) {
2004
- const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
2005
- const sources = [];
2006
- let confidence = 0;
2007
- let version;
2008
- const deps = collectAllDependencies(pkg);
2009
- if (deps['solid-js']) {
2010
- confidence += 70;
2011
- version = parseVersionString(deps['solid-js']);
2012
- sources.push({ type: 'package.json', field: 'dependencies.solid-js' });
2013
- }
2014
- if (deps['vite-plugin-solid']) {
2015
- confidence += 20;
2016
- sources.push({ type: 'package.json', field: 'dependencies.vite-plugin-solid' });
2017
- }
2018
- if (deps['solid-start'] || deps['@solidjs/start']) {
2019
- confidence += 10;
2020
- sources.push({ type: 'package.json', field: 'dependencies.solid-start' });
2021
- }
2022
- if (confidence === 0) {
2023
- return null;
2024
- }
2025
- return {
2026
- id: 'solid',
2027
- name: 'Solid',
2028
- category: 'frontend',
2029
- version,
2030
- confidence: min(confidence, 100),
2031
- detectedFrom: sources,
2032
- };
2033
- }
2034
-
2035
- /**
2036
- * Detect Qwik in project.
2037
1855
  *
2038
- * @param projectPath - Project directory path
2039
- * @param packageJson - Optional pre-loaded package.json
2040
- * @returns Detection result or null if not detected
1856
+ * @example Detecting Vue.js framework
1857
+ * ```typescript
1858
+ * const result = vueDetector('/path/to/vue-app', {
1859
+ * dependencies: { 'vue': '^3.0.0', '@vue/cli-service': '^5.0.0' }
1860
+ * })
1861
+ * // => {
1862
+ * // id: 'vue',
1863
+ * // name: 'Vue',
1864
+ * // category: 'frontend',
1865
+ * // version: '3.0.0',
1866
+ * // confidence: 85,
1867
+ * // detectedFrom: [
1868
+ * // { type: 'package.json', field: 'dependencies.vue' },
1869
+ * // { type: 'package.json', field: 'dependencies.@vue/cli-service' }
1870
+ * // ]
1871
+ * // }
1872
+ * ```
2041
1873
  */
2042
- function qwikDetector(projectPath, packageJson) {
1874
+ function vueDetector(projectPath, packageJson) {
2043
1875
  const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
2044
1876
  const sources = [];
2045
1877
  let confidence = 0;
2046
1878
  let version;
1879
+ const metaFrameworks = [];
2047
1880
  const deps = collectAllDependencies(pkg);
2048
- // @builder.io/qwik package
2049
- if (deps['@builder.io/qwik']) {
1881
+ if (deps['vue']) {
2050
1882
  confidence += 70;
2051
- version = parseVersionString(deps['@builder.io/qwik']);
2052
- sources.push({ type: 'package.json', field: 'dependencies.@builder.io/qwik' });
1883
+ version = parseVersionString(deps['vue']);
1884
+ sources.push({ type: 'package.json', field: 'dependencies.vue' });
2053
1885
  }
2054
- // @builder.io/qwik-city
2055
- if (deps['@builder.io/qwik-city']) {
2056
- confidence += 20;
2057
- sources.push({ type: 'package.json', field: 'dependencies.@builder.io/qwik-city' });
1886
+ if (deps['@vue/cli-service']) {
1887
+ confidence += 15;
1888
+ sources.push({ type: 'package.json', field: 'dependencies.@vue/cli-service' });
2058
1889
  }
2059
- if (exists(node_path.join(projectPath, 'qwik.config.ts')) || exists(node_path.join(projectPath, 'qwik.config.js'))) {
1890
+ const hasVueFiles = exists(node_path.join(projectPath, 'src', 'App.vue')) || exists(node_path.join(projectPath, 'src', 'main.vue'));
1891
+ if (hasVueFiles) {
2060
1892
  confidence += 10;
2061
- sources.push({ type: 'config-file', path: 'qwik.config.*' });
2062
- }
2063
- if (confidence === 0) {
2064
- return null;
2065
- }
2066
- return {
2067
- id: 'qwik',
2068
- name: 'Qwik',
2069
- category: 'frontend',
2070
- version,
2071
- confidence: min(confidence, 100),
2072
- detectedFrom: sources,
2073
- };
2074
- }
2075
-
2076
- /**
2077
- * Detect Astro in project.
2078
- *
2079
- * @param projectPath - Project directory path
2080
- * @param packageJson - Optional pre-loaded package.json
2081
- * @returns Detection result or null if not detected
2082
- */
2083
- function astroDetector(projectPath, packageJson) {
2084
- const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
2085
- const sources = [];
2086
- let confidence = 0;
2087
- let version;
2088
- const deps = collectAllDependencies(pkg);
2089
- if (deps['astro']) {
2090
- confidence += 70;
2091
- version = parseVersionString(deps['astro']);
2092
- sources.push({ type: 'package.json', field: 'dependencies.astro' });
2093
- }
2094
- if (exists(node_path.join(projectPath, 'astro.config.mjs')) ||
2095
- exists(node_path.join(projectPath, 'astro.config.ts')) ||
2096
- exists(node_path.join(projectPath, 'astro.config.js'))) {
2097
- confidence += 25;
2098
- sources.push({ type: 'config-file', path: 'astro.config.*' });
1893
+ sources.push({ type: 'directory', path: 'src/*.vue' });
2099
1894
  }
2100
- if (exists(node_path.join(projectPath, 'src', 'pages'))) {
1895
+ if (exists(node_path.join(projectPath, 'vue.config.js'))) {
2101
1896
  confidence += 5;
2102
- sources.push({ type: 'directory', path: 'src/pages/' });
1897
+ sources.push({ type: 'config-file', path: 'vue.config.js' });
1898
+ }
1899
+ if (deps['nuxt'] || deps['nuxt3']) {
1900
+ metaFrameworks.push({
1901
+ id: 'nuxt',
1902
+ name: 'Nuxt',
1903
+ category: 'meta-framework',
1904
+ version: parseVersionString(deps['nuxt'] ?? deps['nuxt3']),
1905
+ confidence: 90,
1906
+ detectedFrom: [{ type: 'package.json', field: 'dependencies.nuxt' }],
1907
+ });
2103
1908
  }
2104
1909
  if (confidence === 0) {
2105
1910
  return null;
2106
1911
  }
2107
1912
  return {
2108
- id: 'astro',
2109
- name: 'Astro',
2110
- category: 'meta-framework',
1913
+ id: 'vue',
1914
+ name: 'Vue',
1915
+ category: 'frontend',
2111
1916
  version,
2112
- confidence: min(confidence, 100),
1917
+ confidence: index_cjs_js$8.min(confidence, 100),
2113
1918
  detectedFrom: sources,
1919
+ metaFrameworks: metaFrameworks.length > 0 ? metaFrameworks : undefined,
2114
1920
  };
2115
1921
  }
2116
1922
 
@@ -2137,6 +1943,14 @@ const frameworkDetectors = [
2137
1943
  * @param projectPath - Project directory path
2138
1944
  * @param packageJson - Optional pre-loaded package.json
2139
1945
  * @returns Detection result or null if not detected
1946
+ *
1947
+ * @example Detecting AngularJS framework
1948
+ * ```typescript
1949
+ * const result = angularJSDetector('/path/to/project', {
1950
+ * dependencies: { angular: '^1.8.0', 'angular-route': '^1.8.0' },
1951
+ * })
1952
+ * // => { id: 'angularjs', name: 'AngularJS', confidence: 85, version: '1.8.0', ... }
1953
+ * ```
2140
1954
  */
2141
1955
  function angularJSDetector(projectPath, packageJson) {
2142
1956
  const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
@@ -2144,23 +1958,19 @@ function angularJSDetector(projectPath, packageJson) {
2144
1958
  let confidence = 0;
2145
1959
  let version;
2146
1960
  const deps = collectAllDependencies(pkg);
2147
- // AngularJS package (angular, not @angular/core)
2148
1961
  if (deps['angular']) {
2149
1962
  confidence += 70;
2150
1963
  version = parseVersionString(deps['angular']);
2151
1964
  sources.push({ type: 'package.json', field: 'dependencies.angular' });
2152
1965
  }
2153
- // AngularJS router
2154
1966
  if (deps['angular-route']) {
2155
1967
  confidence += 15;
2156
1968
  sources.push({ type: 'package.json', field: 'dependencies.angular-route' });
2157
1969
  }
2158
- // AngularJS resource
2159
1970
  if (deps['angular-resource']) {
2160
1971
  confidence += 10;
2161
1972
  sources.push({ type: 'package.json', field: 'dependencies.angular-resource' });
2162
1973
  }
2163
- // AngularJS animate
2164
1974
  if (deps['angular-animate']) {
2165
1975
  confidence += 5;
2166
1976
  sources.push({ type: 'package.json', field: 'dependencies.angular-animate' });
@@ -2173,7 +1983,7 @@ function angularJSDetector(projectPath, packageJson) {
2173
1983
  name: 'AngularJS',
2174
1984
  category: 'legacy-frontend',
2175
1985
  version,
2176
- confidence: min(confidence, 100),
1986
+ confidence: index_cjs_js$8.min(confidence, 100),
2177
1987
  detectedFrom: sources,
2178
1988
  };
2179
1989
  }
@@ -2184,6 +1994,14 @@ function angularJSDetector(projectPath, packageJson) {
2184
1994
  * @param projectPath - Project directory path
2185
1995
  * @param packageJson - Optional pre-loaded package.json
2186
1996
  * @returns Detection result or null if not detected
1997
+ *
1998
+ * @example Detecting Backbone.js framework
1999
+ * ```typescript
2000
+ * const result = backboneDetector('/path/to/project', {
2001
+ * dependencies: { backbone: '^1.4.0', underscore: '^1.13.0' },
2002
+ * })
2003
+ * // => { id: 'backbone', name: 'Backbone.js', confidence: 85, version: '1.4.0', ... }
2004
+ * ```
2187
2005
  */
2188
2006
  function backboneDetector(projectPath, packageJson) {
2189
2007
  const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
@@ -2191,23 +2009,19 @@ function backboneDetector(projectPath, packageJson) {
2191
2009
  let confidence = 0;
2192
2010
  let version;
2193
2011
  const deps = collectAllDependencies(pkg);
2194
- // Backbone package
2195
2012
  if (deps['backbone']) {
2196
2013
  confidence += 70;
2197
2014
  version = parseVersionString(deps['backbone']);
2198
2015
  sources.push({ type: 'package.json', field: 'dependencies.backbone' });
2199
- // Underscore (commonly used with Backbone)
2200
2016
  if (deps['underscore']) {
2201
2017
  confidence += 15;
2202
2018
  sources.push({ type: 'package.json', field: 'dependencies.underscore' });
2203
2019
  }
2204
- // Lodash can be used as underscore replacement
2205
2020
  if (deps['lodash']) {
2206
2021
  confidence += 5;
2207
2022
  sources.push({ type: 'package.json', field: 'dependencies.lodash' });
2208
2023
  }
2209
2024
  }
2210
- // Marionette (Backbone framework)
2211
2025
  if (deps['backbone.marionette'] || deps['marionette']) {
2212
2026
  confidence += 10;
2213
2027
  sources.push({ type: 'package.json', field: 'dependencies.backbone.marionette' });
@@ -2220,7 +2034,7 @@ function backboneDetector(projectPath, packageJson) {
2220
2034
  name: 'Backbone.js',
2221
2035
  category: 'legacy-frontend',
2222
2036
  version,
2223
- confidence: min(confidence, 100),
2037
+ confidence: index_cjs_js$8.min(confidence, 100),
2224
2038
  detectedFrom: sources,
2225
2039
  };
2226
2040
  }
@@ -2231,6 +2045,15 @@ function backboneDetector(projectPath, packageJson) {
2231
2045
  * @param projectPath - Project directory path
2232
2046
  * @param packageJson - Optional pre-loaded package.json
2233
2047
  * @returns Detection result or null if not detected
2048
+ *
2049
+ * @example Detecting Ember.js framework
2050
+ * ```typescript
2051
+ * const result = emberDetector('/path/to/project', {
2052
+ * dependencies: { 'ember-source': '^4.0.0' },
2053
+ * devDependencies: { 'ember-cli': '^4.0.0' },
2054
+ * })
2055
+ * // => { id: 'ember', name: 'Ember.js', confidence: 90, version: '4.0.0', ... }
2056
+ * ```
2234
2057
  */
2235
2058
  function emberDetector(projectPath, packageJson) {
2236
2059
  const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
@@ -2238,18 +2061,15 @@ function emberDetector(projectPath, packageJson) {
2238
2061
  let confidence = 0;
2239
2062
  let version;
2240
2063
  const deps = collectAllDependencies(pkg);
2241
- // Ember source package
2242
2064
  if (deps['ember-source']) {
2243
2065
  confidence += 70;
2244
2066
  version = parseVersionString(deps['ember-source']);
2245
2067
  sources.push({ type: 'package.json', field: 'dependencies.ember-source' });
2246
2068
  }
2247
- // Ember CLI
2248
2069
  if (deps['ember-cli']) {
2249
2070
  confidence += 20;
2250
2071
  sources.push({ type: 'package.json', field: 'devDependencies.ember-cli' });
2251
2072
  }
2252
- // Ember Data
2253
2073
  if (deps['ember-data']) {
2254
2074
  confidence += 10;
2255
2075
  sources.push({ type: 'package.json', field: 'dependencies.ember-data' });
@@ -2262,7 +2082,7 @@ function emberDetector(projectPath, packageJson) {
2262
2082
  name: 'Ember.js',
2263
2083
  category: 'legacy-frontend',
2264
2084
  version,
2265
- confidence: min(confidence, 100),
2085
+ confidence: index_cjs_js$8.min(confidence, 100),
2266
2086
  detectedFrom: sources,
2267
2087
  };
2268
2088
  }
@@ -2273,50 +2093,105 @@ function emberDetector(projectPath, packageJson) {
2273
2093
  * @param projectPath - Project directory path
2274
2094
  * @param packageJson - Optional pre-loaded package.json
2275
2095
  * @returns Detection result or null if not detected
2096
+ *
2097
+ * @example Detecting jQuery library
2098
+ * ```typescript
2099
+ * const result = jqueryDetector('/path/to/project', {
2100
+ * dependencies: { jquery: '^3.6.0', 'jquery-ui': '^1.13.0' },
2101
+ * })
2102
+ * // => { id: 'jquery', name: 'jQuery', confidence: 90, version: '3.6.0', ... }
2103
+ * ```
2104
+ */
2105
+ function jqueryDetector(projectPath, packageJson) {
2106
+ const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
2107
+ const sources = [];
2108
+ let confidence = 0;
2109
+ let version;
2110
+ const deps = collectAllDependencies(pkg);
2111
+ if (deps['jquery']) {
2112
+ confidence += 80;
2113
+ version = parseVersionString(deps['jquery']);
2114
+ sources.push({ type: 'package.json', field: 'dependencies.jquery' });
2115
+ }
2116
+ if (deps['jquery-ui']) {
2117
+ confidence += 10;
2118
+ sources.push({ type: 'package.json', field: 'dependencies.jquery-ui' });
2119
+ }
2120
+ if (deps['jquery-validation']) {
2121
+ confidence += 5;
2122
+ sources.push({ type: 'package.json', field: 'dependencies.jquery-validation' });
2123
+ }
2124
+ if (confidence === 0) {
2125
+ return null;
2126
+ }
2127
+ return {
2128
+ id: 'jquery',
2129
+ name: 'jQuery',
2130
+ category: 'legacy-frontend',
2131
+ version,
2132
+ confidence: index_cjs_js$8.min(confidence, 100),
2133
+ detectedFrom: sources,
2134
+ };
2135
+ }
2136
+
2137
+ /** All legacy framework detectors */
2138
+ const legacyDetectors = [
2139
+ { id: 'angularjs', name: 'AngularJS', category: 'legacy-frontend', detect: angularJSDetector },
2140
+ { id: 'backbone', name: 'Backbone.js', category: 'legacy-frontend', detect: backboneDetector },
2141
+ { id: 'ember', name: 'Ember.js', category: 'legacy-frontend', detect: emberDetector },
2142
+ { id: 'jquery', name: 'jQuery', category: 'legacy-frontend', detect: jqueryDetector },
2143
+ ];
2144
+
2145
+ /**
2146
+ * Detect Biome in project.
2147
+ *
2148
+ * @param projectPath - Project directory path
2149
+ * @param packageJson - Optional pre-loaded package.json
2150
+ * @returns Detection result or null if not detected
2151
+ *
2152
+ * @example Detecting Biome linter
2153
+ * ```typescript
2154
+ * const result = biomeDetector('/path/to/project', {
2155
+ * devDependencies: { '@biomejs/biome': '^1.5.0' },
2156
+ * })
2157
+ * // => { id: 'biome', name: 'Biome', confidence: 70, version: '1.5.0', ... }
2158
+ * ```
2276
2159
  */
2277
- function jqueryDetector(projectPath, packageJson) {
2160
+ function biomeDetector(projectPath, packageJson) {
2278
2161
  const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
2279
2162
  const sources = [];
2280
2163
  let confidence = 0;
2164
+ let configPath;
2281
2165
  let version;
2282
2166
  const deps = collectAllDependencies(pkg);
2283
- // jQuery package
2284
- if (deps['jquery']) {
2285
- confidence += 80;
2286
- version = parseVersionString(deps['jquery']);
2287
- sources.push({ type: 'package.json', field: 'dependencies.jquery' });
2167
+ if (deps['@biomejs/biome']) {
2168
+ confidence += 70;
2169
+ version = parseVersionString(deps['@biomejs/biome']);
2170
+ sources.push({ type: 'package.json', field: 'dependencies.@biomejs/biome' });
2288
2171
  }
2289
- // jQuery UI
2290
- if (deps['jquery-ui']) {
2291
- confidence += 10;
2292
- sources.push({ type: 'package.json', field: 'dependencies.jquery-ui' });
2172
+ if (exists(node_path.join(projectPath, 'biome.json'))) {
2173
+ confidence += 30;
2174
+ configPath = 'biome.json';
2175
+ sources.push({ type: 'config-file', path: 'biome.json' });
2293
2176
  }
2294
- // jQuery plugins
2295
- if (deps['jquery-validation']) {
2296
- confidence += 5;
2297
- sources.push({ type: 'package.json', field: 'dependencies.jquery-validation' });
2177
+ if (!configPath && exists(node_path.join(projectPath, 'biome.jsonc'))) {
2178
+ confidence += 30;
2179
+ configPath = 'biome.jsonc';
2180
+ sources.push({ type: 'config-file', path: 'biome.jsonc' });
2298
2181
  }
2299
2182
  if (confidence === 0) {
2300
2183
  return null;
2301
2184
  }
2302
2185
  return {
2303
- id: 'jquery',
2304
- name: 'jQuery',
2305
- category: 'legacy-frontend',
2186
+ id: 'biome',
2187
+ name: 'Biome',
2306
2188
  version,
2307
- confidence: min(confidence, 100),
2189
+ configPath,
2190
+ confidence: index_cjs_js$8.min(confidence, 100),
2308
2191
  detectedFrom: sources,
2309
2192
  };
2310
2193
  }
2311
2194
 
2312
- /** All legacy framework detectors */
2313
- const legacyDetectors = [
2314
- { id: 'angularjs', name: 'AngularJS', category: 'legacy-frontend', detect: angularJSDetector },
2315
- { id: 'backbone', name: 'Backbone.js', category: 'legacy-frontend', detect: backboneDetector },
2316
- { id: 'ember', name: 'Ember.js', category: 'legacy-frontend', detect: emberDetector },
2317
- { id: 'jquery', name: 'jQuery', category: 'legacy-frontend', detect: jqueryDetector },
2318
- ];
2319
-
2320
2195
  /** Config patterns for ESLint */
2321
2196
  const ESLINT_CONFIG_PATTERNS = [
2322
2197
  'eslint.config.js',
@@ -2336,6 +2211,15 @@ const ESLINT_CONFIG_PATTERNS = [
2336
2211
  * @param projectPath - Project directory path
2337
2212
  * @param packageJson - Optional pre-loaded package.json
2338
2213
  * @returns Detection result or null if not detected
2214
+ *
2215
+ * @example Detecting ESLint linter
2216
+ * ```typescript
2217
+ * const result = eslintDetector('/path/to/project', {
2218
+ * devDependencies: { eslint: '^8.50.0', '@typescript-eslint/parser': '^6.0.0' },
2219
+ * scripts: { lint: 'eslint src/' },
2220
+ * })
2221
+ * // => { id: 'eslint', name: 'ESLint', confidence: 65, version: '8.50.0', ... }
2222
+ * ```
2339
2223
  */
2340
2224
  function eslintDetector(projectPath, packageJson) {
2341
2225
  const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
@@ -2357,7 +2241,7 @@ function eslintDetector(projectPath, packageJson) {
2357
2241
  confidence += 30;
2358
2242
  sources.push({ type: 'package.json', field: 'eslintConfig' });
2359
2243
  }
2360
- const eslintPlugins = keys(deps).filter((d) => d.startsWith('eslint-plugin-') || d.startsWith('@typescript-eslint/') || d.startsWith('eslint-config-'));
2244
+ const eslintPlugins = index_cjs_js$2.keys(deps).filter((d) => d.startsWith('eslint-plugin-') || d.startsWith('@typescript-eslint/') || d.startsWith('eslint-config-'));
2361
2245
  if (eslintPlugins.length > 0) {
2362
2246
  confidence += 10;
2363
2247
  sources.push({ type: 'package.json', field: 'dependencies (eslint plugins)' });
@@ -2375,7 +2259,7 @@ function eslintDetector(projectPath, packageJson) {
2375
2259
  name: 'ESLint',
2376
2260
  version,
2377
2261
  configPath,
2378
- confidence: min(confidence, 100),
2262
+ confidence: index_cjs_js$8.min(confidence, 100),
2379
2263
  detectedFrom: sources,
2380
2264
  };
2381
2265
  }
@@ -2399,6 +2283,15 @@ const PRETTIER_CONFIG_PATTERNS = [
2399
2283
  * @param projectPath - Project directory path
2400
2284
  * @param packageJson - Optional pre-loaded package.json
2401
2285
  * @returns Detection result or null if not detected
2286
+ *
2287
+ * @example Detecting Prettier formatter
2288
+ * ```typescript
2289
+ * const result = prettierDetector('/path/to/project', {
2290
+ * devDependencies: { prettier: '^3.0.0' },
2291
+ * scripts: { format: 'prettier --write .' },
2292
+ * })
2293
+ * // => { id: 'prettier', name: 'Prettier', confidence: 55, version: '3.0.0', ... }
2294
+ * ```
2402
2295
  */
2403
2296
  function prettierDetector(projectPath, packageJson) {
2404
2297
  const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
@@ -2420,12 +2313,11 @@ function prettierDetector(projectPath, packageJson) {
2420
2313
  confidence += 30;
2421
2314
  sources.push({ type: 'package.json', field: 'prettier' });
2422
2315
  }
2423
- // .prettierignore file
2424
2316
  if (exists(node_path.join(projectPath, '.prettierignore'))) {
2425
2317
  confidence += 10;
2426
2318
  sources.push({ type: 'config-file', path: '.prettierignore' });
2427
2319
  }
2428
- const prettierPlugins = keys(deps).filter((d) => d.startsWith('prettier-plugin-'));
2320
+ const prettierPlugins = index_cjs_js$2.keys(deps).filter((d) => d.startsWith('prettier-plugin-'));
2429
2321
  if (prettierPlugins.length > 0) {
2430
2322
  confidence += 5;
2431
2323
  sources.push({ type: 'package.json', field: 'dependencies (prettier plugins)' });
@@ -2443,7 +2335,7 @@ function prettierDetector(projectPath, packageJson) {
2443
2335
  name: 'Prettier',
2444
2336
  version,
2445
2337
  configPath,
2446
- confidence: min(confidence, 100),
2338
+ confidence: index_cjs_js$8.min(confidence, 100),
2447
2339
  detectedFrom: sources,
2448
2340
  };
2449
2341
  }
@@ -2462,6 +2354,14 @@ const STYLELINT_CONFIG_PATTERNS = [
2462
2354
  * @param projectPath - Project directory path
2463
2355
  * @param packageJson - Optional pre-loaded package.json
2464
2356
  * @returns Detection result or null if not detected
2357
+ *
2358
+ * @example Detecting Stylelint linter
2359
+ * ```typescript
2360
+ * const result = stylelintDetector('/path/to/project', {
2361
+ * devDependencies: { stylelint: '^15.0.0', 'stylelint-config-standard': '^30.0.0' },
2362
+ * })
2363
+ * // => { id: 'stylelint', name: 'Stylelint', confidence: 65, version: '15.0.0', ... }
2364
+ * ```
2465
2365
  */
2466
2366
  function stylelintDetector(projectPath, packageJson) {
2467
2367
  const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
@@ -2483,7 +2383,7 @@ function stylelintDetector(projectPath, packageJson) {
2483
2383
  break;
2484
2384
  }
2485
2385
  }
2486
- const stylelintPlugins = keys(deps).filter((d) => d.startsWith('stylelint-'));
2386
+ const stylelintPlugins = index_cjs_js$2.keys(deps).filter((d) => d.startsWith('stylelint-'));
2487
2387
  if (stylelintPlugins.length > 0) {
2488
2388
  confidence += 5;
2489
2389
  sources.push({ type: 'package.json', field: 'dependencies (stylelint plugins)' });
@@ -2496,50 +2396,7 @@ function stylelintDetector(projectPath, packageJson) {
2496
2396
  name: 'Stylelint',
2497
2397
  version,
2498
2398
  configPath,
2499
- confidence: min(confidence, 100),
2500
- detectedFrom: sources,
2501
- };
2502
- }
2503
-
2504
- /**
2505
- * Detect Biome in project.
2506
- *
2507
- * @param projectPath - Project directory path
2508
- * @param packageJson - Optional pre-loaded package.json
2509
- * @returns Detection result or null if not detected
2510
- */
2511
- function biomeDetector(projectPath, packageJson) {
2512
- const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
2513
- const sources = [];
2514
- let confidence = 0;
2515
- let configPath;
2516
- let version;
2517
- const deps = collectAllDependencies(pkg);
2518
- // @biomejs/biome package
2519
- if (deps['@biomejs/biome']) {
2520
- confidence += 70;
2521
- version = parseVersionString(deps['@biomejs/biome']);
2522
- sources.push({ type: 'package.json', field: 'dependencies.@biomejs/biome' });
2523
- }
2524
- if (exists(node_path.join(projectPath, 'biome.json'))) {
2525
- confidence += 30;
2526
- configPath = 'biome.json';
2527
- sources.push({ type: 'config-file', path: 'biome.json' });
2528
- }
2529
- if (!configPath && exists(node_path.join(projectPath, 'biome.jsonc'))) {
2530
- confidence += 30;
2531
- configPath = 'biome.jsonc';
2532
- sources.push({ type: 'config-file', path: 'biome.jsonc' });
2533
- }
2534
- if (confidence === 0) {
2535
- return null;
2536
- }
2537
- return {
2538
- id: 'biome',
2539
- name: 'Biome',
2540
- version,
2541
- configPath,
2542
- confidence: min(confidence, 100),
2399
+ confidence: index_cjs_js$8.min(confidence, 100),
2543
2400
  detectedFrom: sources,
2544
2401
  };
2545
2402
  }
@@ -2553,140 +2410,179 @@ const lintingDetectors = [
2553
2410
  ];
2554
2411
 
2555
2412
  /**
2556
- * Detect NX in project.
2413
+ * Detect Lerna in project.
2557
2414
  *
2558
2415
  * @param workspacePath - Workspace directory path
2559
2416
  * @param packageJson - Optional pre-loaded package.json
2560
2417
  * @returns Detection result or null if not detected
2418
+ *
2419
+ * @example Detecting Lerna monorepo
2420
+ * ```typescript
2421
+ * // Project with lerna.json config file
2422
+ * const result = lernaDetector('/path/to/lerna-project')
2423
+ * // => {
2424
+ * // id: 'lerna',
2425
+ * // name: 'Lerna',
2426
+ * // confidence: 80,
2427
+ * // configPath: 'lerna.json',
2428
+ * // detectedFrom: [{ type: 'config-file', path: 'lerna.json' }]
2429
+ * // }
2430
+ * ```
2561
2431
  */
2562
- function nxDetector(workspacePath, packageJson) {
2432
+ function lernaDetector(workspacePath, packageJson) {
2563
2433
  const pkg = packageJson ?? readPackageJsonIfExists(workspacePath);
2564
2434
  const sources = [];
2565
2435
  let confidence = 0;
2566
2436
  let version;
2567
- let workspaceLayout;
2568
- const nxJsonPath = node_path.join(workspacePath, 'nx.json');
2569
- if (exists(nxJsonPath)) {
2570
- confidence += 70;
2571
- sources.push({ type: 'config-file', path: 'nx.json' });
2437
+ let configPath;
2438
+ const lernaJsonPath = node_path.join(workspacePath, 'lerna.json');
2439
+ if (exists(lernaJsonPath)) {
2440
+ confidence += 80;
2441
+ configPath = 'lerna.json';
2442
+ sources.push({ type: 'config-file', path: 'lerna.json' });
2572
2443
  }
2573
2444
  const deps = collectAllDependencies(pkg);
2574
- if (deps['nx']) {
2575
- confidence += 20;
2576
- version = parseVersionString(deps['nx']);
2577
- sources.push({ type: 'package.json', field: 'dependencies.nx' });
2578
- }
2579
- const hasApps = exists(node_path.join(workspacePath, 'apps'));
2580
- const hasLibs = exists(node_path.join(workspacePath, 'libs'));
2581
- if (hasApps || hasLibs) {
2582
- confidence += 10;
2583
- sources.push({ type: 'directory', path: 'apps/ or libs/' });
2584
- workspaceLayout = {
2585
- appsDir: hasApps ? 'apps' : '',
2586
- libsDir: hasLibs ? 'libs' : '',
2587
- };
2445
+ if (deps['lerna']) {
2446
+ confidence += 15;
2447
+ version = parseVersionString(deps['lerna']);
2448
+ sources.push({ type: 'package.json', field: 'dependencies.lerna' });
2588
2449
  }
2589
- const nxPackages = keys(deps).filter((d) => d.startsWith('@nx/') || d.startsWith('@nrwl/'));
2590
- if (nxPackages.length > 0) {
2591
- confidence += 10;
2592
- sources.push({ type: 'package.json', field: '@nx/* packages' });
2450
+ if (exists(node_path.join(workspacePath, 'packages'))) {
2451
+ confidence += 5;
2452
+ sources.push({ type: 'directory', path: 'packages/' });
2593
2453
  }
2594
2454
  if (confidence === 0) {
2595
2455
  return null;
2596
2456
  }
2597
2457
  return {
2598
- id: 'nx',
2599
- name: 'NX',
2458
+ id: 'lerna',
2459
+ name: 'Lerna',
2600
2460
  version,
2601
- configPath: exists(nxJsonPath) ? 'nx.json' : undefined,
2602
- confidence: min(confidence, 100),
2461
+ configPath,
2462
+ confidence: index_cjs_js$8.min(confidence, 100),
2603
2463
  detectedFrom: sources,
2604
- workspaceLayout,
2605
2464
  };
2606
2465
  }
2607
2466
 
2608
2467
  /**
2609
- * Detect Turborepo in project.
2468
+ * Detect npm workspaces in project.
2610
2469
  *
2611
2470
  * @param workspacePath - Workspace directory path
2612
2471
  * @param packageJson - Optional pre-loaded package.json
2613
2472
  * @returns Detection result or null if not detected
2473
+ *
2474
+ * @example Detecting npm workspaces
2475
+ * ```typescript
2476
+ * // Project with workspaces in package.json and package-lock.json
2477
+ * const result = npmWorkspacesDetector('/path/to/npm-project')
2478
+ * // => {
2479
+ * // id: 'npm-workspaces',
2480
+ * // name: 'npm Workspaces',
2481
+ * // confidence: 90,
2482
+ * // configPath: 'package.json',
2483
+ * // detectedFrom: [
2484
+ * // { type: 'package.json', field: 'workspaces' },
2485
+ * // { type: 'lockfile', path: 'package-lock.json' }
2486
+ * // ]
2487
+ * // }
2488
+ * ```
2614
2489
  */
2615
- function turborepoDetector(workspacePath, packageJson) {
2490
+ function npmWorkspacesDetector(workspacePath, packageJson) {
2616
2491
  const pkg = packageJson ?? readPackageJsonIfExists(workspacePath);
2617
2492
  const sources = [];
2618
2493
  let confidence = 0;
2619
- let version;
2620
- let configPath;
2621
- const turboJsonPath = node_path.join(workspacePath, 'turbo.json');
2622
- if (exists(turboJsonPath)) {
2494
+ if (pkg?.workspaces) {
2623
2495
  confidence += 80;
2624
- configPath = 'turbo.json';
2625
- sources.push({ type: 'config-file', path: 'turbo.json' });
2496
+ sources.push({ type: 'package.json', field: 'workspaces' });
2626
2497
  }
2627
- const deps = collectAllDependencies(pkg);
2628
- if (deps['turbo']) {
2629
- confidence += 15;
2630
- version = parseVersionString(deps['turbo']);
2631
- sources.push({ type: 'package.json', field: 'dependencies.turbo' });
2498
+ if (exists(node_path.join(workspacePath, 'package-lock.json'))) {
2499
+ confidence += 10;
2500
+ sources.push({ type: 'lockfile', path: 'package-lock.json' });
2632
2501
  }
2633
- const scripts = pkg?.scripts ?? {};
2634
- if (values(scripts).some((s) => s?.includes('turbo'))) {
2635
- confidence += 5;
2636
- sources.push({ type: 'package.json', field: 'scripts (turbo commands)' });
2502
+ if (exists(node_path.join(workspacePath, 'yarn.lock'))) {
2503
+ return null;
2637
2504
  }
2638
2505
  if (confidence === 0) {
2639
2506
  return null;
2640
2507
  }
2641
2508
  return {
2642
- id: 'turborepo',
2643
- name: 'Turborepo',
2644
- version,
2645
- configPath,
2646
- confidence: min(confidence, 100),
2509
+ id: 'npm-workspaces',
2510
+ name: 'npm Workspaces',
2511
+ configPath: 'package.json',
2512
+ confidence: index_cjs_js$8.min(confidence, 100),
2647
2513
  detectedFrom: sources,
2648
2514
  };
2649
2515
  }
2650
2516
 
2651
2517
  /**
2652
- * Detect Lerna in project.
2518
+ * Detect NX in project.
2653
2519
  *
2654
2520
  * @param workspacePath - Workspace directory path
2655
2521
  * @param packageJson - Optional pre-loaded package.json
2656
2522
  * @returns Detection result or null if not detected
2523
+ *
2524
+ * @example Detecting NX workspace
2525
+ * ```typescript
2526
+ * // Project with nx.json and apps/libs directories
2527
+ * const result = nxDetector('/path/to/nx-workspace')
2528
+ * // => {
2529
+ * // id: 'nx',
2530
+ * // name: 'NX',
2531
+ * // confidence: 100,
2532
+ * // configPath: 'nx.json',
2533
+ * // version: '17.0.0',
2534
+ * // workspaceLayout: { appsDir: 'apps', libsDir: 'libs' },
2535
+ * // detectedFrom: [
2536
+ * // { type: 'config-file', path: 'nx.json' },
2537
+ * // { type: 'package.json', field: 'dependencies.nx' },
2538
+ * // { type: 'directory', path: 'apps/ or libs/' }
2539
+ * // ]
2540
+ * // }
2541
+ * ```
2657
2542
  */
2658
- function lernaDetector(workspacePath, packageJson) {
2543
+ function nxDetector(workspacePath, packageJson) {
2659
2544
  const pkg = packageJson ?? readPackageJsonIfExists(workspacePath);
2660
2545
  const sources = [];
2661
2546
  let confidence = 0;
2662
2547
  let version;
2663
- let configPath;
2664
- const lernaJsonPath = node_path.join(workspacePath, 'lerna.json');
2665
- if (exists(lernaJsonPath)) {
2666
- confidence += 80;
2667
- configPath = 'lerna.json';
2668
- sources.push({ type: 'config-file', path: 'lerna.json' });
2548
+ let workspaceLayout;
2549
+ const nxJsonPath = node_path.join(workspacePath, 'nx.json');
2550
+ if (exists(nxJsonPath)) {
2551
+ confidence += 70;
2552
+ sources.push({ type: 'config-file', path: 'nx.json' });
2669
2553
  }
2670
2554
  const deps = collectAllDependencies(pkg);
2671
- if (deps['lerna']) {
2672
- confidence += 15;
2673
- version = parseVersionString(deps['lerna']);
2674
- sources.push({ type: 'package.json', field: 'dependencies.lerna' });
2555
+ if (deps['nx']) {
2556
+ confidence += 20;
2557
+ version = parseVersionString(deps['nx']);
2558
+ sources.push({ type: 'package.json', field: 'dependencies.nx' });
2675
2559
  }
2676
- if (exists(node_path.join(workspacePath, 'packages'))) {
2677
- confidence += 5;
2678
- sources.push({ type: 'directory', path: 'packages/' });
2560
+ const hasApps = exists(node_path.join(workspacePath, 'apps'));
2561
+ const hasLibs = exists(node_path.join(workspacePath, 'libs'));
2562
+ if (hasApps || hasLibs) {
2563
+ confidence += 10;
2564
+ sources.push({ type: 'directory', path: 'apps/ or libs/' });
2565
+ workspaceLayout = {
2566
+ appsDir: hasApps ? 'apps' : '',
2567
+ libsDir: hasLibs ? 'libs' : '',
2568
+ };
2569
+ }
2570
+ const nxPackages = index_cjs_js$2.keys(deps).filter((d) => d.startsWith('@nx/') || d.startsWith('@nrwl/'));
2571
+ if (nxPackages.length > 0) {
2572
+ confidence += 10;
2573
+ sources.push({ type: 'package.json', field: '@nx/* packages' });
2679
2574
  }
2680
2575
  if (confidence === 0) {
2681
2576
  return null;
2682
2577
  }
2683
2578
  return {
2684
- id: 'lerna',
2685
- name: 'Lerna',
2579
+ id: 'nx',
2580
+ name: 'NX',
2686
2581
  version,
2687
- configPath,
2688
- confidence: min(confidence, 100),
2582
+ configPath: exists(nxJsonPath) ? 'nx.json' : undefined,
2583
+ confidence: index_cjs_js$8.min(confidence, 100),
2689
2584
  detectedFrom: sources,
2585
+ workspaceLayout,
2690
2586
  };
2691
2587
  }
2692
2588
 
@@ -2696,6 +2592,19 @@ function lernaDetector(workspacePath, packageJson) {
2696
2592
  * @param workspacePath - Workspace directory path
2697
2593
  * @param packageJson - Optional pre-loaded package.json
2698
2594
  * @returns Detection result or null if not detected
2595
+ *
2596
+ * @example Detecting Rush monorepo
2597
+ * ```typescript
2598
+ * // Project with rush.json config file
2599
+ * const result = rushDetector('/path/to/rush-project')
2600
+ * // => {
2601
+ * // id: 'rush',
2602
+ * // name: 'Rush',
2603
+ * // confidence: 90,
2604
+ * // configPath: 'rush.json',
2605
+ * // detectedFrom: [{ type: 'config-file', path: 'rush.json' }]
2606
+ * // }
2607
+ * ```
2699
2608
  */
2700
2609
  function rushDetector(workspacePath, packageJson) {
2701
2610
  const pkg = packageJson ?? readPackageJsonIfExists(workspacePath);
@@ -2723,77 +2632,71 @@ function rushDetector(workspacePath, packageJson) {
2723
2632
  return null;
2724
2633
  }
2725
2634
  return {
2726
- id: 'rush',
2727
- name: 'Rush',
2728
- version,
2729
- configPath,
2730
- confidence: min(confidence, 100),
2731
- detectedFrom: sources,
2732
- };
2733
- }
2734
-
2735
- /**
2736
- * Detect pnpm workspaces in project.
2737
- *
2738
- * @param workspacePath - Workspace directory path
2739
- * @returns Detection result or null if not detected
2740
- */
2741
- function pnpmWorkspacesDetector(workspacePath) {
2742
- const sources = [];
2743
- let confidence = 0;
2744
- let configPath;
2745
- const pnpmWorkspacePath = node_path.join(workspacePath, 'pnpm-workspace.yaml');
2746
- if (exists(pnpmWorkspacePath)) {
2747
- confidence += 90;
2748
- configPath = 'pnpm-workspace.yaml';
2749
- sources.push({ type: 'config-file', path: 'pnpm-workspace.yaml' });
2750
- }
2751
- if (exists(node_path.join(workspacePath, 'pnpm-lock.yaml'))) {
2752
- confidence += 10;
2753
- sources.push({ type: 'lockfile', path: 'pnpm-lock.yaml' });
2754
- }
2755
- if (confidence === 0) {
2756
- return null;
2757
- }
2758
- return {
2759
- id: 'pnpm-workspaces',
2760
- name: 'pnpm Workspaces',
2635
+ id: 'rush',
2636
+ name: 'Rush',
2637
+ version,
2761
2638
  configPath,
2762
- confidence: min(confidence, 100),
2639
+ confidence: index_cjs_js$8.min(confidence, 100),
2763
2640
  detectedFrom: sources,
2764
2641
  };
2765
2642
  }
2766
2643
 
2767
2644
  /**
2768
- * Detect npm workspaces in project.
2645
+ * Detect Turborepo in project.
2769
2646
  *
2770
2647
  * @param workspacePath - Workspace directory path
2771
2648
  * @param packageJson - Optional pre-loaded package.json
2772
2649
  * @returns Detection result or null if not detected
2650
+ *
2651
+ * @example Detecting Turborepo monorepo
2652
+ * ```typescript
2653
+ * // Project with turbo.json and turbo dependency
2654
+ * const result = turborepoDetector('/path/to/turbo-project')
2655
+ * // => {
2656
+ * // id: 'turborepo',
2657
+ * // name: 'Turborepo',
2658
+ * // confidence: 95,
2659
+ * // configPath: 'turbo.json',
2660
+ * // version: '2.0.0',
2661
+ * // detectedFrom: [
2662
+ * // { type: 'config-file', path: 'turbo.json' },
2663
+ * // { type: 'package.json', field: 'dependencies.turbo' }
2664
+ * // ]
2665
+ * // }
2666
+ * ```
2773
2667
  */
2774
- function npmWorkspacesDetector(workspacePath, packageJson) {
2668
+ function turborepoDetector(workspacePath, packageJson) {
2775
2669
  const pkg = packageJson ?? readPackageJsonIfExists(workspacePath);
2776
2670
  const sources = [];
2777
2671
  let confidence = 0;
2778
- if (pkg?.workspaces) {
2672
+ let version;
2673
+ let configPath;
2674
+ const turboJsonPath = node_path.join(workspacePath, 'turbo.json');
2675
+ if (exists(turboJsonPath)) {
2779
2676
  confidence += 80;
2780
- sources.push({ type: 'package.json', field: 'workspaces' });
2677
+ configPath = 'turbo.json';
2678
+ sources.push({ type: 'config-file', path: 'turbo.json' });
2781
2679
  }
2782
- if (exists(node_path.join(workspacePath, 'package-lock.json'))) {
2783
- confidence += 10;
2784
- sources.push({ type: 'lockfile', path: 'package-lock.json' });
2680
+ const deps = collectAllDependencies(pkg);
2681
+ if (deps['turbo']) {
2682
+ confidence += 15;
2683
+ version = parseVersionString(deps['turbo']);
2684
+ sources.push({ type: 'package.json', field: 'dependencies.turbo' });
2785
2685
  }
2786
- if (exists(node_path.join(workspacePath, 'yarn.lock'))) {
2787
- return null; // Let yarn workspace detector handle this
2686
+ const scripts = pkg?.scripts ?? {};
2687
+ if (index_cjs_js$2.values(scripts).some((s) => s?.includes('turbo'))) {
2688
+ confidence += 5;
2689
+ sources.push({ type: 'package.json', field: 'scripts (turbo commands)' });
2788
2690
  }
2789
2691
  if (confidence === 0) {
2790
2692
  return null;
2791
2693
  }
2792
2694
  return {
2793
- id: 'npm-workspaces',
2794
- name: 'npm Workspaces',
2795
- configPath: 'package.json',
2796
- confidence: min(confidence, 100),
2695
+ id: 'turborepo',
2696
+ name: 'Turborepo',
2697
+ version,
2698
+ configPath,
2699
+ confidence: index_cjs_js$8.min(confidence, 100),
2797
2700
  detectedFrom: sources,
2798
2701
  };
2799
2702
  }
@@ -2804,6 +2707,23 @@ function npmWorkspacesDetector(workspacePath, packageJson) {
2804
2707
  * @param workspacePath - Workspace directory path
2805
2708
  * @param packageJson - Optional pre-loaded package.json
2806
2709
  * @returns Detection result or null if not detected
2710
+ *
2711
+ * @example Detecting yarn workspaces
2712
+ * ```typescript
2713
+ * // Project with workspaces in package.json and yarn.lock
2714
+ * const result = yarnWorkspacesDetector('/path/to/yarn-project')
2715
+ * // => {
2716
+ * // id: 'yarn-workspaces',
2717
+ * // name: 'Yarn Workspaces',
2718
+ * // confidence: 100,
2719
+ * // configPath: 'package.json',
2720
+ * // detectedFrom: [
2721
+ * // { type: 'package.json', field: 'workspaces' },
2722
+ * // { type: 'lockfile', path: 'yarn.lock' },
2723
+ * // { type: 'config-file', path: '.yarnrc.yml' }
2724
+ * // ]
2725
+ * // }
2726
+ * ```
2807
2727
  */
2808
2728
  function yarnWorkspacesDetector(workspacePath, packageJson) {
2809
2729
  const pkg = packageJson ?? readPackageJsonIfExists(workspacePath);
@@ -2828,7 +2748,7 @@ function yarnWorkspacesDetector(workspacePath, packageJson) {
2828
2748
  id: 'yarn-workspaces',
2829
2749
  name: 'Yarn Workspaces',
2830
2750
  configPath: 'package.json',
2831
- confidence: min(confidence, 100),
2751
+ confidence: index_cjs_js$8.min(confidence, 100),
2832
2752
  detectedFrom: sources,
2833
2753
  };
2834
2754
  }
@@ -2844,111 +2764,129 @@ const monorepoDetectors = [
2844
2764
  { id: 'yarn-workspaces', name: 'Yarn Workspaces', detect: yarnWorkspacesDetector },
2845
2765
  ];
2846
2766
 
2847
- /** Config patterns for Jest */
2848
- const JEST_CONFIG_PATTERNS = ['jest.config.js', 'jest.config.ts', 'jest.config.mjs', 'jest.config.cjs', 'jest.config.json'];
2767
+ /** Config patterns for Cypress */
2768
+ const CYPRESS_CONFIG_PATTERNS = ['cypress.config.js', 'cypress.config.ts', 'cypress.config.mjs', 'cypress.json'];
2849
2769
  /**
2850
- * Detect Jest in project.
2770
+ * Detect Cypress in project.
2851
2771
  *
2852
2772
  * @param projectPath - Project directory path
2853
2773
  * @param packageJson - Optional pre-loaded package.json
2854
2774
  * @returns Detection result or null if not detected
2775
+ *
2776
+ * @example Detecting Cypress testing framework
2777
+ * ```typescript
2778
+ * import { cypressDetector } from '@hyperfrontend/project-scope'
2779
+ *
2780
+ * const result = cypressDetector('./my-project')
2781
+ * if (result) {
2782
+ * console.log(`Cypress ${result.version} detected (${result.confidence}% confidence)`)
2783
+ * // => "Cypress 13.6.0 detected (95% confidence)"
2784
+ * }
2785
+ * ```
2855
2786
  */
2856
- function jestDetector(projectPath, packageJson) {
2787
+ function cypressDetector(projectPath, packageJson) {
2857
2788
  const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
2858
2789
  const sources = [];
2859
2790
  let confidence = 0;
2860
2791
  let version;
2861
2792
  const deps = collectAllDependencies(pkg);
2862
- if (deps['jest']) {
2793
+ if (deps['cypress']) {
2863
2794
  confidence += 60;
2864
- version = parseVersionString(deps['jest']);
2865
- sources.push({ type: 'package.json', field: 'dependencies.jest' });
2795
+ version = parseVersionString(deps['cypress']);
2796
+ sources.push({ type: 'package.json', field: 'dependencies.cypress' });
2866
2797
  }
2867
- const configPath = locateConfigFile(projectPath, JEST_CONFIG_PATTERNS);
2798
+ const configPath = locateConfigFile(projectPath, CYPRESS_CONFIG_PATTERNS);
2868
2799
  if (configPath) {
2869
2800
  confidence += 30;
2870
2801
  sources.push({ type: 'config-file', path: configPath });
2871
2802
  }
2872
- if (pkg && 'jest' in pkg) {
2873
- confidence += 20;
2874
- sources.push({ type: 'package.json', field: 'jest' });
2875
- }
2876
- const testScript = pkg?.scripts?.['test'] ?? '';
2877
- if (testScript.includes('jest')) {
2803
+ if (exists(node_path.join(projectPath, 'cypress'))) {
2878
2804
  confidence += 10;
2879
- sources.push({ type: 'package.json', field: 'scripts.test' });
2880
- }
2881
- if (deps['@types/jest']) {
2882
- confidence += 5;
2883
- sources.push({ type: 'package.json', field: 'dependencies.@types/jest' });
2805
+ sources.push({ type: 'directory', path: 'cypress/' });
2884
2806
  }
2885
- if (deps['ts-jest']) {
2807
+ const e2eScript = pkg?.scripts?.['e2e'] ?? pkg?.scripts?.['test:e2e'] ?? '';
2808
+ if (e2eScript.includes('cypress')) {
2886
2809
  confidence += 5;
2887
- sources.push({ type: 'package.json', field: 'dependencies.ts-jest' });
2810
+ sources.push({ type: 'package.json', field: 'scripts.e2e or scripts.test:e2e' });
2888
2811
  }
2889
2812
  if (confidence === 0) {
2890
2813
  return null;
2891
2814
  }
2892
2815
  return {
2893
- id: 'jest',
2894
- name: 'Jest',
2895
- type: 'unit',
2816
+ id: 'cypress',
2817
+ name: 'Cypress',
2818
+ type: 'e2e',
2896
2819
  version,
2897
2820
  configPath,
2898
- confidence: min(confidence, 100),
2821
+ confidence: index_cjs_js$8.min(confidence, 100),
2899
2822
  detectedFrom: sources,
2900
2823
  };
2901
2824
  }
2902
2825
 
2903
- /** Config patterns for Vitest */
2904
- const VITEST_CONFIG_PATTERNS = ['vitest.config.js', 'vitest.config.ts', 'vitest.config.mjs'];
2826
+ /** Config patterns for Jest */
2827
+ const JEST_CONFIG_PATTERNS = ['jest.config.js', 'jest.config.ts', 'jest.config.mjs', 'jest.config.cjs', 'jest.config.json'];
2905
2828
  /**
2906
- * Detect Vitest in project.
2829
+ * Detect Jest in project.
2907
2830
  *
2908
2831
  * @param projectPath - Project directory path
2909
2832
  * @param packageJson - Optional pre-loaded package.json
2910
2833
  * @returns Detection result or null if not detected
2834
+ *
2835
+ * @example Detecting Jest testing framework
2836
+ * ```typescript
2837
+ * import { jestDetector } from '@hyperfrontend/project-scope'
2838
+ *
2839
+ * const result = jestDetector('./my-project')
2840
+ * if (result) {
2841
+ * console.log(`Jest ${result.version} detected`)
2842
+ * console.log('Sources:', result.detectedFrom.map(s => s.type))
2843
+ * // => "Sources: ['package.json', 'config-file']"
2844
+ * }
2845
+ * ```
2911
2846
  */
2912
- function vitestDetector(projectPath, packageJson) {
2847
+ function jestDetector(projectPath, packageJson) {
2913
2848
  const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
2914
2849
  const sources = [];
2915
2850
  let confidence = 0;
2916
2851
  let version;
2917
2852
  const deps = collectAllDependencies(pkg);
2918
- if (deps['vitest']) {
2919
- confidence += 70;
2920
- version = parseVersionString(deps['vitest']);
2921
- sources.push({ type: 'package.json', field: 'dependencies.vitest' });
2853
+ if (deps['jest']) {
2854
+ confidence += 60;
2855
+ version = parseVersionString(deps['jest']);
2856
+ sources.push({ type: 'package.json', field: 'dependencies.jest' });
2922
2857
  }
2923
- const configPath = locateConfigFile(projectPath, VITEST_CONFIG_PATTERNS);
2858
+ const configPath = locateConfigFile(projectPath, JEST_CONFIG_PATTERNS);
2924
2859
  if (configPath) {
2925
- confidence += 25;
2860
+ confidence += 30;
2926
2861
  sources.push({ type: 'config-file', path: configPath });
2927
2862
  }
2928
- if (!configPath) {
2929
- const viteConfig = exists(node_path.join(projectPath, 'vite.config.ts')) ||
2930
- exists(node_path.join(projectPath, 'vite.config.js')) ||
2931
- exists(node_path.join(projectPath, 'vite.config.mjs'));
2932
- if (viteConfig && deps['vitest']) {
2933
- confidence += 5;
2934
- sources.push({ type: 'config-file', path: 'vite.config.*' });
2935
- }
2863
+ if (pkg && 'jest' in pkg) {
2864
+ confidence += 20;
2865
+ sources.push({ type: 'package.json', field: 'jest' });
2936
2866
  }
2937
2867
  const testScript = pkg?.scripts?.['test'] ?? '';
2938
- if (testScript.includes('vitest')) {
2868
+ if (testScript.includes('jest')) {
2939
2869
  confidence += 10;
2940
2870
  sources.push({ type: 'package.json', field: 'scripts.test' });
2941
2871
  }
2872
+ if (deps['@types/jest']) {
2873
+ confidence += 5;
2874
+ sources.push({ type: 'package.json', field: 'dependencies.@types/jest' });
2875
+ }
2876
+ if (deps['ts-jest']) {
2877
+ confidence += 5;
2878
+ sources.push({ type: 'package.json', field: 'dependencies.ts-jest' });
2879
+ }
2942
2880
  if (confidence === 0) {
2943
2881
  return null;
2944
2882
  }
2945
2883
  return {
2946
- id: 'vitest',
2947
- name: 'Vitest',
2884
+ id: 'jest',
2885
+ name: 'Jest',
2948
2886
  type: 'unit',
2949
2887
  version,
2950
2888
  configPath,
2951
- confidence: min(confidence, 100),
2889
+ confidence: index_cjs_js$8.min(confidence, 100),
2952
2890
  detectedFrom: sources,
2953
2891
  };
2954
2892
  }
@@ -2961,6 +2899,17 @@ const MOCHA_CONFIG_PATTERNS = ['.mocharc.js', '.mocharc.json', '.mocharc.yaml',
2961
2899
  * @param projectPath - Project directory path
2962
2900
  * @param packageJson - Optional pre-loaded package.json
2963
2901
  * @returns Detection result or null if not detected
2902
+ *
2903
+ * @example Detecting Mocha testing framework
2904
+ * ```typescript
2905
+ * import { mochaDetector } from '@hyperfrontend/project-scope'
2906
+ *
2907
+ * const result = mochaDetector('./my-project')
2908
+ * if (result) {
2909
+ * console.log(`Mocha ${result.version} detected (${result.confidence}%)`)
2910
+ * // => "Mocha 10.2.0 detected (95%)"
2911
+ * }
2912
+ * ```
2964
2913
  */
2965
2914
  function mochaDetector(projectPath, packageJson) {
2966
2915
  const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
@@ -3000,42 +2949,58 @@ function mochaDetector(projectPath, packageJson) {
3000
2949
  type: 'unit',
3001
2950
  version,
3002
2951
  configPath,
3003
- confidence: min(confidence, 100),
2952
+ confidence: index_cjs_js$8.min(confidence, 100),
3004
2953
  detectedFrom: sources,
3005
2954
  };
3006
2955
  }
3007
2956
 
3008
- /** Config patterns for Cypress */
3009
- const CYPRESS_CONFIG_PATTERNS = ['cypress.config.js', 'cypress.config.ts', 'cypress.config.mjs', 'cypress.json'];
2957
+ /** Config patterns for Playwright */
2958
+ const PLAYWRIGHT_CONFIG_PATTERNS = ['playwright.config.js', 'playwright.config.ts', 'playwright.config.mjs'];
3010
2959
  /**
3011
- * Detect Cypress in project.
2960
+ * Detect Playwright in project.
3012
2961
  *
3013
2962
  * @param projectPath - Project directory path
3014
2963
  * @param packageJson - Optional pre-loaded package.json
3015
2964
  * @returns Detection result or null if not detected
2965
+ *
2966
+ * @example Detecting Playwright testing framework
2967
+ * ```typescript
2968
+ * import { playwrightDetector } from '@hyperfrontend/project-scope'
2969
+ *
2970
+ * const result = playwrightDetector('./my-project')
2971
+ * if (result) {
2972
+ * console.log(`Playwright ${result.version} (${result.type} tests)`)
2973
+ * // => "Playwright 1.42.0 (e2e tests)"
2974
+ * }
2975
+ * ```
3016
2976
  */
3017
- function cypressDetector(projectPath, packageJson) {
2977
+ function playwrightDetector(projectPath, packageJson) {
3018
2978
  const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
3019
2979
  const sources = [];
3020
2980
  let confidence = 0;
3021
2981
  let version;
3022
2982
  const deps = collectAllDependencies(pkg);
3023
- if (deps['cypress']) {
3024
- confidence += 60;
3025
- version = parseVersionString(deps['cypress']);
3026
- sources.push({ type: 'package.json', field: 'dependencies.cypress' });
2983
+ if (deps['@playwright/test']) {
2984
+ confidence += 70;
2985
+ version = parseVersionString(deps['@playwright/test']);
2986
+ sources.push({ type: 'package.json', field: 'dependencies.@playwright/test' });
3027
2987
  }
3028
- const configPath = locateConfigFile(projectPath, CYPRESS_CONFIG_PATTERNS);
2988
+ if (deps['playwright']) {
2989
+ confidence += 50;
2990
+ version = version ?? parseVersionString(deps['playwright']);
2991
+ sources.push({ type: 'package.json', field: 'dependencies.playwright' });
2992
+ }
2993
+ const configPath = locateConfigFile(projectPath, PLAYWRIGHT_CONFIG_PATTERNS);
3029
2994
  if (configPath) {
3030
- confidence += 30;
2995
+ confidence += 25;
3031
2996
  sources.push({ type: 'config-file', path: configPath });
3032
2997
  }
3033
- if (exists(node_path.join(projectPath, 'cypress'))) {
3034
- confidence += 10;
3035
- sources.push({ type: 'directory', path: 'cypress/' });
2998
+ if (exists(node_path.join(projectPath, 'e2e')) || exists(node_path.join(projectPath, 'tests'))) {
2999
+ confidence += 5;
3000
+ sources.push({ type: 'directory', path: 'e2e/ or tests/' });
3036
3001
  }
3037
3002
  const e2eScript = pkg?.scripts?.['e2e'] ?? pkg?.scripts?.['test:e2e'] ?? '';
3038
- if (e2eScript.includes('cypress')) {
3003
+ if (e2eScript.includes('playwright')) {
3039
3004
  confidence += 5;
3040
3005
  sources.push({ type: 'package.json', field: 'scripts.e2e or scripts.test:e2e' });
3041
3006
  }
@@ -3043,65 +3008,77 @@ function cypressDetector(projectPath, packageJson) {
3043
3008
  return null;
3044
3009
  }
3045
3010
  return {
3046
- id: 'cypress',
3047
- name: 'Cypress',
3011
+ id: 'playwright',
3012
+ name: 'Playwright',
3048
3013
  type: 'e2e',
3049
3014
  version,
3050
3015
  configPath,
3051
- confidence: min(confidence, 100),
3016
+ confidence: index_cjs_js$8.min(confidence, 100),
3052
3017
  detectedFrom: sources,
3053
3018
  };
3054
3019
  }
3055
3020
 
3056
- /** Config patterns for Playwright */
3057
- const PLAYWRIGHT_CONFIG_PATTERNS = ['playwright.config.js', 'playwright.config.ts', 'playwright.config.mjs'];
3021
+ /** Config patterns for Vitest */
3022
+ const VITEST_CONFIG_PATTERNS = ['vitest.config.js', 'vitest.config.ts', 'vitest.config.mjs'];
3058
3023
  /**
3059
- * Detect Playwright in project.
3024
+ * Detect Vitest in project.
3060
3025
  *
3061
3026
  * @param projectPath - Project directory path
3062
3027
  * @param packageJson - Optional pre-loaded package.json
3063
3028
  * @returns Detection result or null if not detected
3029
+ *
3030
+ * @example Detecting Vitest testing framework
3031
+ * ```typescript
3032
+ * import { vitestDetector } from '@hyperfrontend/project-scope'
3033
+ *
3034
+ * const result = vitestDetector('./my-project')
3035
+ * if (result) {
3036
+ * console.log(`Vitest ${result.version} detected`)
3037
+ * console.log('Config:', result.configPath)
3038
+ * // => "Config: vitest.config.ts"
3039
+ * }
3040
+ * ```
3064
3041
  */
3065
- function playwrightDetector(projectPath, packageJson) {
3042
+ function vitestDetector(projectPath, packageJson) {
3066
3043
  const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
3067
3044
  const sources = [];
3068
3045
  let confidence = 0;
3069
3046
  let version;
3070
3047
  const deps = collectAllDependencies(pkg);
3071
- if (deps['@playwright/test']) {
3048
+ if (deps['vitest']) {
3072
3049
  confidence += 70;
3073
- version = parseVersionString(deps['@playwright/test']);
3074
- sources.push({ type: 'package.json', field: 'dependencies.@playwright/test' });
3075
- }
3076
- if (deps['playwright']) {
3077
- confidence += 50;
3078
- version = version ?? parseVersionString(deps['playwright']);
3079
- sources.push({ type: 'package.json', field: 'dependencies.playwright' });
3050
+ version = parseVersionString(deps['vitest']);
3051
+ sources.push({ type: 'package.json', field: 'dependencies.vitest' });
3080
3052
  }
3081
- const configPath = locateConfigFile(projectPath, PLAYWRIGHT_CONFIG_PATTERNS);
3053
+ const configPath = locateConfigFile(projectPath, VITEST_CONFIG_PATTERNS);
3082
3054
  if (configPath) {
3083
3055
  confidence += 25;
3084
3056
  sources.push({ type: 'config-file', path: configPath });
3085
3057
  }
3086
- if (exists(node_path.join(projectPath, 'e2e')) || exists(node_path.join(projectPath, 'tests'))) {
3087
- confidence += 5;
3088
- sources.push({ type: 'directory', path: 'e2e/ or tests/' });
3058
+ if (!configPath) {
3059
+ const viteConfig = exists(node_path.join(projectPath, 'vite.config.ts')) ||
3060
+ exists(node_path.join(projectPath, 'vite.config.js')) ||
3061
+ exists(node_path.join(projectPath, 'vite.config.mjs'));
3062
+ if (viteConfig && deps['vitest']) {
3063
+ confidence += 5;
3064
+ sources.push({ type: 'config-file', path: 'vite.config.*' });
3065
+ }
3089
3066
  }
3090
- const e2eScript = pkg?.scripts?.['e2e'] ?? pkg?.scripts?.['test:e2e'] ?? '';
3091
- if (e2eScript.includes('playwright')) {
3092
- confidence += 5;
3093
- sources.push({ type: 'package.json', field: 'scripts.e2e or scripts.test:e2e' });
3067
+ const testScript = pkg?.scripts?.['test'] ?? '';
3068
+ if (testScript.includes('vitest')) {
3069
+ confidence += 10;
3070
+ sources.push({ type: 'package.json', field: 'scripts.test' });
3094
3071
  }
3095
3072
  if (confidence === 0) {
3096
3073
  return null;
3097
3074
  }
3098
3075
  return {
3099
- id: 'playwright',
3100
- name: 'Playwright',
3101
- type: 'e2e',
3076
+ id: 'vitest',
3077
+ name: 'Vitest',
3078
+ type: 'unit',
3102
3079
  version,
3103
3080
  configPath,
3104
- confidence: min(confidence, 100),
3081
+ confidence: index_cjs_js$8.min(confidence, 100),
3105
3082
  detectedFrom: sources,
3106
3083
  };
3107
3084
  }
@@ -3127,9 +3104,8 @@ function checkTsConfigStrict(projectPath) {
3127
3104
  if (!content)
3128
3105
  return undefined;
3129
3106
  try {
3130
- // Simple JSON parsing - doesn't handle comments but good enough for strict check
3131
3107
  const cleanContent = content.replace(/\/\*[\s\S]*?\*\/|\/\/.*/g, '');
3132
- const parsed = parse(cleanContent);
3108
+ const parsed = index_cjs_js$6.parse(cleanContent);
3133
3109
  return parsed?.compilerOptions?.strict === true;
3134
3110
  }
3135
3111
  catch {
@@ -3142,6 +3118,19 @@ function checkTsConfigStrict(projectPath) {
3142
3118
  * @param projectPath - Project directory path
3143
3119
  * @param packageJson - Optional pre-loaded package.json
3144
3120
  * @returns Detection result or null if not detected
3121
+ *
3122
+ * @example Detecting TypeScript
3123
+ * ```typescript
3124
+ * import { typescriptDetector } from '@hyperfrontend/project-scope'
3125
+ *
3126
+ * const result = typescriptDetector('./my-project')
3127
+ * if (result) {
3128
+ * console.log(`TypeScript ${result.version}`)
3129
+ * console.log(`Strict mode: ${result.strictMode ?? 'unknown'}`)
3130
+ * // => "TypeScript 5.3.0"
3131
+ * // => "Strict mode: true"
3132
+ * }
3133
+ * ```
3145
3134
  */
3146
3135
  function typescriptDetector(projectPath, packageJson) {
3147
3136
  const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
@@ -3150,19 +3139,16 @@ function typescriptDetector(projectPath, packageJson) {
3150
3139
  let configPath;
3151
3140
  let version;
3152
3141
  const deps = collectAllDependencies(pkg);
3153
- // TypeScript package
3154
3142
  if (deps['typescript']) {
3155
3143
  confidence += 50;
3156
3144
  version = parseVersionString(deps['typescript']);
3157
3145
  sources.push({ type: 'package.json', field: 'dependencies.typescript' });
3158
3146
  }
3159
- // tsconfig.json
3160
3147
  if (exists(node_path.join(projectPath, 'tsconfig.json'))) {
3161
3148
  confidence += 40;
3162
3149
  configPath = 'tsconfig.json';
3163
3150
  sources.push({ type: 'config-file', path: 'tsconfig.json' });
3164
3151
  }
3165
- // tsconfig.*.json variants
3166
3152
  const tsconfigVariants = ['tsconfig.build.json', 'tsconfig.lib.json', 'tsconfig.spec.json', 'tsconfig.app.json'];
3167
3153
  for (const variant of tsconfigVariants) {
3168
3154
  if (exists(node_path.join(projectPath, variant))) {
@@ -3171,8 +3157,7 @@ function typescriptDetector(projectPath, packageJson) {
3171
3157
  break;
3172
3158
  }
3173
3159
  }
3174
- // @types packages
3175
- const typePackages = keys(deps).filter((d) => d.startsWith('@types/'));
3160
+ const typePackages = index_cjs_js$2.keys(deps).filter((d) => d.startsWith('@types/'));
3176
3161
  if (typePackages.length > 0) {
3177
3162
  confidence += 10;
3178
3163
  sources.push({ type: 'package.json', field: '@types/* packages' });
@@ -3187,7 +3172,7 @@ function typescriptDetector(projectPath, packageJson) {
3187
3172
  version,
3188
3173
  configPath,
3189
3174
  strictMode,
3190
- confidence: min(confidence, 100),
3175
+ confidence: index_cjs_js$8.min(confidence, 100),
3191
3176
  detectedFrom: sources,
3192
3177
  };
3193
3178
  }
@@ -3197,6 +3182,17 @@ function typescriptDetector(projectPath, packageJson) {
3197
3182
  * @param projectPath - Project directory path
3198
3183
  * @param packageJson - Optional pre-loaded package.json
3199
3184
  * @returns Detection result or null if not detected
3185
+ *
3186
+ * @example Detecting Flow type system
3187
+ * ```typescript
3188
+ * import { flowDetector } from '@hyperfrontend/project-scope'
3189
+ *
3190
+ * const result = flowDetector('./my-project')
3191
+ * if (result) {
3192
+ * console.log(`Flow ${result.version} with config: ${result.configPath}`)
3193
+ * // => "Flow 0.232.0 with config: .flowconfig"
3194
+ * }
3195
+ * ```
3200
3196
  */
3201
3197
  function flowDetector(projectPath, packageJson) {
3202
3198
  const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
@@ -3205,24 +3201,20 @@ function flowDetector(projectPath, packageJson) {
3205
3201
  let configPath;
3206
3202
  let version;
3207
3203
  const deps = collectAllDependencies(pkg);
3208
- // flow-bin package
3209
3204
  if (deps['flow-bin']) {
3210
3205
  confidence += 60;
3211
3206
  version = parseVersionString(deps['flow-bin']);
3212
3207
  sources.push({ type: 'package.json', field: 'dependencies.flow-bin' });
3213
3208
  }
3214
- // .flowconfig
3215
3209
  if (exists(node_path.join(projectPath, '.flowconfig'))) {
3216
3210
  confidence += 40;
3217
3211
  configPath = '.flowconfig';
3218
3212
  sources.push({ type: 'config-file', path: '.flowconfig' });
3219
3213
  }
3220
- // flow-typed directory
3221
3214
  if (exists(node_path.join(projectPath, 'flow-typed'))) {
3222
3215
  confidence += 10;
3223
3216
  sources.push({ type: 'directory', path: 'flow-typed/' });
3224
3217
  }
3225
- // @babel/preset-flow
3226
3218
  if (deps['@babel/preset-flow']) {
3227
3219
  confidence += 10;
3228
3220
  sources.push({ type: 'package.json', field: 'dependencies.@babel/preset-flow' });
@@ -3235,7 +3227,7 @@ function flowDetector(projectPath, packageJson) {
3235
3227
  name: 'Flow',
3236
3228
  version,
3237
3229
  configPath,
3238
- confidence: min(confidence, 100),
3230
+ confidence: index_cjs_js$8.min(confidence, 100),
3239
3231
  detectedFrom: sources,
3240
3232
  };
3241
3233
  }
@@ -3246,7 +3238,6 @@ function flowDetector(projectPath, packageJson) {
3246
3238
  * @returns `true` if the content contains JSDoc type annotations.
3247
3239
  */
3248
3240
  function hasJsDocTypes(content) {
3249
- // Check for JSDoc type annotations
3250
3241
  return (content.includes('@type {') ||
3251
3242
  content.includes('@param {') ||
3252
3243
  content.includes('@returns {') ||
@@ -3259,26 +3250,35 @@ function hasJsDocTypes(content) {
3259
3250
  * @param projectPath - Project directory path
3260
3251
  * @param packageJson - Optional pre-loaded package.json
3261
3252
  * @returns Detection result or null if not detected
3253
+ *
3254
+ * @example Detecting JSDoc type annotations
3255
+ * ```typescript
3256
+ * import { jsdocDetector } from '@hyperfrontend/project-scope'
3257
+ *
3258
+ * const result = jsdocDetector('./my-project')
3259
+ * if (result) {
3260
+ * console.log('JSDoc types detected')
3261
+ * console.log('Sources:', result.detectedFrom.map(s => s.path ?? s.field))
3262
+ * // => "Sources: ['jsconfig.json', 'src/utils.js (JSDoc annotations)']"
3263
+ * }
3264
+ * ```
3262
3265
  */
3263
3266
  function jsdocDetector(projectPath, packageJson) {
3264
3267
  const pkg = packageJson ?? readPackageJsonIfExists(projectPath);
3265
3268
  const sources = [];
3266
3269
  let confidence = 0;
3267
3270
  const deps = collectAllDependencies(pkg);
3268
- // jsdoc package
3269
3271
  if (deps['jsdoc']) {
3270
3272
  confidence += 30;
3271
3273
  sources.push({ type: 'package.json', field: 'dependencies.jsdoc' });
3272
3274
  }
3273
- // typescript with checkJs (JSDoc type checking)
3274
3275
  if (deps['typescript']) {
3275
- // Check if checkJs is enabled in tsconfig
3276
3276
  const tsconfigPath = node_path.join(projectPath, 'tsconfig.json');
3277
3277
  const content = readFileIfExists(tsconfigPath);
3278
3278
  if (content) {
3279
3279
  try {
3280
3280
  const cleanContent = content.replace(/\/\*[\s\S]*?\*\/|\/\/.*/g, '');
3281
- const parsed = parse(cleanContent);
3281
+ const parsed = index_cjs_js$6.parse(cleanContent);
3282
3282
  if (parsed?.compilerOptions?.checkJs === true || parsed?.compilerOptions?.allowJs === true) {
3283
3283
  confidence += 30;
3284
3284
  sources.push({ type: 'config-file', path: 'tsconfig.json (checkJs/allowJs)' });
@@ -3289,12 +3289,10 @@ function jsdocDetector(projectPath, packageJson) {
3289
3289
  }
3290
3290
  }
3291
3291
  }
3292
- // Check for jsconfig.json (VS Code JS type checking)
3293
3292
  if (exists(node_path.join(projectPath, 'jsconfig.json'))) {
3294
3293
  confidence += 40;
3295
3294
  sources.push({ type: 'config-file', path: 'jsconfig.json' });
3296
3295
  }
3297
- // Sample check for JSDoc annotations in source files
3298
3296
  const srcDir = node_path.join(projectPath, 'src');
3299
3297
  if (exists(srcDir)) {
3300
3298
  try {
@@ -3319,7 +3317,7 @@ function jsdocDetector(projectPath, packageJson) {
3319
3317
  return {
3320
3318
  id: 'jsdoc',
3321
3319
  name: 'JSDoc',
3322
- confidence: min(confidence, 100),
3320
+ confidence: index_cjs_js$8.min(confidence, 100),
3323
3321
  detectedFrom: sources,
3324
3322
  };
3325
3323
  }
@@ -3345,8 +3343,6 @@ const detectAllCache = createCache({ ttl: 60000, maxSize: 50 });
3345
3343
  function isDetectAllOptions(value) {
3346
3344
  if (typeof value !== 'object' || value === null)
3347
3345
  return false;
3348
- // DetectAllOptions has skipCache or packageJson fields specifically
3349
- // PackageJson never has skipCache field
3350
3346
  return 'skipCache' in value || 'packageJson' in value;
3351
3347
  }
3352
3348
  /**
@@ -3359,7 +3355,7 @@ function isDetectAllOptions(value) {
3359
3355
  * @param packageJsonOrOptions - Optional pre-loaded package.json or options object
3360
3356
  * @returns All detection results organized by category
3361
3357
  *
3362
- * @example
3358
+ * @example Running all tech detectors
3363
3359
  * ```typescript
3364
3360
  * import { detectAll } from '@hyperfrontend/project-scope'
3365
3361
  *
@@ -3378,9 +3374,7 @@ function isDetectAllOptions(value) {
3378
3374
  * ```
3379
3375
  */
3380
3376
  function detectAll(projectPath, packageJsonOrOptions) {
3381
- // Handle backward-compatible arguments
3382
3377
  const options = isDetectAllOptions(packageJsonOrOptions) ? packageJsonOrOptions : { packageJson: packageJsonOrOptions };
3383
- // Check cache first (unless skipCache is true)
3384
3378
  if (!options.skipCache) {
3385
3379
  const cached = detectAllCache.get(projectPath);
3386
3380
  if (cached) {
@@ -3431,7 +3425,6 @@ function detectAll(projectPath, packageJsonOrOptions) {
3431
3425
  legacyFrameworks: result.legacyFrameworks.map((f) => f.id),
3432
3426
  testingFrameworks: result.testingFrameworks.map((f) => f.id),
3433
3427
  });
3434
- // Cache the result
3435
3428
  detectAllCache.set(projectPath, result);
3436
3429
  return result;
3437
3430
  }
@@ -3479,7 +3472,7 @@ function buildSummary(frontend, backend, testing) {
3479
3472
  * @param options - Identification options
3480
3473
  * @returns Framework identification result
3481
3474
  *
3482
- * @example
3475
+ * @example Identifying all frameworks in project
3483
3476
  * ```typescript
3484
3477
  * import { identifyFrameworks } from '@hyperfrontend/project-scope'
3485
3478
  *
@@ -3594,6 +3587,14 @@ function identifyFrameworks(projectPath, options) {
3594
3587
  * Clear the framework identification cache.
3595
3588
  *
3596
3589
  * Useful for testing or when the project files have changed.
3590
+ *
3591
+ * @example Clearing the framework cache
3592
+ * ```typescript
3593
+ * import { clearFrameworkIdentificationCache } from '@hyperfrontend/project-scope'
3594
+ *
3595
+ * // Reset cache before re-identifying frameworks
3596
+ * clearFrameworkIdentificationCache()
3597
+ * ```
3597
3598
  */
3598
3599
  function clearFrameworkIdentificationCache() {
3599
3600
  frameworkIdCache.clear();
@@ -3605,6 +3606,15 @@ function clearFrameworkIdentificationCache() {
3605
3606
  * @param frameworkId - Framework identifier to check
3606
3607
  * @param minConfidence - Minimum confidence threshold (default: 50)
3607
3608
  * @returns True if the framework is detected with sufficient confidence
3609
+ *
3610
+ * @example Checking for a specific framework
3611
+ * ```typescript
3612
+ * import { usesFramework } from '@hyperfrontend/project-scope'
3613
+ *
3614
+ * if (usesFramework('/path/to/project', 'react', 70)) {
3615
+ * console.log('Project uses React with high confidence')
3616
+ * }
3617
+ * ```
3608
3618
  */
3609
3619
  function usesFramework(projectPath, frameworkId, minConfidence = 50) {
3610
3620
  const identification = identifyFrameworks(projectPath, { minConfidence });
@@ -3615,4 +3625,3 @@ function usesFramework(projectPath, frameworkId, minConfidence = 50) {
3615
3625
  exports.clearFrameworkIdentificationCache = clearFrameworkIdentificationCache;
3616
3626
  exports.identifyFrameworks = identifyFrameworks;
3617
3627
  exports.usesFramework = usesFramework;
3618
- //# sourceMappingURL=index.cjs.js.map