@opensip-tools/fitness 1.0.4

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 (461) hide show
  1. package/.turbo/turbo-build.log +4 -0
  2. package/.turbo/turbo-typecheck.log +4 -0
  3. package/LICENSE +21 -0
  4. package/dist/__tests__/gate.test.d.ts +13 -0
  5. package/dist/__tests__/gate.test.d.ts.map +1 -0
  6. package/dist/__tests__/gate.test.js +422 -0
  7. package/dist/__tests__/gate.test.js.map +1 -0
  8. package/dist/__tests__/sarif.test.d.ts +2 -0
  9. package/dist/__tests__/sarif.test.d.ts.map +1 -0
  10. package/dist/__tests__/sarif.test.js +169 -0
  11. package/dist/__tests__/sarif.test.js.map +1 -0
  12. package/dist/cli/dashboard.d.ts +6 -0
  13. package/dist/cli/dashboard.d.ts.map +1 -0
  14. package/dist/cli/dashboard.js +77 -0
  15. package/dist/cli/dashboard.js.map +1 -0
  16. package/dist/cli/fit.d.ts +37 -0
  17. package/dist/cli/fit.d.ts.map +1 -0
  18. package/dist/cli/fit.js +539 -0
  19. package/dist/cli/fit.js.map +1 -0
  20. package/dist/cli/list-checks.d.ts +6 -0
  21. package/dist/cli/list-checks.d.ts.map +1 -0
  22. package/dist/cli/list-checks.js +23 -0
  23. package/dist/cli/list-checks.js.map +1 -0
  24. package/dist/cli/list-recipes.d.ts +6 -0
  25. package/dist/cli/list-recipes.d.ts.map +1 -0
  26. package/dist/cli/list-recipes.js +31 -0
  27. package/dist/cli/list-recipes.js.map +1 -0
  28. package/dist/framework/__tests__/ast-utilities.test.d.ts +2 -0
  29. package/dist/framework/__tests__/ast-utilities.test.d.ts.map +1 -0
  30. package/dist/framework/__tests__/ast-utilities.test.js +153 -0
  31. package/dist/framework/__tests__/ast-utilities.test.js.map +1 -0
  32. package/dist/framework/__tests__/check-config.test.d.ts +2 -0
  33. package/dist/framework/__tests__/check-config.test.d.ts.map +1 -0
  34. package/dist/framework/__tests__/check-config.test.js +56 -0
  35. package/dist/framework/__tests__/check-config.test.js.map +1 -0
  36. package/dist/framework/__tests__/command-executor.test.d.ts +2 -0
  37. package/dist/framework/__tests__/command-executor.test.d.ts.map +1 -0
  38. package/dist/framework/__tests__/command-executor.test.js +71 -0
  39. package/dist/framework/__tests__/command-executor.test.js.map +1 -0
  40. package/dist/framework/__tests__/content-filter-dispatch.test.d.ts +2 -0
  41. package/dist/framework/__tests__/content-filter-dispatch.test.d.ts.map +1 -0
  42. package/dist/framework/__tests__/content-filter-dispatch.test.js +104 -0
  43. package/dist/framework/__tests__/content-filter-dispatch.test.js.map +1 -0
  44. package/dist/framework/__tests__/content-filter.test.d.ts +2 -0
  45. package/dist/framework/__tests__/content-filter.test.d.ts.map +1 -0
  46. package/dist/framework/__tests__/content-filter.test.js +126 -0
  47. package/dist/framework/__tests__/content-filter.test.js.map +1 -0
  48. package/dist/framework/__tests__/define-check.test.d.ts +2 -0
  49. package/dist/framework/__tests__/define-check.test.d.ts.map +1 -0
  50. package/dist/framework/__tests__/define-check.test.js +155 -0
  51. package/dist/framework/__tests__/define-check.test.js.map +1 -0
  52. package/dist/framework/__tests__/directive-inventory.test.d.ts +2 -0
  53. package/dist/framework/__tests__/directive-inventory.test.d.ts.map +1 -0
  54. package/dist/framework/__tests__/directive-inventory.test.js +44 -0
  55. package/dist/framework/__tests__/directive-inventory.test.js.map +1 -0
  56. package/dist/framework/__tests__/execution-context.test.d.ts +2 -0
  57. package/dist/framework/__tests__/execution-context.test.d.ts.map +1 -0
  58. package/dist/framework/__tests__/execution-context.test.js +62 -0
  59. package/dist/framework/__tests__/execution-context.test.js.map +1 -0
  60. package/dist/framework/__tests__/file-accessor.test.d.ts +2 -0
  61. package/dist/framework/__tests__/file-accessor.test.d.ts.map +1 -0
  62. package/dist/framework/__tests__/file-accessor.test.js +106 -0
  63. package/dist/framework/__tests__/file-accessor.test.js.map +1 -0
  64. package/dist/framework/__tests__/file-cache.test.d.ts +2 -0
  65. package/dist/framework/__tests__/file-cache.test.d.ts.map +1 -0
  66. package/dist/framework/__tests__/file-cache.test.js +122 -0
  67. package/dist/framework/__tests__/file-cache.test.js.map +1 -0
  68. package/dist/framework/__tests__/import-graph.test.d.ts +15 -0
  69. package/dist/framework/__tests__/import-graph.test.d.ts.map +1 -0
  70. package/dist/framework/__tests__/import-graph.test.js +164 -0
  71. package/dist/framework/__tests__/import-graph.test.js.map +1 -0
  72. package/dist/framework/__tests__/path-matcher.test.d.ts +2 -0
  73. package/dist/framework/__tests__/path-matcher.test.d.ts.map +1 -0
  74. package/dist/framework/__tests__/path-matcher.test.js +113 -0
  75. package/dist/framework/__tests__/path-matcher.test.js.map +1 -0
  76. package/dist/framework/__tests__/register-helpers.test.d.ts +2 -0
  77. package/dist/framework/__tests__/register-helpers.test.d.ts.map +1 -0
  78. package/dist/framework/__tests__/register-helpers.test.js +42 -0
  79. package/dist/framework/__tests__/register-helpers.test.js.map +1 -0
  80. package/dist/framework/__tests__/registry.test.d.ts +2 -0
  81. package/dist/framework/__tests__/registry.test.d.ts.map +1 -0
  82. package/dist/framework/__tests__/registry.test.js +208 -0
  83. package/dist/framework/__tests__/registry.test.js.map +1 -0
  84. package/dist/framework/__tests__/result-builder.test.d.ts +2 -0
  85. package/dist/framework/__tests__/result-builder.test.d.ts.map +1 -0
  86. package/dist/framework/__tests__/result-builder.test.js +153 -0
  87. package/dist/framework/__tests__/result-builder.test.js.map +1 -0
  88. package/dist/framework/__tests__/scope-resolver.test.d.ts +2 -0
  89. package/dist/framework/__tests__/scope-resolver.test.d.ts.map +1 -0
  90. package/dist/framework/__tests__/scope-resolver.test.js +140 -0
  91. package/dist/framework/__tests__/scope-resolver.test.js.map +1 -0
  92. package/dist/framework/__tests__/severity-mapping.test.d.ts +2 -0
  93. package/dist/framework/__tests__/severity-mapping.test.d.ts.map +1 -0
  94. package/dist/framework/__tests__/severity-mapping.test.js +42 -0
  95. package/dist/framework/__tests__/severity-mapping.test.js.map +1 -0
  96. package/dist/framework/__tests__/strip-literals.test.d.ts +2 -0
  97. package/dist/framework/__tests__/strip-literals.test.d.ts.map +1 -0
  98. package/dist/framework/__tests__/strip-literals.test.js +87 -0
  99. package/dist/framework/__tests__/strip-literals.test.js.map +1 -0
  100. package/dist/framework/abortable-exec.d.ts +34 -0
  101. package/dist/framework/abortable-exec.d.ts.map +1 -0
  102. package/dist/framework/abortable-exec.js +136 -0
  103. package/dist/framework/abortable-exec.js.map +1 -0
  104. package/dist/framework/ast-utilities.d.ts +41 -0
  105. package/dist/framework/ast-utilities.d.ts.map +1 -0
  106. package/dist/framework/ast-utilities.js +106 -0
  107. package/dist/framework/ast-utilities.js.map +1 -0
  108. package/dist/framework/check-config.d.ts +171 -0
  109. package/dist/framework/check-config.d.ts.map +1 -0
  110. package/dist/framework/check-config.js +114 -0
  111. package/dist/framework/check-config.js.map +1 -0
  112. package/dist/framework/check-types.d.ts +57 -0
  113. package/dist/framework/check-types.d.ts.map +1 -0
  114. package/dist/framework/check-types.js +35 -0
  115. package/dist/framework/check-types.js.map +1 -0
  116. package/dist/framework/command-executor.d.ts +25 -0
  117. package/dist/framework/command-executor.d.ts.map +1 -0
  118. package/dist/framework/command-executor.js +63 -0
  119. package/dist/framework/command-executor.js.map +1 -0
  120. package/dist/framework/constants.d.ts +9 -0
  121. package/dist/framework/constants.d.ts.map +1 -0
  122. package/dist/framework/constants.js +16 -0
  123. package/dist/framework/constants.js.map +1 -0
  124. package/dist/framework/content-filter.d.ts +33 -0
  125. package/dist/framework/content-filter.d.ts.map +1 -0
  126. package/dist/framework/content-filter.js +236 -0
  127. package/dist/framework/content-filter.js.map +1 -0
  128. package/dist/framework/define-check.d.ts +38 -0
  129. package/dist/framework/define-check.d.ts.map +1 -0
  130. package/dist/framework/define-check.js +252 -0
  131. package/dist/framework/define-check.js.map +1 -0
  132. package/dist/framework/directive-inventory.d.ts +34 -0
  133. package/dist/framework/directive-inventory.d.ts.map +1 -0
  134. package/dist/framework/directive-inventory.js +77 -0
  135. package/dist/framework/directive-inventory.js.map +1 -0
  136. package/dist/framework/directive-parsing.d.ts +20 -0
  137. package/dist/framework/directive-parsing.d.ts.map +1 -0
  138. package/dist/framework/directive-parsing.js +121 -0
  139. package/dist/framework/directive-parsing.js.map +1 -0
  140. package/dist/framework/execution-context.d.ts +95 -0
  141. package/dist/framework/execution-context.d.ts.map +1 -0
  142. package/dist/framework/execution-context.js +122 -0
  143. package/dist/framework/execution-context.js.map +1 -0
  144. package/dist/framework/file-accessor.d.ts +20 -0
  145. package/dist/framework/file-accessor.d.ts.map +1 -0
  146. package/dist/framework/file-accessor.js +122 -0
  147. package/dist/framework/file-accessor.js.map +1 -0
  148. package/dist/framework/file-cache.d.ts +70 -0
  149. package/dist/framework/file-cache.d.ts.map +1 -0
  150. package/dist/framework/file-cache.js +178 -0
  151. package/dist/framework/file-cache.js.map +1 -0
  152. package/dist/framework/file-type-filter.d.ts +11 -0
  153. package/dist/framework/file-type-filter.d.ts.map +1 -0
  154. package/dist/framework/file-type-filter.js +21 -0
  155. package/dist/framework/file-type-filter.js.map +1 -0
  156. package/dist/framework/ignore-processing.d.ts +22 -0
  157. package/dist/framework/ignore-processing.d.ts.map +1 -0
  158. package/dist/framework/ignore-processing.js +241 -0
  159. package/dist/framework/ignore-processing.js.map +1 -0
  160. package/dist/framework/import-graph.d.ts +51 -0
  161. package/dist/framework/import-graph.d.ts.map +1 -0
  162. package/dist/framework/import-graph.js +216 -0
  163. package/dist/framework/import-graph.js.map +1 -0
  164. package/dist/framework/memory-profiler.d.ts +53 -0
  165. package/dist/framework/memory-profiler.d.ts.map +1 -0
  166. package/dist/framework/memory-profiler.js +92 -0
  167. package/dist/framework/memory-profiler.js.map +1 -0
  168. package/dist/framework/parse-cache.d.ts +23 -0
  169. package/dist/framework/parse-cache.d.ts.map +1 -0
  170. package/dist/framework/parse-cache.js +37 -0
  171. package/dist/framework/parse-cache.js.map +1 -0
  172. package/dist/framework/path-matcher.d.ts +86 -0
  173. package/dist/framework/path-matcher.d.ts.map +1 -0
  174. package/dist/framework/path-matcher.js +138 -0
  175. package/dist/framework/path-matcher.js.map +1 -0
  176. package/dist/framework/register-helpers.d.ts +10 -0
  177. package/dist/framework/register-helpers.d.ts.map +1 -0
  178. package/dist/framework/register-helpers.js +17 -0
  179. package/dist/framework/register-helpers.js.map +1 -0
  180. package/dist/framework/registry.d.ts +41 -0
  181. package/dist/framework/registry.d.ts.map +1 -0
  182. package/dist/framework/registry.js +103 -0
  183. package/dist/framework/registry.js.map +1 -0
  184. package/dist/framework/result-builder.d.ts +74 -0
  185. package/dist/framework/result-builder.d.ts.map +1 -0
  186. package/dist/framework/result-builder.js +154 -0
  187. package/dist/framework/result-builder.js.map +1 -0
  188. package/dist/framework/scope-resolver.d.ts +23 -0
  189. package/dist/framework/scope-resolver.d.ts.map +1 -0
  190. package/dist/framework/scope-resolver.js +201 -0
  191. package/dist/framework/scope-resolver.js.map +1 -0
  192. package/dist/framework/severity-mapping.d.ts +13 -0
  193. package/dist/framework/severity-mapping.d.ts.map +1 -0
  194. package/dist/framework/severity-mapping.js +51 -0
  195. package/dist/framework/severity-mapping.js.map +1 -0
  196. package/dist/framework/strip-literals.d.ts +48 -0
  197. package/dist/framework/strip-literals.d.ts.map +1 -0
  198. package/dist/framework/strip-literals.js +188 -0
  199. package/dist/framework/strip-literals.js.map +1 -0
  200. package/dist/gate.d.ts +74 -0
  201. package/dist/gate.d.ts.map +1 -0
  202. package/dist/gate.js +257 -0
  203. package/dist/gate.js.map +1 -0
  204. package/dist/index.d.ts +47 -0
  205. package/dist/index.d.ts.map +1 -0
  206. package/dist/index.js +51 -0
  207. package/dist/index.js.map +1 -0
  208. package/dist/plugins/__tests__/check-package-discovery.test.d.ts +2 -0
  209. package/dist/plugins/__tests__/check-package-discovery.test.d.ts.map +1 -0
  210. package/dist/plugins/__tests__/check-package-discovery.test.js +170 -0
  211. package/dist/plugins/__tests__/check-package-discovery.test.js.map +1 -0
  212. package/dist/plugins/__tests__/lang-domain.test.d.ts +2 -0
  213. package/dist/plugins/__tests__/lang-domain.test.d.ts.map +1 -0
  214. package/dist/plugins/__tests__/lang-domain.test.js +171 -0
  215. package/dist/plugins/__tests__/lang-domain.test.js.map +1 -0
  216. package/dist/plugins/__tests__/loader.test.d.ts +2 -0
  217. package/dist/plugins/__tests__/loader.test.d.ts.map +1 -0
  218. package/dist/plugins/__tests__/loader.test.js +194 -0
  219. package/dist/plugins/__tests__/loader.test.js.map +1 -0
  220. package/dist/plugins/check-package-discovery.d.ts +73 -0
  221. package/dist/plugins/check-package-discovery.d.ts.map +1 -0
  222. package/dist/plugins/check-package-discovery.js +212 -0
  223. package/dist/plugins/check-package-discovery.js.map +1 -0
  224. package/dist/plugins/loader.d.ts +31 -0
  225. package/dist/plugins/loader.d.ts.map +1 -0
  226. package/dist/plugins/loader.js +290 -0
  227. package/dist/plugins/loader.js.map +1 -0
  228. package/dist/plugins/types.d.ts +23 -0
  229. package/dist/plugins/types.d.ts.map +1 -0
  230. package/dist/plugins/types.js +9 -0
  231. package/dist/plugins/types.js.map +1 -0
  232. package/dist/recipes/__tests__/built-in-recipes.test.d.ts +2 -0
  233. package/dist/recipes/__tests__/built-in-recipes.test.d.ts.map +1 -0
  234. package/dist/recipes/__tests__/built-in-recipes.test.js +93 -0
  235. package/dist/recipes/__tests__/built-in-recipes.test.js.map +1 -0
  236. package/dist/recipes/__tests__/check-config.test.d.ts +5 -0
  237. package/dist/recipes/__tests__/check-config.test.d.ts.map +1 -0
  238. package/dist/recipes/__tests__/check-config.test.js +37 -0
  239. package/dist/recipes/__tests__/check-config.test.js.map +1 -0
  240. package/dist/recipes/__tests__/check-resolution.test.d.ts +2 -0
  241. package/dist/recipes/__tests__/check-resolution.test.d.ts.map +1 -0
  242. package/dist/recipes/__tests__/check-resolution.test.js +135 -0
  243. package/dist/recipes/__tests__/check-resolution.test.js.map +1 -0
  244. package/dist/recipes/__tests__/registry.test.d.ts +2 -0
  245. package/dist/recipes/__tests__/registry.test.d.ts.map +1 -0
  246. package/dist/recipes/__tests__/registry.test.js +97 -0
  247. package/dist/recipes/__tests__/registry.test.js.map +1 -0
  248. package/dist/recipes/__tests__/retry.test.d.ts +2 -0
  249. package/dist/recipes/__tests__/retry.test.d.ts.map +1 -0
  250. package/dist/recipes/__tests__/retry.test.js +75 -0
  251. package/dist/recipes/__tests__/retry.test.js.map +1 -0
  252. package/dist/recipes/__tests__/service.test.d.ts +11 -0
  253. package/dist/recipes/__tests__/service.test.d.ts.map +1 -0
  254. package/dist/recipes/__tests__/service.test.js +482 -0
  255. package/dist/recipes/__tests__/service.test.js.map +1 -0
  256. package/dist/recipes/built-in-recipes.d.ts +14 -0
  257. package/dist/recipes/built-in-recipes.d.ts.map +1 -0
  258. package/dist/recipes/built-in-recipes.js +247 -0
  259. package/dist/recipes/built-in-recipes.js.map +1 -0
  260. package/dist/recipes/check-config.d.ts +40 -0
  261. package/dist/recipes/check-config.d.ts.map +1 -0
  262. package/dist/recipes/check-config.js +61 -0
  263. package/dist/recipes/check-config.js.map +1 -0
  264. package/dist/recipes/check-resolution.d.ts +21 -0
  265. package/dist/recipes/check-resolution.d.ts.map +1 -0
  266. package/dist/recipes/check-resolution.js +121 -0
  267. package/dist/recipes/check-resolution.js.map +1 -0
  268. package/dist/recipes/check-result-processor.d.ts +51 -0
  269. package/dist/recipes/check-result-processor.d.ts.map +1 -0
  270. package/dist/recipes/check-result-processor.js +158 -0
  271. package/dist/recipes/check-result-processor.js.map +1 -0
  272. package/dist/recipes/parallel-execution.d.ts +33 -0
  273. package/dist/recipes/parallel-execution.d.ts.map +1 -0
  274. package/dist/recipes/parallel-execution.js +142 -0
  275. package/dist/recipes/parallel-execution.js.map +1 -0
  276. package/dist/recipes/registry.d.ts +81 -0
  277. package/dist/recipes/registry.d.ts.map +1 -0
  278. package/dist/recipes/registry.js +131 -0
  279. package/dist/recipes/registry.js.map +1 -0
  280. package/dist/recipes/retry.d.ts +25 -0
  281. package/dist/recipes/retry.d.ts.map +1 -0
  282. package/dist/recipes/retry.js +44 -0
  283. package/dist/recipes/retry.js.map +1 -0
  284. package/dist/recipes/sequential-execution.d.ts +10 -0
  285. package/dist/recipes/sequential-execution.d.ts.map +1 -0
  286. package/dist/recipes/sequential-execution.js +122 -0
  287. package/dist/recipes/sequential-execution.js.map +1 -0
  288. package/dist/recipes/service-types.d.ts +84 -0
  289. package/dist/recipes/service-types.d.ts.map +1 -0
  290. package/dist/recipes/service-types.js +8 -0
  291. package/dist/recipes/service-types.js.map +1 -0
  292. package/dist/recipes/service.d.ts +71 -0
  293. package/dist/recipes/service.d.ts.map +1 -0
  294. package/dist/recipes/service.js +331 -0
  295. package/dist/recipes/service.js.map +1 -0
  296. package/dist/recipes/types.d.ts +154 -0
  297. package/dist/recipes/types.d.ts.map +1 -0
  298. package/dist/recipes/types.js +54 -0
  299. package/dist/recipes/types.js.map +1 -0
  300. package/dist/sarif.d.ts +34 -0
  301. package/dist/sarif.d.ts.map +1 -0
  302. package/dist/sarif.js +192 -0
  303. package/dist/sarif.js.map +1 -0
  304. package/dist/signalers/__tests__/loader.test.d.ts +2 -0
  305. package/dist/signalers/__tests__/loader.test.d.ts.map +1 -0
  306. package/dist/signalers/__tests__/loader.test.js +74 -0
  307. package/dist/signalers/__tests__/loader.test.js.map +1 -0
  308. package/dist/signalers/index.d.ts +8 -0
  309. package/dist/signalers/index.d.ts.map +1 -0
  310. package/dist/signalers/index.js +9 -0
  311. package/dist/signalers/index.js.map +1 -0
  312. package/dist/signalers/loader.d.ts +24 -0
  313. package/dist/signalers/loader.d.ts.map +1 -0
  314. package/dist/signalers/loader.js +108 -0
  315. package/dist/signalers/loader.js.map +1 -0
  316. package/dist/signalers/schema.d.ts +288 -0
  317. package/dist/signalers/schema.d.ts.map +1 -0
  318. package/dist/signalers/schema.js +99 -0
  319. package/dist/signalers/schema.js.map +1 -0
  320. package/dist/signalers/types.d.ts +13 -0
  321. package/dist/signalers/types.d.ts.map +1 -0
  322. package/dist/signalers/types.js +5 -0
  323. package/dist/signalers/types.js.map +1 -0
  324. package/dist/targets/__tests__/loader.test.d.ts +2 -0
  325. package/dist/targets/__tests__/loader.test.d.ts.map +1 -0
  326. package/dist/targets/__tests__/loader.test.js +127 -0
  327. package/dist/targets/__tests__/loader.test.js.map +1 -0
  328. package/dist/targets/__tests__/resolver.test.d.ts +2 -0
  329. package/dist/targets/__tests__/resolver.test.d.ts.map +1 -0
  330. package/dist/targets/__tests__/resolver.test.js +54 -0
  331. package/dist/targets/__tests__/resolver.test.js.map +1 -0
  332. package/dist/targets/__tests__/target-registry.test.d.ts +2 -0
  333. package/dist/targets/__tests__/target-registry.test.d.ts.map +1 -0
  334. package/dist/targets/__tests__/target-registry.test.js +89 -0
  335. package/dist/targets/__tests__/target-registry.test.js.map +1 -0
  336. package/dist/targets/index.d.ts +10 -0
  337. package/dist/targets/index.d.ts.map +1 -0
  338. package/dist/targets/index.js +12 -0
  339. package/dist/targets/index.js.map +1 -0
  340. package/dist/targets/loader.d.ts +19 -0
  341. package/dist/targets/loader.d.ts.map +1 -0
  342. package/dist/targets/loader.js +159 -0
  343. package/dist/targets/loader.js.map +1 -0
  344. package/dist/targets/resolver.d.ts +19 -0
  345. package/dist/targets/resolver.d.ts.map +1 -0
  346. package/dist/targets/resolver.js +37 -0
  347. package/dist/targets/resolver.js.map +1 -0
  348. package/dist/targets/target-registry.d.ts +61 -0
  349. package/dist/targets/target-registry.d.ts.map +1 -0
  350. package/dist/targets/target-registry.js +93 -0
  351. package/dist/targets/target-registry.js.map +1 -0
  352. package/dist/targets/types.d.ts +85 -0
  353. package/dist/targets/types.d.ts.map +1 -0
  354. package/dist/targets/types.js +5 -0
  355. package/dist/targets/types.js.map +1 -0
  356. package/dist/tool.d.ts +17 -0
  357. package/dist/tool.d.ts.map +1 -0
  358. package/dist/tool.js +282 -0
  359. package/dist/tool.js.map +1 -0
  360. package/dist/types/findings.d.ts +117 -0
  361. package/dist/types/findings.d.ts.map +1 -0
  362. package/dist/types/findings.js +93 -0
  363. package/dist/types/findings.js.map +1 -0
  364. package/dist/types/severity.d.ts +15 -0
  365. package/dist/types/severity.d.ts.map +1 -0
  366. package/dist/types/severity.js +36 -0
  367. package/dist/types/severity.js.map +1 -0
  368. package/package.json +45 -0
  369. package/src/__tests__/gate.test.ts +537 -0
  370. package/src/__tests__/sarif.test.ts +201 -0
  371. package/src/cli/dashboard.ts +93 -0
  372. package/src/cli/fit.ts +612 -0
  373. package/src/cli/list-checks.ts +32 -0
  374. package/src/cli/list-recipes.ts +38 -0
  375. package/src/framework/__tests__/ast-utilities.test.ts +157 -0
  376. package/src/framework/__tests__/check-config.test.ts +65 -0
  377. package/src/framework/__tests__/command-executor.test.ts +79 -0
  378. package/src/framework/__tests__/content-filter-dispatch.test.ts +132 -0
  379. package/src/framework/__tests__/content-filter.test.ts +136 -0
  380. package/src/framework/__tests__/define-check.test.ts +180 -0
  381. package/src/framework/__tests__/directive-inventory.test.ts +53 -0
  382. package/src/framework/__tests__/execution-context.test.ts +80 -0
  383. package/src/framework/__tests__/file-accessor.test.ts +121 -0
  384. package/src/framework/__tests__/file-cache.test.ts +142 -0
  385. package/src/framework/__tests__/import-graph.test.ts +282 -0
  386. package/src/framework/__tests__/path-matcher.test.ts +130 -0
  387. package/src/framework/__tests__/register-helpers.test.ts +51 -0
  388. package/src/framework/__tests__/registry.test.ts +243 -0
  389. package/src/framework/__tests__/result-builder.test.ts +178 -0
  390. package/src/framework/__tests__/scope-resolver.test.ts +208 -0
  391. package/src/framework/__tests__/severity-mapping.test.ts +50 -0
  392. package/src/framework/__tests__/strip-literals.test.ts +109 -0
  393. package/src/framework/abortable-exec.ts +177 -0
  394. package/src/framework/ast-utilities.ts +112 -0
  395. package/src/framework/check-config.ts +339 -0
  396. package/src/framework/check-types.ts +77 -0
  397. package/src/framework/command-executor.ts +100 -0
  398. package/src/framework/constants.ts +16 -0
  399. package/src/framework/content-filter.ts +288 -0
  400. package/src/framework/define-check.ts +336 -0
  401. package/src/framework/directive-inventory.ts +110 -0
  402. package/src/framework/directive-parsing.ts +152 -0
  403. package/src/framework/execution-context.ts +247 -0
  404. package/src/framework/file-accessor.ts +171 -0
  405. package/src/framework/file-cache.ts +220 -0
  406. package/src/framework/file-type-filter.ts +25 -0
  407. package/src/framework/ignore-processing.ts +350 -0
  408. package/src/framework/import-graph.ts +280 -0
  409. package/src/framework/memory-profiler.ts +145 -0
  410. package/src/framework/parse-cache.ts +38 -0
  411. package/src/framework/path-matcher.ts +191 -0
  412. package/src/framework/register-helpers.ts +20 -0
  413. package/src/framework/registry.ts +125 -0
  414. package/src/framework/result-builder.ts +225 -0
  415. package/src/framework/scope-resolver.ts +262 -0
  416. package/src/framework/severity-mapping.ts +56 -0
  417. package/src/framework/strip-literals.ts +200 -0
  418. package/src/gate.ts +337 -0
  419. package/src/index.ts +110 -0
  420. package/src/plugins/__tests__/check-package-discovery.test.ts +204 -0
  421. package/src/plugins/__tests__/lang-domain.test.ts +198 -0
  422. package/src/plugins/__tests__/loader.test.ts +226 -0
  423. package/src/plugins/check-package-discovery.ts +242 -0
  424. package/src/plugins/loader.ts +327 -0
  425. package/src/plugins/types.ts +25 -0
  426. package/src/recipes/__tests__/built-in-recipes.test.ts +107 -0
  427. package/src/recipes/__tests__/check-config.test.ts +51 -0
  428. package/src/recipes/__tests__/check-resolution.test.ts +185 -0
  429. package/src/recipes/__tests__/registry.test.ts +115 -0
  430. package/src/recipes/__tests__/retry.test.ts +83 -0
  431. package/src/recipes/__tests__/service.test.ts +572 -0
  432. package/src/recipes/built-in-recipes.ts +273 -0
  433. package/src/recipes/check-config.ts +64 -0
  434. package/src/recipes/check-resolution.ts +169 -0
  435. package/src/recipes/check-result-processor.ts +258 -0
  436. package/src/recipes/parallel-execution.ts +220 -0
  437. package/src/recipes/registry.ts +192 -0
  438. package/src/recipes/retry.ts +69 -0
  439. package/src/recipes/sequential-execution.ts +139 -0
  440. package/src/recipes/service-types.ts +105 -0
  441. package/src/recipes/service.ts +400 -0
  442. package/src/recipes/types.ts +247 -0
  443. package/src/sarif.ts +232 -0
  444. package/src/signalers/__tests__/loader.test.ts +99 -0
  445. package/src/signalers/index.ts +9 -0
  446. package/src/signalers/loader.ts +141 -0
  447. package/src/signalers/schema.ts +117 -0
  448. package/src/signalers/types.ts +15 -0
  449. package/src/targets/__tests__/loader.test.ts +170 -0
  450. package/src/targets/__tests__/resolver.test.ts +74 -0
  451. package/src/targets/__tests__/target-registry.test.ts +103 -0
  452. package/src/targets/index.ts +13 -0
  453. package/src/targets/loader.ts +214 -0
  454. package/src/targets/resolver.ts +44 -0
  455. package/src/targets/target-registry.ts +111 -0
  456. package/src/targets/types.ts +89 -0
  457. package/src/tool.ts +302 -0
  458. package/src/types/findings.ts +239 -0
  459. package/src/types/severity.ts +39 -0
  460. package/tsconfig.json +8 -0
  461. package/vitest.config.ts +33 -0
@@ -0,0 +1,280 @@
1
+ /**
2
+ * @fileoverview Project-wide import graph builder.
3
+ *
4
+ * Builds a file-level dependency graph from a set of TypeScript/JavaScript
5
+ * source files, plus a Tarjan's strongly-connected-components implementation
6
+ * for cycle detection. Used by structural-drift checks like
7
+ * circular-import-detection and module-coupling-fan-out.
8
+ *
9
+ * Module resolution is deliberately a heuristic: relative imports are
10
+ * resolved by trying common extension/index.ts suffixes; bare specifiers
11
+ * (npm packages) are dropped; tsconfig path aliases are NOT resolved
12
+ * (treated as unresolved — they simply don't appear as edges in the graph).
13
+ *
14
+ * This matches the heuristic the existing `phantom-dependency-detection`
15
+ * check uses, which has been shipping reliably. Adding tsconfig-aware
16
+ * resolution is a follow-up plan.
17
+ */
18
+
19
+ import * as path from 'node:path'
20
+
21
+ import ts from 'typescript'
22
+
23
+ import { getSharedSourceFile } from './parse-cache.js'
24
+
25
+ // =============================================================================
26
+ // PUBLIC TYPES
27
+ // =============================================================================
28
+
29
+ /** A file-level import graph for a project. */
30
+ export interface ImportGraph {
31
+ /** All node file paths (absolute, as supplied by the caller). */
32
+ readonly nodes: ReadonlySet<string>
33
+ /** Adjacency: file → set of files it imports (intra-project edges only). */
34
+ readonly outbound: ReadonlyMap<string, ReadonlySet<string>>
35
+ /** Reverse adjacency: file → set of files that import it. */
36
+ readonly inbound: ReadonlyMap<string, ReadonlySet<string>>
37
+ }
38
+
39
+ // =============================================================================
40
+ // PUBLIC API
41
+ // =============================================================================
42
+
43
+ /**
44
+ * Build an import graph from a collection of file paths and their content.
45
+ *
46
+ * Each file's TS AST is walked for top-level `import` and `export ... from`
47
+ * declarations. Relative specifiers (`./foo`, `../bar/baz.js`) are resolved
48
+ * against the importing file's directory using the heuristic in
49
+ * `resolveRelativeSpecifier`. Bare specifiers (`react`, `lodash`) are
50
+ * dropped — they don't represent intra-project edges.
51
+ *
52
+ * Files that fail to parse are still added as nodes (with no edges) so the
53
+ * graph remains complete.
54
+ */
55
+ export function buildImportGraph(files: ReadonlyMap<string, string>): ImportGraph {
56
+ const nodes = new Set<string>(files.keys())
57
+ const outbound = new Map<string, Set<string>>()
58
+ const inbound = new Map<string, Set<string>>()
59
+
60
+ // Initialize empty edge sets for every node so callers can safely
61
+ // outbound.get(file) without checking for undefined.
62
+ for (const node of nodes) {
63
+ outbound.set(node, new Set())
64
+ inbound.set(node, new Set())
65
+ }
66
+
67
+ for (const [filePath, content] of files) {
68
+ const specifiers = extractImportSpecifiers(filePath, content)
69
+ for (const spec of specifiers) {
70
+ const resolved = resolveRelativeSpecifier(filePath, spec, nodes)
71
+ if (resolved !== null) {
72
+ outbound.get(filePath)!.add(resolved)
73
+ inbound.get(resolved)!.add(filePath)
74
+ }
75
+ }
76
+ }
77
+
78
+ return { nodes, outbound, inbound }
79
+ }
80
+
81
+ /**
82
+ * Find strongly-connected components in the graph using Tarjan's algorithm.
83
+ *
84
+ * Returns an array of SCCs, each represented as an array of node names. SCCs
85
+ * of size 1 represent a node with no cycle (or a self-loop, which is rare in
86
+ * import graphs). Cycle-detection callers typically filter to `scc.length > 1`
87
+ * to get only real multi-file cycles.
88
+ *
89
+ * Algorithm: standard iterative Tarjan's SCC. O(V + E), single pass.
90
+ */
91
+ export function findStronglyConnectedComponents(
92
+ graph: ImportGraph,
93
+ ): readonly (readonly string[])[] {
94
+ const indexOf = new Map<string, number>()
95
+ const lowlinkOf = new Map<string, number>()
96
+ const onStack = new Set<string>()
97
+ const stack: string[] = []
98
+ const sccs: string[][] = []
99
+ let nextIndex = 0
100
+
101
+ // Iterative Tarjan's — recursive form blows the stack on large graphs.
102
+ // State machine: we replay each node's adjacency from where we left off.
103
+ interface Frame {
104
+ node: string
105
+ neighbors: string[]
106
+ next: number
107
+ }
108
+
109
+ // eslint-disable-next-line sonarjs/cognitive-complexity -- iterative Tarjan SCC: explicit stack to avoid recursion; the algorithm is canonical and reads cleanest as a single function
110
+ function strongConnect(start: string): void {
111
+ const callStack: Frame[] = []
112
+
113
+ indexOf.set(start, nextIndex)
114
+ lowlinkOf.set(start, nextIndex)
115
+ nextIndex++
116
+ stack.push(start)
117
+ onStack.add(start)
118
+ callStack.push({
119
+ node: start,
120
+ neighbors: [...(graph.outbound.get(start) ?? [])],
121
+ next: 0,
122
+ })
123
+
124
+ while (callStack.length > 0) {
125
+ const frame = callStack.at(-1)!
126
+
127
+ if (frame.next < frame.neighbors.length) {
128
+ const w = frame.neighbors[frame.next]
129
+ frame.next++
130
+
131
+ if (!indexOf.has(w)) {
132
+ // Recurse into w.
133
+ indexOf.set(w, nextIndex)
134
+ lowlinkOf.set(w, nextIndex)
135
+ nextIndex++
136
+ stack.push(w)
137
+ onStack.add(w)
138
+ callStack.push({
139
+ node: w,
140
+ neighbors: [...(graph.outbound.get(w) ?? [])],
141
+ next: 0,
142
+ })
143
+ continue
144
+ }
145
+
146
+ if (onStack.has(w)) {
147
+ // Back edge — update v's lowlink.
148
+ const vLow = lowlinkOf.get(frame.node)!
149
+ const wIdx = indexOf.get(w)!
150
+ if (wIdx < vLow) lowlinkOf.set(frame.node, wIdx)
151
+ }
152
+ continue
153
+ }
154
+
155
+ // All neighbors processed — finalize this node.
156
+ const v = frame.node
157
+ const vLow = lowlinkOf.get(v)!
158
+ const vIdx = indexOf.get(v)!
159
+
160
+ if (vLow === vIdx) {
161
+ // v is the root of an SCC — pop until v is removed.
162
+ const scc: string[] = []
163
+ let w: string
164
+ do {
165
+ w = stack.pop()!
166
+ onStack.delete(w)
167
+ scc.push(w)
168
+ } while (w !== v)
169
+ sccs.push(scc)
170
+ }
171
+
172
+ callStack.pop()
173
+
174
+ // Propagate lowlink up to the parent frame.
175
+ if (callStack.length > 0) {
176
+ const parent = callStack.at(-1)!
177
+ const parentLow = lowlinkOf.get(parent.node)!
178
+ if (vLow < parentLow) lowlinkOf.set(parent.node, vLow)
179
+ }
180
+ }
181
+ }
182
+
183
+ for (const node of graph.nodes) {
184
+ if (!indexOf.has(node)) {
185
+ strongConnect(node)
186
+ }
187
+ }
188
+
189
+ return sccs
190
+ }
191
+
192
+ // =============================================================================
193
+ // INTERNAL HELPERS
194
+ // =============================================================================
195
+
196
+ /** Walk the AST and collect top-level import / export-from specifiers. */
197
+ function extractImportSpecifiers(filePath: string, content: string): string[] {
198
+ const sourceFile = getSharedSourceFile(filePath, content)
199
+ if (sourceFile === null) return []
200
+
201
+ const specifiers: string[] = []
202
+ for (const stmt of sourceFile.statements) {
203
+ // import foo from './bar'; import './side-effect'; import * as ns from './m';
204
+ if (ts.isImportDeclaration(stmt) && ts.isStringLiteral(stmt.moduleSpecifier)) {
205
+ specifiers.push(stmt.moduleSpecifier.text)
206
+ continue
207
+ }
208
+ // export * from './foo'; export { x } from './foo';
209
+ if (
210
+ ts.isExportDeclaration(stmt) &&
211
+ stmt.moduleSpecifier !== undefined &&
212
+ ts.isStringLiteral(stmt.moduleSpecifier)
213
+ ) {
214
+ specifiers.push(stmt.moduleSpecifier.text)
215
+ }
216
+ }
217
+ return specifiers
218
+ }
219
+
220
+ /**
221
+ * Resolve a module specifier to an actual file path in the project, or
222
+ * return null if the specifier is non-relative (npm package, path alias) or
223
+ * doesn't resolve to a known project file.
224
+ *
225
+ * Supports:
226
+ * - `./foo` → `<dir>/foo.ts`, `.tsx`, `/index.ts`, `/index.tsx`
227
+ * - `./foo.js` → `<dir>/foo.ts` (ESM extension swap, common in TS+ESM)
228
+ * - `./foo.ts` → `<dir>/foo.ts` (literal)
229
+ * - `../bar/baz` → resolved relative to importer's directory
230
+ *
231
+ * Does NOT support:
232
+ * - tsconfig `paths` aliases (deferred per plan)
233
+ * - npm packages (correctly dropped — out of scope for intra-project graph)
234
+ */
235
+ function resolveRelativeSpecifier(
236
+ importerPath: string,
237
+ specifier: string,
238
+ knownPaths: ReadonlySet<string>,
239
+ ): string | null {
240
+ // Only relative specifiers participate in the intra-project graph.
241
+ if (!specifier.startsWith('.')) return null
242
+
243
+ const importerDir = path.dirname(importerPath)
244
+ const base = path.resolve(importerDir, specifier)
245
+
246
+ // Try the candidate paths in priority order. The first one that exists in
247
+ // the project's file set wins.
248
+ const candidates: string[] = [ base]
249
+
250
+ // 1. Literal path (specifier already includes extension).
251
+
252
+ // 2. ESM extension swap: `.js` → `.ts` / `.tsx` (TypeScript ESM convention).
253
+ if (base.endsWith('.js')) {
254
+ candidates.push(base.slice(0, -3) + '.ts', base.slice(0, -3) + '.tsx')
255
+ }
256
+ if (base.endsWith('.jsx')) {
257
+ candidates.push(base.slice(0, -4) + '.tsx')
258
+ }
259
+
260
+ // 3. Append common extensions if the specifier was extension-less.
261
+ const hasExt = path.extname(base) !== ''
262
+ if (!hasExt) {
263
+ // Direct extensions and index resolution.
264
+ candidates.push(
265
+ base + '.ts',
266
+ base + '.tsx',
267
+ base + '.js',
268
+ base + '.jsx',
269
+ path.join(base, 'index.ts'),
270
+ path.join(base, 'index.tsx'),
271
+ path.join(base, 'index.js'),
272
+ path.join(base, 'index.jsx'),
273
+ )
274
+ }
275
+
276
+ for (const candidate of candidates) {
277
+ if (knownPaths.has(candidate)) return candidate
278
+ }
279
+ return null
280
+ }
@@ -0,0 +1,145 @@
1
+ /**
2
+ * @fileoverview Memory profiler for fitness checks
3
+ *
4
+ * Always-on, low-overhead memory tracking for check execution.
5
+ * Collects per-check profiles for trending analysis.
6
+ */
7
+
8
+ /** Point-in-time snapshot of Node.js memory usage */
9
+ interface MemorySnapshot {
10
+ readonly heapUsed: number
11
+ readonly heapTotal: number
12
+ readonly external: number
13
+ readonly arrayBuffers: number
14
+ readonly rss: number
15
+ }
16
+
17
+ /** Memory usage profile recorded for a single check execution */
18
+ export interface CheckMemoryProfile {
19
+ readonly checkId: string
20
+ readonly memoryBeforeMB: number
21
+ readonly memoryAfterMB: number
22
+ readonly memoryDeltaMB: number
23
+ readonly violationCount: number
24
+ readonly durationMs: number
25
+ }
26
+
27
+ /** Aggregated memory profiling summary across all check executions */
28
+ interface MemoryProfileSummary {
29
+ readonly prewarmMemoryMB: number
30
+ readonly peakMemoryMB: number
31
+ readonly checksExceedingThreshold: number
32
+ readonly topConsumers: readonly CheckMemoryProfile[]
33
+ readonly allProfiles: readonly CheckMemoryProfile[]
34
+ }
35
+
36
+ const DEFAULT_MEMORY_WARNING_THRESHOLD_MB = 200
37
+
38
+ /** Low-overhead memory profiler that tracks per-check heap usage during fitness runs */
39
+ class MemoryProfiler {
40
+ private readonly profiles: CheckMemoryProfile[] = []
41
+ private prewarmMemoryMB = 0
42
+ private peakMemoryMB = 0
43
+ private readonly warningThresholdMB: number
44
+
45
+ constructor(warningThresholdMB = DEFAULT_MEMORY_WARNING_THRESHOLD_MB) {
46
+ this.warningThresholdMB = warningThresholdMB
47
+ }
48
+
49
+ private takeSnapshot(): MemorySnapshot {
50
+ const mem = process.memoryUsage()
51
+ return {
52
+ heapUsed: mem.heapUsed,
53
+ heapTotal: mem.heapTotal,
54
+ external: mem.external,
55
+ arrayBuffers: mem.arrayBuffers,
56
+ rss: mem.rss,
57
+ }
58
+ }
59
+
60
+ private bytesToMB(bytes: number): number {
61
+ return bytes / 1024 / 1024
62
+ }
63
+
64
+ /** Record memory baseline after cache prewarm completes */
65
+ recordPrewarmComplete(): void {
66
+ const snapshot = this.takeSnapshot()
67
+ this.prewarmMemoryMB = this.bytesToMB(snapshot.heapUsed)
68
+ this.peakMemoryMB = this.prewarmMemoryMB
69
+ }
70
+
71
+ /** Return current heap usage in megabytes */
72
+ getCurrentMemoryMB(): number {
73
+ const snapshot = this.takeSnapshot()
74
+ return this.bytesToMB(snapshot.heapUsed)
75
+ }
76
+
77
+ /** Record memory before a check starts; returns the pre-check heap in MB */
78
+ recordCheckStart(): number {
79
+ return this.getCurrentMemoryMB()
80
+ }
81
+
82
+ /** Record memory after a check completes and return the check's memory profile */
83
+ recordCheckComplete(
84
+ checkId: string,
85
+ memoryBeforeMB: number,
86
+ violationCount: number,
87
+ durationMs: number,
88
+ ): CheckMemoryProfile {
89
+ const memoryAfterMB = this.getCurrentMemoryMB()
90
+ const memoryDeltaMB = memoryAfterMB - memoryBeforeMB
91
+
92
+ if (memoryAfterMB > this.peakMemoryMB) {
93
+ this.peakMemoryMB = memoryAfterMB
94
+ }
95
+
96
+ const profile: CheckMemoryProfile = {
97
+ checkId,
98
+ memoryBeforeMB: Math.round(memoryBeforeMB * 100) / 100,
99
+ memoryAfterMB: Math.round(memoryAfterMB * 100) / 100,
100
+ memoryDeltaMB: Math.round(memoryDeltaMB * 100) / 100,
101
+ violationCount,
102
+ durationMs,
103
+ }
104
+
105
+ this.profiles.push(profile)
106
+ return profile
107
+ }
108
+
109
+ /** Check whether a memory delta exceeds the configured warning threshold */
110
+ exceedsThreshold(deltaMB: number): boolean {
111
+ return deltaMB > this.warningThresholdMB
112
+ }
113
+
114
+ /** Return the configured warning threshold in megabytes */
115
+ getWarningThresholdMB(): number {
116
+ return this.warningThresholdMB
117
+ }
118
+
119
+ /** Build and return an aggregated summary of all recorded check profiles */
120
+ getSummary(): MemoryProfileSummary {
121
+ const sortedProfiles = [...this.profiles].sort((a, b) => b.memoryDeltaMB - a.memoryDeltaMB)
122
+
123
+ const checksExceedingThreshold = this.profiles.filter(
124
+ (p) => p.memoryDeltaMB > this.warningThresholdMB,
125
+ ).length
126
+
127
+ return {
128
+ prewarmMemoryMB: Math.round(this.prewarmMemoryMB * 100) / 100,
129
+ peakMemoryMB: Math.round(this.peakMemoryMB * 100) / 100,
130
+ checksExceedingThreshold,
131
+ topConsumers: sortedProfiles.slice(0, 10),
132
+ allProfiles: this.profiles,
133
+ }
134
+ }
135
+
136
+ /** Reset all recorded profiles and counters */
137
+ reset(): void {
138
+ this.profiles.length = 0
139
+ this.prewarmMemoryMB = 0
140
+ this.peakMemoryMB = 0
141
+ }
142
+ }
143
+
144
+ /** Shared singleton memory profiler instance used across fitness check runs */
145
+ export const memoryProfiler = new MemoryProfiler()
@@ -0,0 +1,38 @@
1
+ /**
2
+ * @fileoverview Re-export from the language-aware parse cache.
3
+ *
4
+ * The init/clear lifecycle and getParseTree API live in
5
+ * core/src/languages/parse-cache.ts. This file forwards those calls
6
+ * for backward compatibility with code that imported from this path.
7
+ *
8
+ * getSharedSourceFile remains as a TS-specific convenience wrapper
9
+ * that resolves the TypeScript adapter from the language registry.
10
+ * Phase 2 moved the canonical TS AST helpers to
11
+ * @opensip-tools/lang-typescript; this shim is retained for the
12
+ * core framework/import-graph.ts internal use case.
13
+ */
14
+
15
+
16
+ import { getParseTree, defaultLanguageRegistry } from '@opensip-tools/core'
17
+ import ts from 'typescript'
18
+
19
+ /**
20
+ * Get a TypeScript SourceFile via the language-aware cache when the TS
21
+ * adapter is registered, falling back to a direct parse otherwise.
22
+ *
23
+ * @internal Used by framework/import-graph.ts. New TS check authors
24
+ * should import getSharedSourceFile from @opensip-tools/lang-typescript.
25
+ */
26
+ export function getSharedSourceFile(filePath: string, content: string): ts.SourceFile | null {
27
+ const adapter = defaultLanguageRegistry.get('typescript')
28
+ if (adapter) {
29
+ return getParseTree(adapter, filePath, content) as ts.SourceFile | null
30
+ }
31
+ // No adapter registered yet (e.g. unit tests that run without CLI bootstrap).
32
+ // Fall back to direct parse — preserves prior behavior.
33
+ try {
34
+ return ts.createSourceFile(filePath, content, ts.ScriptTarget.Latest, true, ts.ScriptKind.TSX)
35
+ } catch {
36
+ return null
37
+ }
38
+ }
@@ -0,0 +1,191 @@
1
+ /**
2
+ * @fileoverview PathMatcher - Strategy pattern for file matching
3
+ *
4
+ * Provides glob-based file matching with include/exclude patterns.
5
+ * Supports lazy evaluation and composition.
6
+ */
7
+
8
+ import * as path from 'node:path'
9
+
10
+ import { glob } from 'glob'
11
+ import { minimatch } from 'minimatch'
12
+
13
+ /**
14
+ * Options for PathMatcher.
15
+ */
16
+ export interface PathMatcherOptions {
17
+ /** Root directory to search from */
18
+ readonly cwd: string
19
+ /** Glob patterns to include */
20
+ readonly include: readonly string[]
21
+ /** Glob patterns to exclude */
22
+ readonly exclude: readonly string[]
23
+ /** Additional exclusion patterns (combined with exclude) */
24
+ readonly additionalExcludes?: readonly string[]
25
+ }
26
+
27
+ /**
28
+ * Result of file matching operation.
29
+ */
30
+ export interface MatchResult {
31
+ /** Matched files (absolute paths) */
32
+ readonly files: readonly string[]
33
+ /** Files that were excluded */
34
+ readonly excluded: readonly string[]
35
+ /** Time taken for glob operation in ms */
36
+ readonly durationMs: number
37
+ }
38
+
39
+ /**
40
+ * Strategy for matching files based on glob patterns.
41
+ * Supports both custom patterns and composition.
42
+ *
43
+ * @example
44
+ * ```typescript
45
+ * const matcher = PathMatcher.create({
46
+ * cwd: '/path/to/repo',
47
+ * include: ['src/**\/*.ts'],
48
+ * exclude: ['**\/__tests__/**'],
49
+ * });
50
+ * const files = await matcher.files();
51
+ * ```
52
+ */
53
+ export class PathMatcher {
54
+ private constructor(private readonly options: PathMatcherOptions) {}
55
+
56
+ /**
57
+ * Create a PathMatcher from options.
58
+ */
59
+ static create(options: PathMatcherOptions): PathMatcher {
60
+ return new PathMatcher(options)
61
+ }
62
+
63
+ /**
64
+ * Get all matching files.
65
+ * @returns Array of absolute file paths matching the patterns
66
+ */
67
+ async files(): Promise<readonly string[]> {
68
+ const result = await this.match()
69
+ return result.files
70
+ }
71
+
72
+ /**
73
+ * Get detailed match result including timing.
74
+ */
75
+ async match(): Promise<MatchResult> {
76
+ const start = Date.now()
77
+
78
+ const allExcludes = [...this.options.exclude, ...(this.options.additionalExcludes ?? [])]
79
+
80
+ // Run glob for all include patterns
81
+ const matchedSets = await Promise.all(
82
+ this.options.include.map((pattern) =>
83
+ glob(pattern, {
84
+ cwd: this.options.cwd,
85
+ absolute: true,
86
+ nodir: true,
87
+ ignore: allExcludes,
88
+ }),
89
+ ),
90
+ )
91
+
92
+ // Combine and deduplicate results
93
+ const allMatched = new Set<string>()
94
+ for (const matches of matchedSets) {
95
+ for (const file of matches) {
96
+ allMatched.add(path.normalize(file))
97
+ }
98
+ }
99
+
100
+ const files = [...allMatched].sort()
101
+ const durationMs = Date.now() - start
102
+
103
+ return {
104
+ files,
105
+ excluded: [],
106
+ durationMs,
107
+ }
108
+ }
109
+
110
+ /**
111
+ * Check if a file matches the patterns.
112
+ * @param filePath - Absolute path to check
113
+ * @returns True if file matches include patterns and is not excluded
114
+ */
115
+ matches(filePath: string): boolean {
116
+ const relativePath = path.relative(this.options.cwd, filePath)
117
+
118
+ const matchesInclude = this.options.include.some((pattern) =>
119
+ minimatch(relativePath, pattern, { dot: true }),
120
+ )
121
+
122
+ if (!matchesInclude) {
123
+ return false
124
+ }
125
+
126
+ const allExcludes = [...this.options.exclude, ...(this.options.additionalExcludes ?? [])]
127
+
128
+ const matchesExclude = allExcludes.some((pattern) =>
129
+ minimatch(relativePath, pattern, { dot: true }),
130
+ )
131
+
132
+ return !matchesExclude
133
+ }
134
+
135
+ /**
136
+ * Create a new PathMatcher with additional exclusions.
137
+ */
138
+ withExcludes(additionalExcludes: readonly string[]): PathMatcher {
139
+ return new PathMatcher({
140
+ ...this.options,
141
+ additionalExcludes: [...(this.options.additionalExcludes ?? []), ...additionalExcludes],
142
+ })
143
+ }
144
+
145
+ /**
146
+ * Create a new PathMatcher that only includes TypeScript files.
147
+ */
148
+ typescriptOnly(): PathMatcher {
149
+ return new PathMatcher({
150
+ ...this.options,
151
+ include: this.options.include.map((pattern) => {
152
+ if (pattern.endsWith('/*') || pattern.endsWith('/**/*')) {
153
+ const base = pattern.replace(/\/\*+$/, '')
154
+ return `${base}/**/*.{ts,tsx}`
155
+ }
156
+ if (!pattern.includes('.')) {
157
+ return `${pattern}/**/*.{ts,tsx}`
158
+ }
159
+ return pattern
160
+ }),
161
+ })
162
+ }
163
+
164
+ /**
165
+ * Create a new PathMatcher that excludes test files.
166
+ */
167
+ noTests(): PathMatcher {
168
+ return this.withExcludes([
169
+ '**/__tests__/**',
170
+ '**/*.test.ts',
171
+ '**/*.test.tsx',
172
+ '**/*.spec.ts',
173
+ '**/*.spec.tsx',
174
+ ])
175
+ }
176
+
177
+ /** Get the current working directory. */
178
+ get cwd(): string {
179
+ return this.options.cwd
180
+ }
181
+
182
+ /** Get the include patterns. */
183
+ get includePatterns(): readonly string[] {
184
+ return this.options.include
185
+ }
186
+
187
+ /** Get the exclude patterns. */
188
+ get excludePatterns(): readonly string[] {
189
+ return [...this.options.exclude, ...(this.options.additionalExcludes ?? [])]
190
+ }
191
+ }
@@ -0,0 +1,20 @@
1
+ /**
2
+ * @fileoverview Helper for registering checks with a namespace
3
+ */
4
+
5
+ import { defaultRegistry } from './registry.js';
6
+
7
+ import type { Check } from './check-types.js';
8
+
9
+ /**
10
+ * Register an array of checks with a namespace into the default registry.
11
+ * @returns The number of checks registered.
12
+ */
13
+ export function registerChecks(checks: Check[], namespace: string): number {
14
+ let count = 0;
15
+ for (const check of checks) {
16
+ defaultRegistry.register(check, namespace);
17
+ count++;
18
+ }
19
+ return count;
20
+ }