pr-checkmate 3.0.4 → 3.2.0

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 (384) hide show
  1. package/dist/{cli.js → cjs/cli.js} +30 -30
  2. package/dist/{config → cjs/config}/index.d.ts +2 -2
  3. package/dist/{config → cjs/config}/index.js +8 -7
  4. package/dist/{config → cjs/config}/loader.d.ts +1 -1
  5. package/dist/{config → cjs/config}/loader.js +8 -8
  6. package/dist/{core → cjs/core}/checks/dependencies/banned-imports.d.ts +1 -1
  7. package/dist/{core → cjs/core}/checks/dependencies/banned-imports.js +10 -10
  8. package/dist/{core → cjs/core}/checks/dependencies/circular-deps.d.ts +1 -1
  9. package/dist/{core → cjs/core}/checks/dependencies/circular-deps.js +27 -27
  10. package/dist/{core → cjs/core}/checks/dependencies/dependency-check.d.ts +1 -1
  11. package/dist/{core → cjs/core}/checks/dependencies/dependency-check.js +17 -17
  12. package/dist/{core → cjs/core}/checks/dependencies/grype-scan.d.ts +1 -1
  13. package/dist/{core → cjs/core}/checks/dependencies/grype-scan.js +18 -18
  14. package/dist/{core → cjs/core}/checks/dependencies/license-check.d.ts +1 -1
  15. package/dist/{core → cjs/core}/checks/dependencies/license-check.js +12 -12
  16. package/dist/{core → cjs/core}/checks/dependencies/npm-audit.d.ts +1 -1
  17. package/dist/{core → cjs/core}/checks/dependencies/npm-audit.js +14 -14
  18. package/dist/{core → cjs/core}/checks/dependencies/outdated-deps.d.ts +1 -1
  19. package/dist/{core → cjs/core}/checks/dependencies/outdated-deps.js +14 -14
  20. package/dist/{core → cjs/core}/checks/dependencies/vuln-scan.d.ts +1 -1
  21. package/dist/{core → cjs/core}/checks/dependencies/vuln-scan.js +14 -14
  22. package/dist/{core → cjs/core}/checks/findings.d.ts +1 -1
  23. package/dist/{core → cjs/core}/checks/findings.js +16 -16
  24. package/dist/{core → cjs/core}/checks/git/custom-rules.d.ts +1 -1
  25. package/dist/{core → cjs/core}/checks/git/custom-rules.js +19 -19
  26. package/dist/{core → cjs/core}/checks/git/diff-smell.d.ts +2 -2
  27. package/dist/{core → cjs/core}/checks/git/diff-smell.js +13 -13
  28. package/dist/{core → cjs/core}/checks/git/large-files.d.ts +1 -1
  29. package/dist/{core → cjs/core}/checks/git/large-files.js +15 -15
  30. package/dist/{core → cjs/core}/checks/git/leftover-debug.d.ts +1 -1
  31. package/dist/{core → cjs/core}/checks/git/leftover-debug.js +13 -13
  32. package/dist/{core → cjs/core}/checks/git/lockfile-drift.d.ts +1 -1
  33. package/dist/{core → cjs/core}/checks/git/lockfile-drift.js +12 -12
  34. package/dist/{core → cjs/core}/checks/git/merge-conflict.d.ts +1 -1
  35. package/dist/{core → cjs/core}/checks/git/merge-conflict.js +15 -15
  36. package/dist/{core → cjs/core}/checks/git/missing-tests.d.ts +1 -1
  37. package/dist/{core → cjs/core}/checks/git/missing-tests.js +15 -15
  38. package/dist/{core → cjs/core}/checks/git/todo-fixme.d.ts +1 -1
  39. package/dist/{core → cjs/core}/checks/git/todo-fixme.js +11 -11
  40. package/dist/{core → cjs/core}/checks/languages/cpp-format.d.ts +1 -1
  41. package/dist/{core → cjs/core}/checks/languages/cpp-format.js +18 -18
  42. package/dist/{core → cjs/core}/checks/languages/external-checks.d.ts +9 -9
  43. package/dist/{core → cjs/core}/checks/languages/external-checks.js +10 -10
  44. package/dist/{core → cjs/core}/checks/languages/external-runner.d.ts +2 -2
  45. package/dist/{core → cjs/core}/checks/languages/external-runner.js +21 -21
  46. package/dist/{core → cjs/core}/checks/languages/go-format.d.ts +1 -1
  47. package/dist/{core → cjs/core}/checks/languages/go-format.js +21 -21
  48. package/dist/cjs/core/checks/languages/lint.d.ts +2 -0
  49. package/dist/{core → cjs/core}/checks/languages/lint.js +21 -21
  50. package/dist/{core → cjs/core}/checks/languages/prettier.d.ts +1 -1
  51. package/dist/{core → cjs/core}/checks/languages/prettier.js +18 -18
  52. package/dist/{core → cjs/core}/checks/languages/python-format.d.ts +1 -1
  53. package/dist/{core → cjs/core}/checks/languages/python-format.js +14 -14
  54. package/dist/{core → cjs/core}/checks/languages/python-lint.d.ts +1 -1
  55. package/dist/{core → cjs/core}/checks/languages/python-lint.js +13 -13
  56. package/dist/{core → cjs/core}/checks/languages/python-typecheck.d.ts +1 -1
  57. package/dist/{core → cjs/core}/checks/languages/python-typecheck.js +29 -29
  58. package/dist/{core → cjs/core}/checks/languages/typecheck.d.ts +1 -1
  59. package/dist/{core → cjs/core}/checks/languages/typecheck.js +13 -13
  60. package/dist/{core → cjs/core}/checks/pr/commitlint.d.ts +1 -1
  61. package/dist/{core → cjs/core}/checks/pr/commitlint.js +12 -12
  62. package/dist/{core → cjs/core}/checks/pr/pr-body.d.ts +1 -1
  63. package/dist/{core → cjs/core}/checks/pr/pr-body.js +8 -8
  64. package/dist/{core → cjs/core}/checks/pr/pr-size-check.d.ts +1 -1
  65. package/dist/{core → cjs/core}/checks/pr/pr-size-check.js +10 -10
  66. package/dist/{core → cjs/core}/checks/pr/pr-title-lint.d.ts +1 -1
  67. package/dist/{core → cjs/core}/checks/pr/pr-title-lint.js +8 -8
  68. package/dist/{core → cjs/core}/checks/quality/case-collision.d.ts +1 -1
  69. package/dist/{core → cjs/core}/checks/quality/case-collision.js +7 -7
  70. package/dist/{core → cjs/core}/checks/quality/config-validation.d.ts +1 -1
  71. package/dist/{core → cjs/core}/checks/quality/config-validation.js +9 -9
  72. package/dist/{core → cjs/core}/checks/quality/coverage.d.ts +1 -1
  73. package/dist/{core → cjs/core}/checks/quality/coverage.js +4 -4
  74. package/dist/{core → cjs/core}/checks/quality/dead-code.d.ts +1 -1
  75. package/dist/{core → cjs/core}/checks/quality/dead-code.js +23 -23
  76. package/dist/{core → cjs/core}/checks/quality/duplicate-check.d.ts +1 -1
  77. package/dist/{core → cjs/core}/checks/quality/duplicate-check.js +22 -22
  78. package/dist/{core → cjs/core}/checks/quality/license-header.d.ts +1 -1
  79. package/dist/{core → cjs/core}/checks/quality/license-header.js +16 -16
  80. package/dist/{core → cjs/core}/checks/quality/markdown-lint.d.ts +1 -1
  81. package/dist/cjs/core/checks/quality/markdown-lint.js +147 -0
  82. package/dist/{core → cjs/core}/checks/quality/package-size.d.ts +1 -1
  83. package/dist/{core → cjs/core}/checks/quality/package-size.js +12 -12
  84. package/dist/{core → cjs/core}/checks/quality/spellcheck.d.ts +2 -2
  85. package/dist/{core → cjs/core}/checks/quality/spellcheck.js +18 -18
  86. package/dist/{core → cjs/core}/checks/quality/symlinks.d.ts +1 -1
  87. package/dist/{core → cjs/core}/checks/quality/symlinks.js +8 -8
  88. package/dist/{core → cjs/core}/checks/quality/yaml-lint.d.ts +1 -1
  89. package/dist/{core → cjs/core}/checks/quality/yaml-lint.js +12 -12
  90. package/dist/{core → cjs/core}/checks/security/diff-security.d.ts +1 -1
  91. package/dist/{core → cjs/core}/checks/security/diff-security.js +15 -15
  92. package/dist/{core → cjs/core}/checks/security/dockerfile-security.d.ts +1 -1
  93. package/dist/{core → cjs/core}/checks/security/dockerfile-security.js +16 -16
  94. package/dist/{core → cjs/core}/checks/security/migration-safety.d.ts +1 -1
  95. package/dist/{core → cjs/core}/checks/security/migration-safety.js +17 -17
  96. package/dist/{core → cjs/core}/checks/security/security.d.ts +1 -1
  97. package/dist/{core → cjs/core}/checks/security/security.js +21 -21
  98. package/dist/{core → cjs/core}/checks/security/sensitive-file-guard.d.ts +1 -1
  99. package/dist/{core → cjs/core}/checks/security/sensitive-file-guard.js +14 -14
  100. package/dist/{core → cjs/core}/checks/security/workflow-security.d.ts +2 -2
  101. package/dist/{core → cjs/core}/checks/security/workflow-security.js +14 -14
  102. package/dist/{core → cjs/core}/checks/tool-install.d.ts +1 -1
  103. package/dist/{core → cjs/core}/checks/tool-install.js +2 -2
  104. package/dist/{core → cjs/core}/context.d.ts +1 -1
  105. package/dist/{core → cjs/core}/context.js +16 -16
  106. package/dist/cjs/core/index.d.ts +4 -0
  107. package/dist/{core → cjs/core}/index.js +7 -7
  108. package/dist/{core → cjs/core}/install/cache.js +2 -2
  109. package/dist/{core → cjs/core}/install/doctor.d.ts +4 -4
  110. package/dist/{core → cjs/core}/install/doctor.js +34 -34
  111. package/dist/{core → cjs/core}/install/ensure.d.ts +2 -2
  112. package/dist/{core → cjs/core}/install/ensure.js +15 -14
  113. package/dist/{core → cjs/core}/install/lock.js +4 -4
  114. package/dist/{core → cjs/core}/install/prepare.d.ts +4 -4
  115. package/dist/{core → cjs/core}/install/prepare.js +13 -13
  116. package/dist/{core → cjs/core}/install/profiles.d.ts +2 -2
  117. package/dist/{core → cjs/core}/install/profiles.js +1 -1
  118. package/dist/{core → cjs/core}/install/reuse.d.ts +1 -1
  119. package/dist/{core → cjs/core}/install/reuse.js +4 -4
  120. package/dist/{core → cjs/core}/registry.d.ts +1 -1
  121. package/dist/cjs/core/registry.js +112 -0
  122. package/dist/{core → cjs/core}/reporters.d.ts +1 -1
  123. package/dist/{core → cjs/core}/reporters.js +28 -28
  124. package/dist/{core → cjs/core}/run-checks.d.ts +2 -2
  125. package/dist/{core → cjs/core}/run-checks.js +31 -31
  126. package/dist/{core → cjs/core}/targets.d.ts +1 -1
  127. package/dist/{core → cjs/core}/targets.js +20 -20
  128. package/dist/{core → cjs/core}/types.d.ts +3 -3
  129. package/dist/cjs/index.d.ts +12 -0
  130. package/dist/{index.js → cjs/index.js} +18 -18
  131. package/dist/{init.js → cjs/init.js} +68 -56
  132. package/dist/{interfaces → cjs/interfaces}/index.d.ts +3 -3
  133. package/dist/cjs/package.json +1 -0
  134. package/dist/{scripts → cjs/scripts}/copy-configs.js +22 -7
  135. package/dist/{scripts → cjs/scripts}/generate-install-manifests.js +2 -2
  136. package/dist/{scripts → cjs/scripts}/publish-github.js +4 -4
  137. package/dist/{utils → cjs/utils}/detect-language.js +12 -12
  138. package/dist/{utils → cjs/utils}/git.js +2 -2
  139. package/dist/{utils → cjs/utils}/http.js +2 -2
  140. package/dist/cjs/utils/index.d.ts +15 -0
  141. package/dist/{utils → cjs/utils}/index.js +13 -13
  142. package/dist/{utils → cjs/utils}/own-deps.d.ts +2 -0
  143. package/dist/{utils → cjs/utils}/own-deps.js +1 -0
  144. package/dist/{utils → cjs/utils}/package-version.js +2 -1
  145. package/dist/{utils → cjs/utils}/resolve-bin.js +2 -1
  146. package/dist/{utils → cjs/utils}/update-notifier.js +4 -4
  147. package/dist/esm/cli.d.ts +2 -0
  148. package/dist/esm/cli.js +137 -0
  149. package/dist/esm/config/constants.d.ts +153 -0
  150. package/dist/esm/config/constants.js +360 -0
  151. package/dist/esm/config/index.d.ts +40 -0
  152. package/dist/esm/config/index.js +60 -0
  153. package/dist/esm/config/loader.d.ts +6 -0
  154. package/dist/esm/config/loader.js +191 -0
  155. package/dist/esm/config/pr-checkmate-workflow-docker.yml +79 -0
  156. package/dist/esm/config/pr-checkmate-workflow.yml +92 -0
  157. package/dist/esm/core/checks/dependencies/banned-imports.d.ts +2 -0
  158. package/dist/esm/core/checks/dependencies/banned-imports.js +70 -0
  159. package/dist/esm/core/checks/dependencies/circular-deps.d.ts +2 -0
  160. package/dist/esm/core/checks/dependencies/circular-deps.js +155 -0
  161. package/dist/esm/core/checks/dependencies/dependency-check.d.ts +43 -0
  162. package/dist/esm/core/checks/dependencies/dependency-check.js +174 -0
  163. package/dist/esm/core/checks/dependencies/grype-scan.d.ts +22 -0
  164. package/dist/esm/core/checks/dependencies/grype-scan.js +112 -0
  165. package/dist/esm/core/checks/dependencies/license-check.d.ts +2 -0
  166. package/dist/esm/core/checks/dependencies/license-check.js +61 -0
  167. package/dist/esm/core/checks/dependencies/npm-audit.d.ts +6 -0
  168. package/dist/esm/core/checks/dependencies/npm-audit.js +80 -0
  169. package/dist/esm/core/checks/dependencies/outdated-deps.d.ts +2 -0
  170. package/dist/esm/core/checks/dependencies/outdated-deps.js +66 -0
  171. package/dist/esm/core/checks/dependencies/vuln-scan.d.ts +2 -0
  172. package/dist/esm/core/checks/dependencies/vuln-scan.js +54 -0
  173. package/dist/esm/core/checks/findings.d.ts +299 -0
  174. package/dist/esm/core/checks/findings.js +701 -0
  175. package/dist/esm/core/checks/git/custom-rules.d.ts +2 -0
  176. package/dist/esm/core/checks/git/custom-rules.js +106 -0
  177. package/dist/esm/core/checks/git/diff-smell.d.ts +19 -0
  178. package/dist/esm/core/checks/git/diff-smell.js +69 -0
  179. package/dist/esm/core/checks/git/large-files.d.ts +2 -0
  180. package/dist/esm/core/checks/git/large-files.js +112 -0
  181. package/dist/esm/core/checks/git/leftover-debug.d.ts +2 -0
  182. package/dist/esm/core/checks/git/leftover-debug.js +89 -0
  183. package/dist/esm/core/checks/git/lockfile-drift.d.ts +2 -0
  184. package/dist/esm/core/checks/git/lockfile-drift.js +114 -0
  185. package/dist/esm/core/checks/git/merge-conflict.d.ts +2 -0
  186. package/dist/esm/core/checks/git/merge-conflict.js +117 -0
  187. package/dist/esm/core/checks/git/missing-tests.d.ts +2 -0
  188. package/dist/esm/core/checks/git/missing-tests.js +105 -0
  189. package/dist/esm/core/checks/git/todo-fixme.d.ts +7 -0
  190. package/dist/esm/core/checks/git/todo-fixme.js +80 -0
  191. package/dist/esm/core/checks/languages/cpp-format.d.ts +7 -0
  192. package/dist/esm/core/checks/languages/cpp-format.js +91 -0
  193. package/dist/esm/core/checks/languages/external-checks.d.ts +77 -0
  194. package/dist/esm/core/checks/languages/external-checks.js +197 -0
  195. package/dist/esm/core/checks/languages/external-runner.d.ts +119 -0
  196. package/dist/esm/core/checks/languages/external-runner.js +138 -0
  197. package/dist/esm/core/checks/languages/go-format.d.ts +8 -0
  198. package/dist/esm/core/checks/languages/go-format.js +163 -0
  199. package/dist/esm/core/checks/languages/lint.d.ts +2 -0
  200. package/dist/esm/core/checks/languages/lint.js +92 -0
  201. package/dist/esm/core/checks/languages/prettier.d.ts +2 -0
  202. package/dist/esm/core/checks/languages/prettier.js +85 -0
  203. package/dist/esm/core/checks/languages/python-format.d.ts +7 -0
  204. package/dist/esm/core/checks/languages/python-format.js +61 -0
  205. package/dist/esm/core/checks/languages/python-lint.d.ts +9 -0
  206. package/dist/esm/core/checks/languages/python-lint.js +55 -0
  207. package/dist/esm/core/checks/languages/python-typecheck.d.ts +14 -0
  208. package/dist/esm/core/checks/languages/python-typecheck.js +184 -0
  209. package/dist/esm/core/checks/languages/ruff-shared.d.ts +10 -0
  210. package/dist/esm/core/checks/languages/ruff-shared.js +35 -0
  211. package/dist/esm/core/checks/languages/typecheck.d.ts +2 -0
  212. package/dist/esm/core/checks/languages/typecheck.js +61 -0
  213. package/dist/esm/core/checks/pr/commitlint.d.ts +2 -0
  214. package/dist/esm/core/checks/pr/commitlint.js +102 -0
  215. package/dist/esm/core/checks/pr/pr-body.d.ts +2 -0
  216. package/dist/esm/core/checks/pr/pr-body.js +43 -0
  217. package/dist/esm/core/checks/pr/pr-size-check.d.ts +2 -0
  218. package/dist/esm/core/checks/pr/pr-size-check.js +42 -0
  219. package/dist/esm/core/checks/pr/pr-title-lint.d.ts +2 -0
  220. package/dist/esm/core/checks/pr/pr-title-lint.js +31 -0
  221. package/dist/esm/core/checks/quality/case-collision.d.ts +8 -0
  222. package/dist/esm/core/checks/quality/case-collision.js +39 -0
  223. package/dist/esm/core/checks/quality/config-validation.d.ts +11 -0
  224. package/dist/esm/core/checks/quality/config-validation.js +188 -0
  225. package/dist/esm/core/checks/quality/coverage.d.ts +2 -0
  226. package/dist/esm/core/checks/quality/coverage.js +62 -0
  227. package/dist/esm/core/checks/quality/dead-code.d.ts +2 -0
  228. package/dist/esm/core/checks/quality/dead-code.js +124 -0
  229. package/dist/esm/core/checks/quality/duplicate-check.d.ts +2 -0
  230. package/dist/esm/core/checks/quality/duplicate-check.js +141 -0
  231. package/dist/esm/core/checks/quality/license-header.d.ts +7 -0
  232. package/dist/esm/core/checks/quality/license-header.js +81 -0
  233. package/dist/esm/core/checks/quality/markdown-lint.d.ts +2 -0
  234. package/dist/esm/core/checks/quality/markdown-lint.js +141 -0
  235. package/dist/esm/core/checks/quality/package-size.d.ts +36 -0
  236. package/dist/esm/core/checks/quality/package-size.js +196 -0
  237. package/dist/esm/core/checks/quality/spellcheck.d.ts +77 -0
  238. package/dist/esm/core/checks/quality/spellcheck.js +296 -0
  239. package/dist/esm/core/checks/quality/symlinks.d.ts +16 -0
  240. package/dist/esm/core/checks/quality/symlinks.js +57 -0
  241. package/dist/esm/core/checks/quality/yaml-lint.d.ts +20 -0
  242. package/dist/esm/core/checks/quality/yaml-lint.js +116 -0
  243. package/dist/esm/core/checks/security/diff-security.d.ts +2 -0
  244. package/dist/esm/core/checks/security/diff-security.js +354 -0
  245. package/dist/esm/core/checks/security/dockerfile-security.d.ts +2 -0
  246. package/dist/esm/core/checks/security/dockerfile-security.js +98 -0
  247. package/dist/esm/core/checks/security/migration-safety.d.ts +2 -0
  248. package/dist/esm/core/checks/security/migration-safety.js +137 -0
  249. package/dist/esm/core/checks/security/security.d.ts +63 -0
  250. package/dist/esm/core/checks/security/security.js +201 -0
  251. package/dist/esm/core/checks/security/sensitive-file-guard.d.ts +2 -0
  252. package/dist/esm/core/checks/security/sensitive-file-guard.js +160 -0
  253. package/dist/esm/core/checks/security/workflow-security.d.ts +12 -0
  254. package/dist/esm/core/checks/security/workflow-security.js +100 -0
  255. package/dist/esm/core/checks/tool-install.d.ts +102 -0
  256. package/dist/esm/core/checks/tool-install.js +66 -0
  257. package/dist/esm/core/commands.d.ts +27 -0
  258. package/dist/esm/core/commands.js +89 -0
  259. package/dist/esm/core/context.d.ts +62 -0
  260. package/dist/esm/core/context.js +241 -0
  261. package/dist/esm/core/index.d.ts +4 -0
  262. package/dist/esm/core/index.js +4 -0
  263. package/dist/esm/core/install/cache.d.ts +58 -0
  264. package/dist/esm/core/install/cache.js +142 -0
  265. package/dist/esm/core/install/doctor.d.ts +35 -0
  266. package/dist/esm/core/install/doctor.js +164 -0
  267. package/dist/esm/core/install/ensure.d.ts +77 -0
  268. package/dist/esm/core/install/ensure.js +269 -0
  269. package/dist/esm/core/install/lock.d.ts +34 -0
  270. package/dist/esm/core/install/lock.js +92 -0
  271. package/dist/esm/core/install/merge.d.ts +47 -0
  272. package/dist/esm/core/install/merge.js +85 -0
  273. package/dist/esm/core/install/prepare.d.ts +76 -0
  274. package/dist/esm/core/install/prepare.js +142 -0
  275. package/dist/esm/core/install/profiles.d.ts +78 -0
  276. package/dist/esm/core/install/profiles.js +192 -0
  277. package/dist/esm/core/install/reuse.d.ts +41 -0
  278. package/dist/esm/core/install/reuse.js +100 -0
  279. package/dist/esm/core/registry.d.ts +6 -0
  280. package/dist/esm/core/registry.js +109 -0
  281. package/dist/esm/core/reporters.d.ts +18 -0
  282. package/dist/esm/core/reporters.js +266 -0
  283. package/dist/esm/core/run-checks.d.ts +33 -0
  284. package/dist/esm/core/run-checks.js +293 -0
  285. package/dist/esm/core/targets.d.ts +140 -0
  286. package/dist/esm/core/targets.js +213 -0
  287. package/dist/esm/core/types.d.ts +195 -0
  288. package/dist/esm/core/types.js +38 -0
  289. package/dist/esm/index.d.ts +12 -0
  290. package/dist/esm/index.js +15 -0
  291. package/dist/esm/init.d.ts +38 -0
  292. package/dist/esm/init.js +421 -0
  293. package/dist/esm/interfaces/index.d.ts +432 -0
  294. package/dist/esm/interfaces/index.js +2 -0
  295. package/dist/esm/package.json +1 -0
  296. package/dist/esm/scripts/copy-configs.d.ts +1 -0
  297. package/dist/esm/scripts/copy-configs.js +64 -0
  298. package/dist/esm/scripts/generate-install-manifests.d.ts +39 -0
  299. package/dist/esm/scripts/generate-install-manifests.js +115 -0
  300. package/dist/esm/scripts/publish-github.d.ts +1 -0
  301. package/dist/esm/scripts/publish-github.js +45 -0
  302. package/dist/esm/utils/ci.d.ts +11 -0
  303. package/dist/esm/utils/ci.js +40 -0
  304. package/dist/esm/utils/detect-language.d.ts +48 -0
  305. package/dist/esm/utils/detect-language.js +234 -0
  306. package/dist/esm/utils/direct-deps.d.ts +21 -0
  307. package/dist/esm/utils/direct-deps.js +220 -0
  308. package/dist/esm/utils/execa.d.ts +22 -0
  309. package/dist/esm/utils/execa.js +10 -0
  310. package/dist/esm/utils/git.d.ts +14 -0
  311. package/dist/esm/utils/git.js +21 -0
  312. package/dist/esm/utils/glob.d.ts +24 -0
  313. package/dist/esm/utils/glob.js +40 -0
  314. package/dist/esm/utils/http.d.ts +59 -0
  315. package/dist/esm/utils/http.js +115 -0
  316. package/dist/esm/utils/index.d.ts +15 -0
  317. package/dist/esm/utils/index.js +26 -0
  318. package/dist/esm/utils/logger.d.ts +65 -0
  319. package/dist/esm/utils/logger.js +157 -0
  320. package/dist/esm/utils/own-deps.d.ts +16 -0
  321. package/dist/esm/utils/own-deps.js +107 -0
  322. package/dist/esm/utils/package-version.d.ts +4 -0
  323. package/dist/esm/utils/package-version.js +38 -0
  324. package/dist/esm/utils/pool.d.ts +49 -0
  325. package/dist/esm/utils/pool.js +113 -0
  326. package/dist/esm/utils/resolve-bin.d.ts +67 -0
  327. package/dist/esm/utils/resolve-bin.js +156 -0
  328. package/dist/esm/utils/result-collector.d.ts +33 -0
  329. package/dist/esm/utils/result-collector.js +44 -0
  330. package/dist/esm/utils/update-notifier.d.ts +19 -0
  331. package/dist/esm/utils/update-notifier.js +108 -0
  332. package/install-manifests/core/package-lock.json +4 -4
  333. package/install-manifests/core/package.json +1 -1
  334. package/install-manifests/duplicate/package-lock.json +0 -12
  335. package/install-manifests/js/package-lock.json +17 -41
  336. package/install-manifests/js/package.json +1 -1
  337. package/install-manifests/markdown/package-lock.json +1 -492
  338. package/install-manifests/markdown/package.json +1 -1
  339. package/package.json +17 -15
  340. package/dist/core/checks/languages/lint.d.ts +0 -2
  341. package/dist/core/checks/quality/markdown-lint.js +0 -110
  342. package/dist/core/index.d.ts +0 -4
  343. package/dist/core/registry.js +0 -112
  344. package/dist/index.d.ts +0 -12
  345. package/dist/utils/index.d.ts +0 -15
  346. /package/dist/{cli.d.ts → cjs/cli.d.ts} +0 -0
  347. /package/dist/{config → cjs/config}/constants.d.ts +0 -0
  348. /package/dist/{config → cjs/config}/constants.js +0 -0
  349. /package/dist/{config → cjs/config}/pr-checkmate-workflow-docker.yml +0 -0
  350. /package/dist/{config → cjs/config}/pr-checkmate-workflow.yml +0 -0
  351. /package/dist/{core → cjs/core}/checks/languages/ruff-shared.d.ts +0 -0
  352. /package/dist/{core → cjs/core}/checks/languages/ruff-shared.js +0 -0
  353. /package/dist/{core → cjs/core}/commands.d.ts +0 -0
  354. /package/dist/{core → cjs/core}/commands.js +0 -0
  355. /package/dist/{core → cjs/core}/install/cache.d.ts +0 -0
  356. /package/dist/{core → cjs/core}/install/lock.d.ts +0 -0
  357. /package/dist/{core → cjs/core}/install/merge.d.ts +0 -0
  358. /package/dist/{core → cjs/core}/install/merge.js +0 -0
  359. /package/dist/{core → cjs/core}/types.js +0 -0
  360. /package/dist/{init.d.ts → cjs/init.d.ts} +0 -0
  361. /package/dist/{interfaces → cjs/interfaces}/index.js +0 -0
  362. /package/dist/{scripts → cjs/scripts}/copy-configs.d.ts +0 -0
  363. /package/dist/{scripts → cjs/scripts}/generate-install-manifests.d.ts +0 -0
  364. /package/dist/{scripts → cjs/scripts}/publish-github.d.ts +0 -0
  365. /package/dist/{utils → cjs/utils}/ci.d.ts +0 -0
  366. /package/dist/{utils → cjs/utils}/ci.js +0 -0
  367. /package/dist/{utils → cjs/utils}/detect-language.d.ts +0 -0
  368. /package/dist/{utils → cjs/utils}/direct-deps.d.ts +0 -0
  369. /package/dist/{utils → cjs/utils}/direct-deps.js +0 -0
  370. /package/dist/{utils → cjs/utils}/execa.d.ts +0 -0
  371. /package/dist/{utils → cjs/utils}/execa.js +0 -0
  372. /package/dist/{utils → cjs/utils}/git.d.ts +0 -0
  373. /package/dist/{utils → cjs/utils}/glob.d.ts +0 -0
  374. /package/dist/{utils → cjs/utils}/glob.js +0 -0
  375. /package/dist/{utils → cjs/utils}/http.d.ts +0 -0
  376. /package/dist/{utils → cjs/utils}/logger.d.ts +0 -0
  377. /package/dist/{utils → cjs/utils}/logger.js +0 -0
  378. /package/dist/{utils → cjs/utils}/package-version.d.ts +0 -0
  379. /package/dist/{utils → cjs/utils}/pool.d.ts +0 -0
  380. /package/dist/{utils → cjs/utils}/pool.js +0 -0
  381. /package/dist/{utils → cjs/utils}/resolve-bin.d.ts +0 -0
  382. /package/dist/{utils → cjs/utils}/result-collector.d.ts +0 -0
  383. /package/dist/{utils → cjs/utils}/result-collector.js +0 -0
  384. /package/dist/{utils → cjs/utils}/update-notifier.d.ts +0 -0
@@ -0,0 +1,47 @@
1
+ /** The `package.json` half of a shipped profile manifest. */
2
+ interface ProfilePkg {
3
+ dependencies?: Record<string, string>;
4
+ overrides?: Record<string, unknown>;
5
+ }
6
+ /** The `package-lock.json` half. Entries are opaque to us beyond their identity. */
7
+ interface ProfileLock {
8
+ packages: Record<string, unknown>;
9
+ }
10
+ /** A manifest pair `npm ci` can be pointed at. */
11
+ export interface MergedManifest {
12
+ pkg: object;
13
+ lockfile: object;
14
+ }
15
+ /**
16
+ * Merge several profile manifests into the one a single `npm ci` installs.
17
+ *
18
+ * This is what stops the tooling cache from paying for the same package twice.
19
+ * Installing each profile into its own directory leaves npm nothing to
20
+ * deduplicate: `commitlint` and `js` share 30 MB, and separate trees download
21
+ * both copies. One tree costs the union instead of the sum — measured at 213 MB
22
+ * against 234 for a JavaScript repository, where per-profile directories came to
23
+ * 267 (ticket 087).
24
+ *
25
+ * The merge is a union, not a resolution, and it never reaches the network. Every
26
+ * shipped manifest was cut out of our own `package-lock.json` at build time, so
27
+ * two profiles that both contain a package contain the *same* entry for it,
28
+ * byte for byte. That is the whole reason this is safe to do at run time on a
29
+ * client's machine.
30
+ *
31
+ * Which makes a disagreement impossible unless we broke the build — so it throws
32
+ * rather than picking a winner. Choosing silently would hand a client a tree
33
+ * neither profile was tested against, and the integrity hashes that make this
34
+ * design defensible would be describing something we never ran.
35
+ *
36
+ * @param profiles Directories holding the shipped manifests, in any order.
37
+ * @param read Injected by tests; defaults to reading the two files.
38
+ * @throws If two profiles disagree about a package, or a manifest cannot be read.
39
+ */
40
+ export declare function mergeManifests(profiles: Array<{
41
+ name: string;
42
+ dir: string;
43
+ }>, read?: (dir: string) => {
44
+ pkg: ProfilePkg;
45
+ lock: ProfileLock;
46
+ }): MergedManifest;
47
+ export {};
@@ -0,0 +1,85 @@
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+ const MERGED_NAME = 'pr-checkmate-tooling';
4
+ const MERGED_VERSION = '1.0.0';
5
+ /** Read a profile's shipped manifest pair from the installed package. */
6
+ function readShippedManifest(dir) {
7
+ return {
8
+ pkg: JSON.parse(fs.readFileSync(path.join(dir, 'package.json'), 'utf-8')),
9
+ lock: JSON.parse(fs.readFileSync(path.join(dir, 'package-lock.json'), 'utf-8')),
10
+ };
11
+ }
12
+ /**
13
+ * Merge several profile manifests into the one a single `npm ci` installs.
14
+ *
15
+ * This is what stops the tooling cache from paying for the same package twice.
16
+ * Installing each profile into its own directory leaves npm nothing to
17
+ * deduplicate: `commitlint` and `js` share 30 MB, and separate trees download
18
+ * both copies. One tree costs the union instead of the sum — measured at 213 MB
19
+ * against 234 for a JavaScript repository, where per-profile directories came to
20
+ * 267 (ticket 087).
21
+ *
22
+ * The merge is a union, not a resolution, and it never reaches the network. Every
23
+ * shipped manifest was cut out of our own `package-lock.json` at build time, so
24
+ * two profiles that both contain a package contain the *same* entry for it,
25
+ * byte for byte. That is the whole reason this is safe to do at run time on a
26
+ * client's machine.
27
+ *
28
+ * Which makes a disagreement impossible unless we broke the build — so it throws
29
+ * rather than picking a winner. Choosing silently would hand a client a tree
30
+ * neither profile was tested against, and the integrity hashes that make this
31
+ * design defensible would be describing something we never ran.
32
+ *
33
+ * @param profiles Directories holding the shipped manifests, in any order.
34
+ * @param read Injected by tests; defaults to reading the two files.
35
+ * @throws If two profiles disagree about a package, or a manifest cannot be read.
36
+ */
37
+ export function mergeManifests(profiles, read = readShippedManifest) {
38
+ const dependencies = {};
39
+ const overrides = {};
40
+ const packages = {};
41
+ // Which profile first claimed a given key, so a conflict names both sides.
42
+ const claimedBy = new Map();
43
+ const claim = (kind, key, value, by, into) => {
44
+ const id = `${kind}:${key}`;
45
+ const seen = claimedBy.get(id);
46
+ if (seen === undefined) {
47
+ claimedBy.set(id, by);
48
+ into[key] = value;
49
+ return;
50
+ }
51
+ if (JSON.stringify(into[key]) !== JSON.stringify(value)) {
52
+ throw new Error(`profiles "${seen}" and "${by}" disagree about ${kind} "${key}" — ` +
53
+ 'the shipped manifests are out of sync with our lockfile');
54
+ }
55
+ };
56
+ for (const { name, dir } of profiles) {
57
+ const { pkg, lock } = read(dir);
58
+ for (const [dep, version] of Object.entries(pkg.dependencies ?? {})) {
59
+ claim('dependency', dep, version, name, dependencies);
60
+ }
61
+ for (const [target, rule] of Object.entries(pkg.overrides ?? {})) {
62
+ claim('override', target, rule, name, overrides);
63
+ }
64
+ for (const [entryPath, entry] of Object.entries(lock.packages ?? {})) {
65
+ // The root entry describes the profile itself — its name, its direct
66
+ // dependencies. It is replaced by the merged root below, not merged: two
67
+ // profiles always "disagree" about it, and rightly so.
68
+ if (entryPath === '')
69
+ continue;
70
+ claim('package', entryPath, entry, name, packages);
71
+ }
72
+ }
73
+ const scoped = Object.keys(overrides).length > 0 ? { overrides } : {};
74
+ const root = { name: MERGED_NAME, version: MERGED_VERSION, dependencies, ...scoped };
75
+ return {
76
+ pkg: { ...root, private: true },
77
+ lockfile: {
78
+ name: MERGED_NAME,
79
+ version: MERGED_VERSION,
80
+ lockfileVersion: 3,
81
+ requires: true,
82
+ packages: { '': root, ...packages },
83
+ },
84
+ };
85
+ }
@@ -0,0 +1,76 @@
1
+ import type { PRCheckMateConfig } from '../../interfaces/index.js';
2
+ import type { LanguageUsage } from '../../utils/detect-language.js';
3
+ import { type EnsureOptions } from './ensure.js';
4
+ import { type Profile } from './profiles.js';
5
+ /**
6
+ * Whether a profile needs fetching at all, or already ships inside the package.
7
+ *
8
+ * This is the hinge the whole adaptive-install rollout turns on. Nearly every
9
+ * profile's packages sit in our `dependencies`, so it answers `true`, nothing is
10
+ * fetched, and a run is byte-for-byte the run it was before any of this existed.
11
+ * `pytypes` is the exception that already proves the other half works: `pyright`
12
+ * is a devDependency, so it reaches no client and is fetched on demand. When a
13
+ * package is moved out of `dependencies` it stops being present, its profile
14
+ * starts answering `false`, and the fetch turns itself on — no flag, no second
15
+ * code path, nothing to remember to flip.
16
+ *
17
+ * Which is what makes releases 2 and 3 of ticket 064 an edit to `package.json`
18
+ * rather than another change to this logic.
19
+ */
20
+ export declare function profileSatisfiedLocally(profile: Profile): boolean;
21
+ /** What the run knows about tooling before the first check starts. */
22
+ export interface ToolingPlan {
23
+ /** Check name → why its tooling is not available. Empty on a healthy run. */
24
+ unavailable: Map<string, string>;
25
+ /** Profile directories tool resolution should search. */
26
+ dirs: string[];
27
+ /**
28
+ * True when tooling is missing and `install.onMissingTool` is `"error"`. The
29
+ * affected checks fail instead of skipping: in a closed contour a check that
30
+ * quietly stops running is worse than a red build.
31
+ */
32
+ fatal: boolean;
33
+ }
34
+ interface PrepareOptions {
35
+ cwd: string;
36
+ config: PRCheckMateConfig;
37
+ /** Detected languages with file counts — reused so the tree is scanned once. */
38
+ usage: LanguageUsage[];
39
+ /** Names of the checks this run intends to execute. */
40
+ selected: string[];
41
+ /** pr-checkmate's own version; part of the cache path. */
42
+ version: string;
43
+ /**
44
+ * The profile catalogue. Defaults to the shipped one; injected by tests.
45
+ *
46
+ * A seam rather than a mock of the module, for the same reason `ensure.ts` has
47
+ * one: nearly every profile ships inside the package, so the interesting half
48
+ * of this function — a profile that is genuinely absent — is otherwise reachable
49
+ * only through a network install in a unit test. The code that runs when a
50
+ * package leaves `dependencies` must be tested before that day, not on it.
51
+ */
52
+ profiles?: Profile[];
53
+ /** The fetch itself, forwarded to `ensureTooling`. Injected by tests. */
54
+ installer?: EnsureOptions['installer'];
55
+ }
56
+ /**
57
+ * Make sure the tooling this run needs is present, and say what is missing.
58
+ *
59
+ * Runs once, before the first check, and answers two questions the run cannot
60
+ * proceed honestly without: which directories tool resolution should search, and
61
+ * which checks have no tool to run. The second is the one ticket 057 is about —
62
+ * a check whose tooling never arrived must appear in the report saying so, not
63
+ * vanish from it.
64
+ *
65
+ * Only profiles backing checks that are actually selected are considered, so
66
+ * `severity: { "Spellcheck": "off" }` stops costing a download rather than only a
67
+ * row in the report (lever B of ticket 064).
68
+ */
69
+ export declare function prepareTooling(opts: PrepareOptions): Promise<ToolingPlan>;
70
+ /**
71
+ * The plan for a run where preparation did not happen — nothing missing, nothing
72
+ * registered. Built fresh each time rather than shared: a caller holding a plan
73
+ * must not be able to see another run's.
74
+ */
75
+ export declare function noTooling(): ToolingPlan;
76
+ export {};
@@ -0,0 +1,142 @@
1
+ import { logger } from '../../utils/logger.js';
2
+ import { clearToolPaths, packagePresent, registerToolPaths } from '../../utils/resolve-bin.js';
3
+ import { ensureTooling } from './ensure.js';
4
+ import { PROFILES, planProfiles } from './profiles.js';
5
+ /**
6
+ * Whether a profile needs fetching at all, or already ships inside the package.
7
+ *
8
+ * This is the hinge the whole adaptive-install rollout turns on. Nearly every
9
+ * profile's packages sit in our `dependencies`, so it answers `true`, nothing is
10
+ * fetched, and a run is byte-for-byte the run it was before any of this existed.
11
+ * `pytypes` is the exception that already proves the other half works: `pyright`
12
+ * is a devDependency, so it reaches no client and is fetched on demand. When a
13
+ * package is moved out of `dependencies` it stops being present, its profile
14
+ * starts answering `false`, and the fetch turns itself on — no flag, no second
15
+ * code path, nothing to remember to flip.
16
+ *
17
+ * Which is what makes releases 2 and 3 of ticket 064 an edit to `package.json`
18
+ * rather than another change to this logic.
19
+ */
20
+ export function profileSatisfiedLocally(profile) {
21
+ return profile.packages.every(pkg => packagePresent(pkg));
22
+ }
23
+ /** Profiles blocked outright by `install.deny`, with a line saying so. */
24
+ function denied(profile, deny) {
25
+ const blocked = profile.packages.filter(pkg => deny.has(pkg));
26
+ if (blocked.length === 0)
27
+ return null;
28
+ return `install.deny lists ${blocked.join(', ')}`;
29
+ }
30
+ /**
31
+ * Make sure the tooling this run needs is present, and say what is missing.
32
+ *
33
+ * Runs once, before the first check, and answers two questions the run cannot
34
+ * proceed honestly without: which directories tool resolution should search, and
35
+ * which checks have no tool to run. The second is the one ticket 057 is about —
36
+ * a check whose tooling never arrived must appear in the report saying so, not
37
+ * vanish from it.
38
+ *
39
+ * Only profiles backing checks that are actually selected are considered, so
40
+ * `severity: { "Spellcheck": "off" }` stops costing a download rather than only a
41
+ * row in the report (lever B of ticket 064).
42
+ */
43
+ export async function prepareTooling(opts) {
44
+ // Every run starts from no registered roots. The SDK can call `runChecks` more
45
+ // than once in one process, and a directory registered by a previous run — for
46
+ // a different repository, with a different profile set — must not still be on
47
+ // the search path for this one.
48
+ clearToolPaths();
49
+ const install = opts.config.install ?? {};
50
+ const strategy = process.env.PR_CHECKMATE_INSTALL_STRATEGY ?? install.strategy ?? 'adaptive';
51
+ const onMissing = install.onMissingTool ?? 'auto';
52
+ const deny = new Set(install.deny ?? []);
53
+ // Which profiles this repository needs: languages by file count, universal
54
+ // profiles by whether their check survived config. `install.profiles` and
55
+ // `excludeProfiles` have already had their say inside `planProfiles`.
56
+ const required = new Set(planProfiles(opts.usage, opts.config)
57
+ .filter(decision => decision.required)
58
+ .map(decision => decision.profile));
59
+ // A profile nobody in this run would use is not worth a thought, let alone a
60
+ // download. `eager` opts out of that reasoning by definition: it exists so a
61
+ // container build or an air-gapped mirror can hold everything up front.
62
+ const chosen = opts.selected.length > 0 ? new Set(opts.selected) : null;
63
+ const wanted = (opts.profiles ?? PROFILES).filter(profile => {
64
+ if (strategy === 'eager')
65
+ return true;
66
+ if (!required.has(profile.name))
67
+ return false;
68
+ return !chosen || profile.checks.some(check => chosen.has(check));
69
+ });
70
+ const unavailable = new Map();
71
+ const dirs = [];
72
+ const miss = (profile, reason) => {
73
+ for (const check of profile.checks)
74
+ unavailable.set(check, reason);
75
+ };
76
+ const toFetch = [];
77
+ for (const profile of wanted) {
78
+ // Bundled tooling is the answer to "where is it" for most profiles, and
79
+ // asking first is what keeps this whole path free of network calls.
80
+ if (profileSatisfiedLocally(profile))
81
+ continue;
82
+ const block = denied(profile, deny);
83
+ if (block) {
84
+ miss(profile, block);
85
+ continue;
86
+ }
87
+ // No early exit for `install.strategy: "manual"`. It means "never fetch",
88
+ // and `ensureTooling` enforces that — but only after checking the cache, so
89
+ // pre-warmed tooling is still used. Returning here instead meant `manual`
90
+ // also refused tooling that was already downloaded.
91
+ if (onMissing === 'skip') {
92
+ miss(profile, 'install.onMissingTool is "skip"');
93
+ continue;
94
+ }
95
+ toFetch.push(profile);
96
+ }
97
+ // One call, one directory, one lock — for the whole run rather than per profile.
98
+ // Profiles overlap heavily, and a tree each made the client download the shared
99
+ // half once per profile that named it (ticket 087).
100
+ //
101
+ // Reached only when something actually needs fetching, which is also what keeps
102
+ // the cache directory untouched otherwise: resolving it is not a read — it
103
+ // creates the directory and warns when the configured path is unwritable, and a
104
+ // container with a read-only home would print that on every single run.
105
+ if (toFetch.length > 0) {
106
+ const result = await ensureTooling(toFetch.map(profile => profile.name), {
107
+ cwd: opts.cwd,
108
+ version: opts.version,
109
+ install,
110
+ ...(opts.installer ? { installer: opts.installer } : {}),
111
+ });
112
+ if (result.status === 'failed' || result.status === 'skipped') {
113
+ for (const profile of toFetch)
114
+ miss(profile, result.reason);
115
+ }
116
+ else if (result.dir) {
117
+ dirs.push(result.dir);
118
+ }
119
+ }
120
+ if (unavailable.size > 0) {
121
+ // Always logged, never behind --debug. A check that did not run is the
122
+ // failure mode this whole layer exists to make loud.
123
+ const names = [...new Set(unavailable.keys())].join(', ');
124
+ logger.warn(`[install]: ⚠️ tooling unavailable — these checks cannot run: ${names}`);
125
+ if (onMissing === 'error') {
126
+ logger.error('[install]: ❌ install.onMissingTool is "error" — the affected checks fail');
127
+ }
128
+ else {
129
+ logger.info('[install]: Pre-warm the cache with: npx pr-checkmate install --all');
130
+ }
131
+ }
132
+ registerToolPaths(dirs);
133
+ return { unavailable, dirs, fatal: onMissing === 'error' && unavailable.size > 0 };
134
+ }
135
+ /**
136
+ * The plan for a run where preparation did not happen — nothing missing, nothing
137
+ * registered. Built fresh each time rather than shared: a caller holding a plan
138
+ * must not be able to see another run's.
139
+ */
140
+ export function noTooling() {
141
+ return { unavailable: new Map(), dirs: [], fatal: false };
142
+ }
@@ -0,0 +1,78 @@
1
+ import type { PRCheckMateConfig } from '../../interfaces/index.js';
2
+ import type { Language, LanguageUsage } from '../../utils/detect-language.js';
3
+ /**
4
+ * A named bundle of tooling, and the checks that stop working without it.
5
+ *
6
+ * The package ships ~233 MB of tooling, and no repository needs all of it: a
7
+ * Python service pays for the whole JavaScript toolchain, a repository with
8
+ * Spellcheck switched off still pays for cspell. Profiles are how that stops —
9
+ * they name which slice of the tooling a given repository actually needs.
10
+ *
11
+ * `checks` is not documentation. It is what turns a failed install into an
12
+ * honest report: when a profile is missing, exactly those checks skip, with the
13
+ * reason, instead of quietly disappearing (the mistake of ticket 057).
14
+ */
15
+ export interface Profile {
16
+ name: ProfileName;
17
+ /** Top-level packages installed for this profile. */
18
+ packages: string[];
19
+ /** Registry names of the checks that need it. */
20
+ checks: string[];
21
+ /**
22
+ * Languages that make this profile necessary. Absent for profiles driven by
23
+ * enabled checks rather than by what the repository is written in.
24
+ */
25
+ languages?: Language[];
26
+ /**
27
+ * An extra condition on the client's config, for a language profile whose
28
+ * checks can be switched off by a key of their own.
29
+ *
30
+ * `severity: { "X": "off" }` is already honoured for every profile, but it is
31
+ * not the only off switch: `python.typecheck: false` and `go.enabled: false`
32
+ * are the ones a client actually writes, and a language profile decided on
33
+ * file counts alone downloads the tooling regardless. For `pytypes` that is
34
+ * 19 MB fetched to run nothing.
35
+ *
36
+ * Deliberately a predicate over the config rather than a list of keys: the
37
+ * condition it mirrors lives in the check's own `applies`, and expressing it
38
+ * the same way is what makes the two readable side by side.
39
+ */
40
+ enabledBy?(config: PRCheckMateConfig): boolean;
41
+ }
42
+ export type ProfileName = 'core' | 'js' | 'python' | 'pytypes' | 'cpp' | 'go' | 'spellcheck' | 'markdown' | 'commitlint' | 'duplicate';
43
+ /**
44
+ * The catalogue.
45
+ *
46
+ * Sizes in the comments are measured exclusive footprints — what leaves with the
47
+ * profile and is shared with nothing else (see ticket 069).
48
+ */
49
+ export declare const PROFILES: Profile[];
50
+ /** The profile a check belongs to, or `undefined` when it needs no extra tooling. */
51
+ export declare function profileForCheck(check: string): Profile | undefined;
52
+ /** Why a profile is (or is not) part of this run — the answer `doctor` prints. */
53
+ export interface ProfileDecision {
54
+ profile: ProfileName;
55
+ required: boolean;
56
+ reason: string;
57
+ }
58
+ /**
59
+ * Decide which profiles this repository needs, and why.
60
+ *
61
+ * The two inputs are deliberately different in kind:
62
+ *
63
+ * - **Languages are counted in files, never in markers.** A Python service that
64
+ * installed us through npm has a `package.json`, which is a JavaScript marker
65
+ * — and downloading 152 MB of JavaScript tooling because of the file that
66
+ * installed us would be the whole feature backfiring. `LanguageUsage.files`
67
+ * exists for exactly this (ticket 068).
68
+ * - **Universal profiles are driven by enabled checks**, so `severity: {
69
+ * "Spellcheck": "off" }` starts saving bandwidth instead of only a report row.
70
+ *
71
+ * @param usage Detected languages with their tracked file counts.
72
+ * @param config The client's config; `install.profiles` and `install.excludeProfiles`
73
+ * have the last word, in that order — an explicit exclusion beats an explicit
74
+ * request, because it is the one that can be a hard requirement (air-gapped,
75
+ * licence policy, a runner that must not download a wasm binary).
76
+ * @returns One decision per profile, in catalogue order.
77
+ */
78
+ export declare function planProfiles(usage: LanguageUsage[], config: PRCheckMateConfig): ProfileDecision[];
@@ -0,0 +1,192 @@
1
+ /**
2
+ * The catalogue.
3
+ *
4
+ * Sizes in the comments are measured exclusive footprints — what leaves with the
5
+ * profile and is shared with nothing else (see ticket 069).
6
+ */
7
+ export const PROFILES = [
8
+ {
9
+ // Always installed. Everything here backs a check that runs on any
10
+ // repository whatever it is written in, so there is nothing to decide.
11
+ name: 'core',
12
+ packages: ['execa', 'yaml', 'inquirer', 'gitleaks-secret-scanner-fixed'],
13
+ checks: ['Security Scan'],
14
+ },
15
+ {
16
+ // 152 MB, the largest by far, and the one a Python repository pays for
17
+ // today with nothing to show for it.
18
+ name: 'js',
19
+ packages: [
20
+ 'typescript',
21
+ 'eslint',
22
+ 'eslint-config-prettier',
23
+ 'eslint-plugin-import-x',
24
+ 'eslint-plugin-jsdoc',
25
+ 'eslint-plugin-prettier',
26
+ 'eslint-plugin-sonarjs',
27
+ '@typescript-eslint/eslint-plugin',
28
+ '@typescript-eslint/parser',
29
+ 'prettier',
30
+ 'dpdm',
31
+ 'knip',
32
+ 'ts-unused-exports',
33
+ 'license-checker-rseidelsohn',
34
+ ],
35
+ checks: [
36
+ 'ESLint',
37
+ 'Prettier',
38
+ 'TypeScript',
39
+ 'Circular Deps',
40
+ 'Dependencies',
41
+ 'Dead Code',
42
+ 'License Check',
43
+ ],
44
+ languages: ['typescript', 'javascript'],
45
+ },
46
+ {
47
+ name: 'python',
48
+ packages: ['@astral-sh/ruff-wasm-nodejs'],
49
+ checks: ['Ruff Lint', 'Ruff Format'],
50
+ languages: ['python'],
51
+ },
52
+ {
53
+ // Separate from `python` because it is 19 MB against ruff's 12, and because
54
+ // the two answer different questions: plenty of repositories want the linter
55
+ // and have their own opinion about type checking. Bundling them would make
56
+ // `python.typecheck: false` cost the download anyway, which is the feature
57
+ // defeating itself.
58
+ name: 'pytypes',
59
+ packages: ['pyright'],
60
+ checks: ['Python Types'],
61
+ languages: ['python'],
62
+ enabledBy: config => config.python?.typecheck !== false && config.python?.enabled !== false,
63
+ },
64
+ {
65
+ name: 'cpp',
66
+ packages: ['@wasm-fmt/clang-format'],
67
+ checks: ['C++ Format'],
68
+ languages: ['cpp'],
69
+ },
70
+ {
71
+ // Go Format only. `go vet` needs the toolchain itself, which is not ours to
72
+ // ship, so it stays a runner dependency and is deliberately absent here.
73
+ name: 'go',
74
+ packages: ['@wasm-fmt/gofmt'],
75
+ checks: ['Go Format'],
76
+ languages: ['go'],
77
+ enabledBy: config => config.go?.enabled !== false,
78
+ },
79
+ {
80
+ // The four below are not languages. They are single checks with heavy
81
+ // tooling behind them, which is exactly why they are separate: switching
82
+ // one off should stop costing megabytes, not just a line in the report.
83
+ name: 'spellcheck',
84
+ packages: ['cspell'],
85
+ checks: ['Spellcheck'],
86
+ },
87
+ {
88
+ name: 'markdown',
89
+ packages: ['markdownlint'],
90
+ checks: ['Markdown'],
91
+ },
92
+ {
93
+ name: 'commitlint',
94
+ packages: ['@commitlint/cli', '@commitlint/config-conventional'],
95
+ checks: ['Commitlint'],
96
+ },
97
+ {
98
+ name: 'duplicate',
99
+ packages: ['jscpd'],
100
+ checks: ['Duplicate Code'],
101
+ },
102
+ ];
103
+ /** The profile a check belongs to, or `undefined` when it needs no extra tooling. */
104
+ export function profileForCheck(check) {
105
+ return PROFILES.find(p => p.checks.includes(check));
106
+ }
107
+ /**
108
+ * A check counts as enabled unless it is switched off.
109
+ *
110
+ * Deliberately asymmetric with how the runner selects checks: this must not
111
+ * import the registry (that would drag every check into the install path), and
112
+ * being wrong in the "enabled" direction only costs a download, while being
113
+ * wrong the other way silently removes a check. So anything not explicitly off
114
+ * is treated as on.
115
+ */
116
+ function isCheckEnabled(check, config) {
117
+ return config.severity?.[check] !== 'off';
118
+ }
119
+ /**
120
+ * Decide which profiles this repository needs, and why.
121
+ *
122
+ * The two inputs are deliberately different in kind:
123
+ *
124
+ * - **Languages are counted in files, never in markers.** A Python service that
125
+ * installed us through npm has a `package.json`, which is a JavaScript marker
126
+ * — and downloading 152 MB of JavaScript tooling because of the file that
127
+ * installed us would be the whole feature backfiring. `LanguageUsage.files`
128
+ * exists for exactly this (ticket 068).
129
+ * - **Universal profiles are driven by enabled checks**, so `severity: {
130
+ * "Spellcheck": "off" }` starts saving bandwidth instead of only a report row.
131
+ *
132
+ * @param usage Detected languages with their tracked file counts.
133
+ * @param config The client's config; `install.profiles` and `install.excludeProfiles`
134
+ * have the last word, in that order — an explicit exclusion beats an explicit
135
+ * request, because it is the one that can be a hard requirement (air-gapped,
136
+ * licence policy, a runner that must not download a wasm binary).
137
+ * @returns One decision per profile, in catalogue order.
138
+ */
139
+ export function planProfiles(usage, config) {
140
+ const install = config.install ?? {};
141
+ const minFiles = Math.max(1, install.minFilesPerLanguage ?? 1);
142
+ const requested = new Set(install.profiles ?? []);
143
+ const excluded = new Set(install.excludeProfiles ?? []);
144
+ return PROFILES.map(profile => {
145
+ const decision = decide(profile, usage, config, minFiles);
146
+ if (excluded.has(profile.name)) {
147
+ return {
148
+ profile: profile.name,
149
+ required: false,
150
+ reason: 'excluded by install.excludeProfiles',
151
+ };
152
+ }
153
+ if (!decision.required && requested.has(profile.name)) {
154
+ return { profile: profile.name, required: true, reason: 'requested by install.profiles' };
155
+ }
156
+ return { profile: profile.name, required: decision.required, reason: decision.reason };
157
+ });
158
+ }
159
+ /** The automatic half of {@link planProfiles}, before the client's overrides. */
160
+ function decide(profile, usage, config, minFiles) {
161
+ if (profile.name === 'core')
162
+ return { required: true, reason: 'always installed' };
163
+ if (profile.languages) {
164
+ // Asked before the file counts, because it is the cheaper and the more
165
+ // definite answer: a client who wrote `python.typecheck: false` has settled
166
+ // the question, and counting `.py` files can only override them.
167
+ if (profile.enabledBy && !profile.enabledBy(config)) {
168
+ return { required: false, reason: `${profile.checks.join(', ')} switched off` };
169
+ }
170
+ const found = profile.languages
171
+ .map(lang => usage.find(u => u.lang === lang))
172
+ .filter((u) => Boolean(u) && u.files >= minFiles);
173
+ if (found.length > 0) {
174
+ const detail = found.map(u => `${u.files} ${u.lang} file(s)`).join(', ');
175
+ return { required: true, reason: detail };
176
+ }
177
+ // Named separately from "no files": a marker with no source files is the
178
+ // OctoBot case — a `Cargo.toml` beside zero `.rs`. The language is real
179
+ // enough to run checks for; it is not real enough to download a toolchain.
180
+ const markerOnly = profile.languages.some(lang => usage.some(u => u.lang === lang));
181
+ return {
182
+ required: false,
183
+ reason: markerOnly
184
+ ? 'declared by a marker file but no source files tracked'
185
+ : 'no source files tracked',
186
+ };
187
+ }
188
+ const enabled = profile.checks.filter(check => isCheckEnabled(check, config));
189
+ return enabled.length > 0
190
+ ? { required: true, reason: `${enabled.join(', ')} enabled` }
191
+ : { required: false, reason: `${profile.checks.join(', ')} switched off` };
192
+ }
@@ -0,0 +1,41 @@
1
+ import type { CheckContext } from '../types.js';
2
+ /** One reuse decision, with the sentence that explains it. */
3
+ interface ReuseDecision {
4
+ /** Search roots to prefer, or `undefined` to use our own copy. */
5
+ paths?: string[];
6
+ reason: string;
7
+ }
8
+ interface ReuseOptions {
9
+ /**
10
+ * The tool will read the client's OWN configuration file.
11
+ *
12
+ * When it will, the version check is the wrong question and must not be asked:
13
+ * a repository with ESLint 8 and a legacy `.eslintrc` can only be linted by
14
+ * ESLint 8, because ESLint 10 does not read eslintrc — and falling back to ours
15
+ * on the strength of a major mismatch would break precisely the case the reuse
16
+ * was there to serve. TypeScript is the same shape permanently: the check only
17
+ * applies when the repository has a `tsconfig.json`, so their compiler is
18
+ * always the one their config was written for.
19
+ *
20
+ * The version check exists for the opposite case — the client's old tool being
21
+ * handed configuration WE generated.
22
+ */
23
+ clientOwnsConfig?: boolean;
24
+ }
25
+ /**
26
+ * Decide whether this run should prefer the client's copy of `pkgName`.
27
+ *
28
+ * `compatible` (the default) reuses when the client's major matches ours, or when
29
+ * the client's own configuration is what the tool will read. A mismatch is not an
30
+ * error — we have our own copy — so it downgrades to ours with a line saying why.
31
+ */
32
+ export declare function reuseDecision(pkgName: string, ctx: CheckContext, opts?: ReuseOptions): ReuseDecision;
33
+ /**
34
+ * The search roots a check should prefer for `pkgName`, logging the reason once.
35
+ *
36
+ * The reason is logged rather than returned to each caller because it answers the
37
+ * question every confusing lint result starts with — "whose ESLint ran" — and no
38
+ * check should have to remember to say so.
39
+ */
40
+ export declare function clientToolPaths(pkgName: string, ctx: CheckContext, opts?: ReuseOptions): string[] | undefined;
41
+ export {};