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