@opensip-cli/checks-typescript 0.1.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 (404) hide show
  1. package/LICENSE +202 -0
  2. package/NOTICE +8 -0
  3. package/README.md +31 -0
  4. package/dist/__tests__/all-checks-execute.test.d.ts +12 -0
  5. package/dist/__tests__/all-checks-execute.test.d.ts.map +1 -0
  6. package/dist/__tests__/all-checks-execute.test.js +846 -0
  7. package/dist/__tests__/all-checks-execute.test.js.map +1 -0
  8. package/dist/__tests__/behavior-fixtures-2.test.d.ts +9 -0
  9. package/dist/__tests__/behavior-fixtures-2.test.d.ts.map +1 -0
  10. package/dist/__tests__/behavior-fixtures-2.test.js +625 -0
  11. package/dist/__tests__/behavior-fixtures-2.test.js.map +1 -0
  12. package/dist/__tests__/behavior-fixtures-3.test.d.ts +7 -0
  13. package/dist/__tests__/behavior-fixtures-3.test.d.ts.map +1 -0
  14. package/dist/__tests__/behavior-fixtures-3.test.js +658 -0
  15. package/dist/__tests__/behavior-fixtures-3.test.js.map +1 -0
  16. package/dist/__tests__/behavior-fixtures-4.test.d.ts +8 -0
  17. package/dist/__tests__/behavior-fixtures-4.test.d.ts.map +1 -0
  18. package/dist/__tests__/behavior-fixtures-4.test.js +590 -0
  19. package/dist/__tests__/behavior-fixtures-4.test.js.map +1 -0
  20. package/dist/__tests__/behavior-fixtures-5.test.d.ts +7 -0
  21. package/dist/__tests__/behavior-fixtures-5.test.d.ts.map +1 -0
  22. package/dist/__tests__/behavior-fixtures-5.test.js +548 -0
  23. package/dist/__tests__/behavior-fixtures-5.test.js.map +1 -0
  24. package/dist/__tests__/behavior-fixtures-6.test.d.ts +18 -0
  25. package/dist/__tests__/behavior-fixtures-6.test.d.ts.map +1 -0
  26. package/dist/__tests__/behavior-fixtures-6.test.js +1700 -0
  27. package/dist/__tests__/behavior-fixtures-6.test.js.map +1 -0
  28. package/dist/__tests__/behavior-fixtures.test.d.ts +10 -0
  29. package/dist/__tests__/behavior-fixtures.test.d.ts.map +1 -0
  30. package/dist/__tests__/behavior-fixtures.test.js +812 -0
  31. package/dist/__tests__/behavior-fixtures.test.js.map +1 -0
  32. package/dist/__tests__/branch-fixtures-2.test.d.ts +6 -0
  33. package/dist/__tests__/branch-fixtures-2.test.d.ts.map +1 -0
  34. package/dist/__tests__/branch-fixtures-2.test.js +1369 -0
  35. package/dist/__tests__/branch-fixtures-2.test.js.map +1 -0
  36. package/dist/__tests__/branch-fixtures-3.test.d.ts +7 -0
  37. package/dist/__tests__/branch-fixtures-3.test.d.ts.map +1 -0
  38. package/dist/__tests__/branch-fixtures-3.test.js +877 -0
  39. package/dist/__tests__/branch-fixtures-3.test.js.map +1 -0
  40. package/dist/__tests__/branch-fixtures.test.d.ts +6 -0
  41. package/dist/__tests__/branch-fixtures.test.d.ts.map +1 -0
  42. package/dist/__tests__/branch-fixtures.test.js +1072 -0
  43. package/dist/__tests__/branch-fixtures.test.js.map +1 -0
  44. package/dist/__tests__/checks.test.d.ts +2 -0
  45. package/dist/__tests__/checks.test.d.ts.map +1 -0
  46. package/dist/__tests__/checks.test.js +39 -0
  47. package/dist/__tests__/checks.test.js.map +1 -0
  48. package/dist/__tests__/fixture-coverage.allowlist.d.ts +19 -0
  49. package/dist/__tests__/fixture-coverage.allowlist.d.ts.map +1 -0
  50. package/dist/__tests__/fixture-coverage.allowlist.js +27 -0
  51. package/dist/__tests__/fixture-coverage.allowlist.js.map +1 -0
  52. package/dist/__tests__/fixture-coverage.test.d.ts +13 -0
  53. package/dist/__tests__/fixture-coverage.test.d.ts.map +1 -0
  54. package/dist/__tests__/fixture-coverage.test.js +57 -0
  55. package/dist/__tests__/fixture-coverage.test.js.map +1 -0
  56. package/dist/__tests__/no-bootstrap-tool-import.test.d.ts +2 -0
  57. package/dist/__tests__/no-bootstrap-tool-import.test.d.ts.map +1 -0
  58. package/dist/__tests__/no-bootstrap-tool-import.test.js +75 -0
  59. package/dist/__tests__/no-bootstrap-tool-import.test.js.map +1 -0
  60. package/dist/__tests__/phantom-dependency-detection.test.d.ts +12 -0
  61. package/dist/__tests__/phantom-dependency-detection.test.d.ts.map +1 -0
  62. package/dist/__tests__/phantom-dependency-detection.test.js +112 -0
  63. package/dist/__tests__/phantom-dependency-detection.test.js.map +1 -0
  64. package/dist/__tests__/typescript-frontend.test.d.ts +8 -0
  65. package/dist/__tests__/typescript-frontend.test.d.ts.map +1 -0
  66. package/dist/__tests__/typescript-frontend.test.js +57 -0
  67. package/dist/__tests__/typescript-frontend.test.js.map +1 -0
  68. package/dist/checks/architecture/circular-import-detection.d.ts +14 -0
  69. package/dist/checks/architecture/circular-import-detection.d.ts.map +1 -0
  70. package/dist/checks/architecture/circular-import-detection.js +55 -0
  71. package/dist/checks/architecture/circular-import-detection.js.map +1 -0
  72. package/dist/checks/architecture/contracts-schema-consistency.d.ts +11 -0
  73. package/dist/checks/architecture/contracts-schema-consistency.d.ts.map +1 -0
  74. package/dist/checks/architecture/contracts-schema-consistency.js +75 -0
  75. package/dist/checks/architecture/contracts-schema-consistency.js.map +1 -0
  76. package/dist/checks/architecture/drizzle-orm-migration-guardrails.d.ts +12 -0
  77. package/dist/checks/architecture/drizzle-orm-migration-guardrails.d.ts.map +1 -0
  78. package/dist/checks/architecture/drizzle-orm-migration-guardrails.js +92 -0
  79. package/dist/checks/architecture/drizzle-orm-migration-guardrails.js.map +1 -0
  80. package/dist/checks/architecture/index.d.ts +10 -0
  81. package/dist/checks/architecture/index.d.ts.map +1 -0
  82. package/dist/checks/architecture/index.js +10 -0
  83. package/dist/checks/architecture/index.js.map +1 -0
  84. package/dist/checks/architecture/missing-type-exports.d.ts +13 -0
  85. package/dist/checks/architecture/missing-type-exports.d.ts.map +1 -0
  86. package/dist/checks/architecture/missing-type-exports.js +245 -0
  87. package/dist/checks/architecture/missing-type-exports.js.map +1 -0
  88. package/dist/checks/architecture/module-coupling-fan-out.d.ts +20 -0
  89. package/dist/checks/architecture/module-coupling-fan-out.d.ts.map +1 -0
  90. package/dist/checks/architecture/module-coupling-fan-out.js +120 -0
  91. package/dist/checks/architecture/module-coupling-fan-out.js.map +1 -0
  92. package/dist/checks/architecture/no-bootstrap-tool-import.d.ts +38 -0
  93. package/dist/checks/architecture/no-bootstrap-tool-import.d.ts.map +1 -0
  94. package/dist/checks/architecture/no-bootstrap-tool-import.js +95 -0
  95. package/dist/checks/architecture/no-bootstrap-tool-import.js.map +1 -0
  96. package/dist/checks/architecture/package-json-exports-field.d.ts +10 -0
  97. package/dist/checks/architecture/package-json-exports-field.d.ts.map +1 -0
  98. package/dist/checks/architecture/package-json-exports-field.js +56 -0
  99. package/dist/checks/architecture/package-json-exports-field.js.map +1 -0
  100. package/dist/checks/architecture/phantom-dependency-detection.d.ts +22 -0
  101. package/dist/checks/architecture/phantom-dependency-detection.d.ts.map +1 -0
  102. package/dist/checks/architecture/phantom-dependency-detection.js +330 -0
  103. package/dist/checks/architecture/phantom-dependency-detection.js.map +1 -0
  104. package/dist/checks/architecture/tsconfig-extends-validation.d.ts +10 -0
  105. package/dist/checks/architecture/tsconfig-extends-validation.d.ts.map +1 -0
  106. package/dist/checks/architecture/tsconfig-extends-validation.js +78 -0
  107. package/dist/checks/architecture/tsconfig-extends-validation.js.map +1 -0
  108. package/dist/checks/index.d.ts +6 -0
  109. package/dist/checks/index.d.ts.map +1 -0
  110. package/dist/checks/index.js +6 -0
  111. package/dist/checks/index.js.map +1 -0
  112. package/dist/checks/quality/api/api-contract-validation.d.ts +15 -0
  113. package/dist/checks/quality/api/api-contract-validation.d.ts.map +1 -0
  114. package/dist/checks/quality/api/api-contract-validation.js +316 -0
  115. package/dist/checks/quality/api/api-contract-validation.js.map +1 -0
  116. package/dist/checks/quality/api/api-response-validation.d.ts +14 -0
  117. package/dist/checks/quality/api/api-response-validation.d.ts.map +1 -0
  118. package/dist/checks/quality/api/api-response-validation.js +209 -0
  119. package/dist/checks/quality/api/api-response-validation.js.map +1 -0
  120. package/dist/checks/quality/api/fastify-route-validation.d.ts +14 -0
  121. package/dist/checks/quality/api/fastify-route-validation.d.ts.map +1 -0
  122. package/dist/checks/quality/api/fastify-route-validation.js +298 -0
  123. package/dist/checks/quality/api/fastify-route-validation.js.map +1 -0
  124. package/dist/checks/quality/api/fastify-schema-coverage.d.ts +11 -0
  125. package/dist/checks/quality/api/fastify-schema-coverage.d.ts.map +1 -0
  126. package/dist/checks/quality/api/fastify-schema-coverage.js +261 -0
  127. package/dist/checks/quality/api/fastify-schema-coverage.js.map +1 -0
  128. package/dist/checks/quality/api/index.d.ts +5 -0
  129. package/dist/checks/quality/api/index.d.ts.map +1 -0
  130. package/dist/checks/quality/api/index.js +5 -0
  131. package/dist/checks/quality/api/index.js.map +1 -0
  132. package/dist/checks/quality/code-structure/duplicate-utility-functions.d.ts +32 -0
  133. package/dist/checks/quality/code-structure/duplicate-utility-functions.d.ts.map +1 -0
  134. package/dist/checks/quality/code-structure/duplicate-utility-functions.js +451 -0
  135. package/dist/checks/quality/code-structure/duplicate-utility-functions.js.map +1 -0
  136. package/dist/checks/quality/code-structure/index.d.ts +3 -0
  137. package/dist/checks/quality/code-structure/index.d.ts.map +1 -0
  138. package/dist/checks/quality/code-structure/index.js +3 -0
  139. package/dist/checks/quality/code-structure/index.js.map +1 -0
  140. package/dist/checks/quality/code-structure/no-any-types.d.ts +13 -0
  141. package/dist/checks/quality/code-structure/no-any-types.d.ts.map +1 -0
  142. package/dist/checks/quality/code-structure/no-any-types.js +116 -0
  143. package/dist/checks/quality/code-structure/no-any-types.js.map +1 -0
  144. package/dist/checks/quality/data-integrity/__tests__/null-safety-fp.test.d.ts +15 -0
  145. package/dist/checks/quality/data-integrity/__tests__/null-safety-fp.test.d.ts.map +1 -0
  146. package/dist/checks/quality/data-integrity/__tests__/null-safety-fp.test.js +51 -0
  147. package/dist/checks/quality/data-integrity/__tests__/null-safety-fp.test.js.map +1 -0
  148. package/dist/checks/quality/data-integrity/array-validation.d.ts +16 -0
  149. package/dist/checks/quality/data-integrity/array-validation.d.ts.map +1 -0
  150. package/dist/checks/quality/data-integrity/array-validation.js +508 -0
  151. package/dist/checks/quality/data-integrity/array-validation.js.map +1 -0
  152. package/dist/checks/quality/data-integrity/database-index-coverage.d.ts +14 -0
  153. package/dist/checks/quality/data-integrity/database-index-coverage.d.ts.map +1 -0
  154. package/dist/checks/quality/data-integrity/database-index-coverage.js +235 -0
  155. package/dist/checks/quality/data-integrity/database-index-coverage.js.map +1 -0
  156. package/dist/checks/quality/data-integrity/database-schema-validation.d.ts +16 -0
  157. package/dist/checks/quality/data-integrity/database-schema-validation.d.ts.map +1 -0
  158. package/dist/checks/quality/data-integrity/database-schema-validation.js +328 -0
  159. package/dist/checks/quality/data-integrity/database-schema-validation.js.map +1 -0
  160. package/dist/checks/quality/data-integrity/in-memory-repository-detection.d.ts +14 -0
  161. package/dist/checks/quality/data-integrity/in-memory-repository-detection.d.ts.map +1 -0
  162. package/dist/checks/quality/data-integrity/in-memory-repository-detection.js +157 -0
  163. package/dist/checks/quality/data-integrity/in-memory-repository-detection.js.map +1 -0
  164. package/dist/checks/quality/data-integrity/index.d.ts +8 -0
  165. package/dist/checks/quality/data-integrity/index.d.ts.map +1 -0
  166. package/dist/checks/quality/data-integrity/index.js +8 -0
  167. package/dist/checks/quality/data-integrity/index.js.map +1 -0
  168. package/dist/checks/quality/data-integrity/missing-input-validation.d.ts +12 -0
  169. package/dist/checks/quality/data-integrity/missing-input-validation.d.ts.map +1 -0
  170. package/dist/checks/quality/data-integrity/missing-input-validation.js +180 -0
  171. package/dist/checks/quality/data-integrity/missing-input-validation.js.map +1 -0
  172. package/dist/checks/quality/data-integrity/null-safety.d.ts +33 -0
  173. package/dist/checks/quality/data-integrity/null-safety.d.ts.map +1 -0
  174. package/dist/checks/quality/data-integrity/null-safety.js +766 -0
  175. package/dist/checks/quality/data-integrity/null-safety.js.map +1 -0
  176. package/dist/checks/quality/data-integrity/numeric-validation.d.ts +12 -0
  177. package/dist/checks/quality/data-integrity/numeric-validation.d.ts.map +1 -0
  178. package/dist/checks/quality/data-integrity/numeric-validation.js +409 -0
  179. package/dist/checks/quality/data-integrity/numeric-validation.js.map +1 -0
  180. package/dist/checks/quality/frontend/a11y-form-labels.d.ts +14 -0
  181. package/dist/checks/quality/frontend/a11y-form-labels.d.ts.map +1 -0
  182. package/dist/checks/quality/frontend/a11y-form-labels.js +93 -0
  183. package/dist/checks/quality/frontend/a11y-form-labels.js.map +1 -0
  184. package/dist/checks/quality/frontend/a11y-semantic-html.d.ts +14 -0
  185. package/dist/checks/quality/frontend/a11y-semantic-html.d.ts.map +1 -0
  186. package/dist/checks/quality/frontend/a11y-semantic-html.js +88 -0
  187. package/dist/checks/quality/frontend/a11y-semantic-html.js.map +1 -0
  188. package/dist/checks/quality/frontend/index.d.ts +4 -0
  189. package/dist/checks/quality/frontend/index.d.ts.map +1 -0
  190. package/dist/checks/quality/frontend/index.js +4 -0
  191. package/dist/checks/quality/frontend/index.js.map +1 -0
  192. package/dist/checks/quality/frontend/test-only-frontend-modules.d.ts +13 -0
  193. package/dist/checks/quality/frontend/test-only-frontend-modules.d.ts.map +1 -0
  194. package/dist/checks/quality/frontend/test-only-frontend-modules.js +159 -0
  195. package/dist/checks/quality/frontend/test-only-frontend-modules.js.map +1 -0
  196. package/dist/checks/quality/incomplete-regex-escaping.d.ts +13 -0
  197. package/dist/checks/quality/incomplete-regex-escaping.d.ts.map +1 -0
  198. package/dist/checks/quality/incomplete-regex-escaping.js +207 -0
  199. package/dist/checks/quality/incomplete-regex-escaping.js.map +1 -0
  200. package/dist/checks/quality/index.d.ts +11 -0
  201. package/dist/checks/quality/index.d.ts.map +1 -0
  202. package/dist/checks/quality/index.js +11 -0
  203. package/dist/checks/quality/index.js.map +1 -0
  204. package/dist/checks/quality/linting/index.d.ts +2 -0
  205. package/dist/checks/quality/linting/index.d.ts.map +1 -0
  206. package/dist/checks/quality/linting/index.js +2 -0
  207. package/dist/checks/quality/linting/index.js.map +1 -0
  208. package/dist/checks/quality/linting/typescript-frontend.d.ts +25 -0
  209. package/dist/checks/quality/linting/typescript-frontend.d.ts.map +1 -0
  210. package/dist/checks/quality/linting/typescript-frontend.js +159 -0
  211. package/dist/checks/quality/linting/typescript-frontend.js.map +1 -0
  212. package/dist/checks/quality/observability/index.d.ts +5 -0
  213. package/dist/checks/quality/observability/index.d.ts.map +1 -0
  214. package/dist/checks/quality/observability/index.js +5 -0
  215. package/dist/checks/quality/observability/index.js.map +1 -0
  216. package/dist/checks/quality/observability/logger-event-name-format.d.ts +12 -0
  217. package/dist/checks/quality/observability/logger-event-name-format.d.ts.map +1 -0
  218. package/dist/checks/quality/observability/logger-event-name-format.js +124 -0
  219. package/dist/checks/quality/observability/logger-event-name-format.js.map +1 -0
  220. package/dist/checks/quality/observability/no-hardcoded-correlation-id.d.ts +5 -0
  221. package/dist/checks/quality/observability/no-hardcoded-correlation-id.d.ts.map +1 -0
  222. package/dist/checks/quality/observability/no-hardcoded-correlation-id.js +77 -0
  223. package/dist/checks/quality/observability/no-hardcoded-correlation-id.js.map +1 -0
  224. package/dist/checks/quality/observability/observability-coverage/__tests__/analyzer.test.d.ts +11 -0
  225. package/dist/checks/quality/observability/observability-coverage/__tests__/analyzer.test.d.ts.map +1 -0
  226. package/dist/checks/quality/observability/observability-coverage/__tests__/analyzer.test.js +107 -0
  227. package/dist/checks/quality/observability/observability-coverage/__tests__/analyzer.test.js.map +1 -0
  228. package/dist/checks/quality/observability/observability-coverage/__tests__/logger-detector.test.d.ts +12 -0
  229. package/dist/checks/quality/observability/observability-coverage/__tests__/logger-detector.test.d.ts.map +1 -0
  230. package/dist/checks/quality/observability/observability-coverage/__tests__/logger-detector.test.js +94 -0
  231. package/dist/checks/quality/observability/observability-coverage/__tests__/logger-detector.test.js.map +1 -0
  232. package/dist/checks/quality/observability/observability-coverage/analyzer.d.ts +13 -0
  233. package/dist/checks/quality/observability/observability-coverage/analyzer.d.ts.map +1 -0
  234. package/dist/checks/quality/observability/observability-coverage/analyzer.js +117 -0
  235. package/dist/checks/quality/observability/observability-coverage/analyzer.js.map +1 -0
  236. package/dist/checks/quality/observability/observability-coverage/index.d.ts +4 -0
  237. package/dist/checks/quality/observability/observability-coverage/index.d.ts.map +1 -0
  238. package/dist/checks/quality/observability/observability-coverage/index.js +4 -0
  239. package/dist/checks/quality/observability/observability-coverage/index.js.map +1 -0
  240. package/dist/checks/quality/observability/observability-coverage/logger-detector.d.ts +29 -0
  241. package/dist/checks/quality/observability/observability-coverage/logger-detector.d.ts.map +1 -0
  242. package/dist/checks/quality/observability/observability-coverage/logger-detector.js +111 -0
  243. package/dist/checks/quality/observability/observability-coverage/logger-detector.js.map +1 -0
  244. package/dist/checks/quality/observability/observability-coverage/types.d.ts +64 -0
  245. package/dist/checks/quality/observability/observability-coverage/types.d.ts.map +1 -0
  246. package/dist/checks/quality/observability/observability-coverage/types.js +6 -0
  247. package/dist/checks/quality/observability/observability-coverage/types.js.map +1 -0
  248. package/dist/checks/quality/observability/pii-exposure-in-logs.d.ts +22 -0
  249. package/dist/checks/quality/observability/pii-exposure-in-logs.d.ts.map +1 -0
  250. package/dist/checks/quality/observability/pii-exposure-in-logs.js +212 -0
  251. package/dist/checks/quality/observability/pii-exposure-in-logs.js.map +1 -0
  252. package/dist/checks/quality/observability/pii-exposure-in-logs.test.d.ts +11 -0
  253. package/dist/checks/quality/observability/pii-exposure-in-logs.test.d.ts.map +1 -0
  254. package/dist/checks/quality/observability/pii-exposure-in-logs.test.js +46 -0
  255. package/dist/checks/quality/observability/pii-exposure-in-logs.test.js.map +1 -0
  256. package/dist/checks/quality/patterns/__tests__/toctou-fp.test.d.ts +14 -0
  257. package/dist/checks/quality/patterns/__tests__/toctou-fp.test.d.ts.map +1 -0
  258. package/dist/checks/quality/patterns/__tests__/toctou-fp.test.js +61 -0
  259. package/dist/checks/quality/patterns/__tests__/toctou-fp.test.js.map +1 -0
  260. package/dist/checks/quality/patterns/async-waterfall-detection.d.ts +26 -0
  261. package/dist/checks/quality/patterns/async-waterfall-detection.d.ts.map +1 -0
  262. package/dist/checks/quality/patterns/async-waterfall-detection.js +410 -0
  263. package/dist/checks/quality/patterns/async-waterfall-detection.js.map +1 -0
  264. package/dist/checks/quality/patterns/dispose-pattern-completeness.d.ts +13 -0
  265. package/dist/checks/quality/patterns/dispose-pattern-completeness.d.ts.map +1 -0
  266. package/dist/checks/quality/patterns/dispose-pattern-completeness.js +220 -0
  267. package/dist/checks/quality/patterns/dispose-pattern-completeness.js.map +1 -0
  268. package/dist/checks/quality/patterns/error-handling-quality.d.ts +17 -0
  269. package/dist/checks/quality/patterns/error-handling-quality.d.ts.map +1 -0
  270. package/dist/checks/quality/patterns/error-handling-quality.js +335 -0
  271. package/dist/checks/quality/patterns/error-handling-quality.js.map +1 -0
  272. package/dist/checks/quality/patterns/index.d.ts +10 -0
  273. package/dist/checks/quality/patterns/index.d.ts.map +1 -0
  274. package/dist/checks/quality/patterns/index.js +10 -0
  275. package/dist/checks/quality/patterns/index.js.map +1 -0
  276. package/dist/checks/quality/patterns/lifecycle-cleanup-enforcement.d.ts +16 -0
  277. package/dist/checks/quality/patterns/lifecycle-cleanup-enforcement.d.ts.map +1 -0
  278. package/dist/checks/quality/patterns/lifecycle-cleanup-enforcement.js +205 -0
  279. package/dist/checks/quality/patterns/lifecycle-cleanup-enforcement.js.map +1 -0
  280. package/dist/checks/quality/patterns/result-pattern-consistency.d.ts +16 -0
  281. package/dist/checks/quality/patterns/result-pattern-consistency.d.ts.map +1 -0
  282. package/dist/checks/quality/patterns/result-pattern-consistency.js +328 -0
  283. package/dist/checks/quality/patterns/result-pattern-consistency.js.map +1 -0
  284. package/dist/checks/quality/patterns/silent-early-returns.d.ts +23 -0
  285. package/dist/checks/quality/patterns/silent-early-returns.d.ts.map +1 -0
  286. package/dist/checks/quality/patterns/silent-early-returns.js +266 -0
  287. package/dist/checks/quality/patterns/silent-early-returns.js.map +1 -0
  288. package/dist/checks/quality/patterns/stream-buffer-size-limits.d.ts +13 -0
  289. package/dist/checks/quality/patterns/stream-buffer-size-limits.d.ts.map +1 -0
  290. package/dist/checks/quality/patterns/stream-buffer-size-limits.js +163 -0
  291. package/dist/checks/quality/patterns/stream-buffer-size-limits.js.map +1 -0
  292. package/dist/checks/quality/patterns/throws-documentation.d.ts +23 -0
  293. package/dist/checks/quality/patterns/throws-documentation.d.ts.map +1 -0
  294. package/dist/checks/quality/patterns/throws-documentation.js +519 -0
  295. package/dist/checks/quality/patterns/throws-documentation.js.map +1 -0
  296. package/dist/checks/quality/patterns/toctou-race-condition.d.ts +48 -0
  297. package/dist/checks/quality/patterns/toctou-race-condition.d.ts.map +1 -0
  298. package/dist/checks/quality/patterns/toctou-race-condition.js +639 -0
  299. package/dist/checks/quality/patterns/toctou-race-condition.js.map +1 -0
  300. package/dist/checks/quality/stubbed-implementation-detection.d.ts +24 -0
  301. package/dist/checks/quality/stubbed-implementation-detection.d.ts.map +1 -0
  302. package/dist/checks/quality/stubbed-implementation-detection.js +355 -0
  303. package/dist/checks/quality/stubbed-implementation-detection.js.map +1 -0
  304. package/dist/checks/quality/unused-config-options.d.ts +12 -0
  305. package/dist/checks/quality/unused-config-options.d.ts.map +1 -0
  306. package/dist/checks/quality/unused-config-options.js +245 -0
  307. package/dist/checks/quality/unused-config-options.js.map +1 -0
  308. package/dist/checks/resilience/__tests__/callback-invocation-safe.test.d.ts +2 -0
  309. package/dist/checks/resilience/__tests__/callback-invocation-safe.test.d.ts.map +1 -0
  310. package/dist/checks/resilience/__tests__/callback-invocation-safe.test.js +79 -0
  311. package/dist/checks/resilience/__tests__/callback-invocation-safe.test.js.map +1 -0
  312. package/dist/checks/resilience/__tests__/context-leakage-fp.test.d.ts +12 -0
  313. package/dist/checks/resilience/__tests__/context-leakage-fp.test.d.ts.map +1 -0
  314. package/dist/checks/resilience/__tests__/context-leakage-fp.test.js +34 -0
  315. package/dist/checks/resilience/__tests__/context-leakage-fp.test.js.map +1 -0
  316. package/dist/checks/resilience/__tests__/context-mutation.test.d.ts +11 -0
  317. package/dist/checks/resilience/__tests__/context-mutation.test.d.ts.map +1 -0
  318. package/dist/checks/resilience/__tests__/context-mutation.test.js +54 -0
  319. package/dist/checks/resilience/__tests__/context-mutation.test.js.map +1 -0
  320. package/dist/checks/resilience/callback-invocation-safe.d.ts +34 -0
  321. package/dist/checks/resilience/callback-invocation-safe.d.ts.map +1 -0
  322. package/dist/checks/resilience/callback-invocation-safe.js +247 -0
  323. package/dist/checks/resilience/callback-invocation-safe.js.map +1 -0
  324. package/dist/checks/resilience/context-leakage.d.ts +25 -0
  325. package/dist/checks/resilience/context-leakage.d.ts.map +1 -0
  326. package/dist/checks/resilience/context-leakage.js +435 -0
  327. package/dist/checks/resilience/context-leakage.js.map +1 -0
  328. package/dist/checks/resilience/context-mutation.d.ts +21 -0
  329. package/dist/checks/resilience/context-mutation.d.ts.map +1 -0
  330. package/dist/checks/resilience/context-mutation.js +368 -0
  331. package/dist/checks/resilience/context-mutation.js.map +1 -0
  332. package/dist/checks/resilience/detached-promises.d.ts +40 -0
  333. package/dist/checks/resilience/detached-promises.d.ts.map +1 -0
  334. package/dist/checks/resilience/detached-promises.js +646 -0
  335. package/dist/checks/resilience/detached-promises.js.map +1 -0
  336. package/dist/checks/resilience/index.d.ts +7 -0
  337. package/dist/checks/resilience/index.d.ts.map +1 -0
  338. package/dist/checks/resilience/index.js +7 -0
  339. package/dist/checks/resilience/index.js.map +1 -0
  340. package/dist/checks/resilience/no-raw-fetch.d.ts +11 -0
  341. package/dist/checks/resilience/no-raw-fetch.d.ts.map +1 -0
  342. package/dist/checks/resilience/no-raw-fetch.js +110 -0
  343. package/dist/checks/resilience/no-raw-fetch.js.map +1 -0
  344. package/dist/checks/resilience/no-unbounded-concurrency.d.ts +11 -0
  345. package/dist/checks/resilience/no-unbounded-concurrency.d.ts.map +1 -0
  346. package/dist/checks/resilience/no-unbounded-concurrency.js +117 -0
  347. package/dist/checks/resilience/no-unbounded-concurrency.js.map +1 -0
  348. package/dist/checks/security/__tests__/sql-injection.test.d.ts +17 -0
  349. package/dist/checks/security/__tests__/sql-injection.test.d.ts.map +1 -0
  350. package/dist/checks/security/__tests__/sql-injection.test.js +97 -0
  351. package/dist/checks/security/__tests__/sql-injection.test.js.map +1 -0
  352. package/dist/checks/security/index.d.ts +4 -0
  353. package/dist/checks/security/index.d.ts.map +1 -0
  354. package/dist/checks/security/index.js +4 -0
  355. package/dist/checks/security/index.js.map +1 -0
  356. package/dist/checks/security/input-sanitization.d.ts +20 -0
  357. package/dist/checks/security/input-sanitization.d.ts.map +1 -0
  358. package/dist/checks/security/input-sanitization.js +255 -0
  359. package/dist/checks/security/input-sanitization.js.map +1 -0
  360. package/dist/checks/security/sql-injection.d.ts +24 -0
  361. package/dist/checks/security/sql-injection.d.ts.map +1 -0
  362. package/dist/checks/security/sql-injection.js +330 -0
  363. package/dist/checks/security/sql-injection.js.map +1 -0
  364. package/dist/checks/security/unsafe-secret-comparison.d.ts +17 -0
  365. package/dist/checks/security/unsafe-secret-comparison.d.ts.map +1 -0
  366. package/dist/checks/security/unsafe-secret-comparison.js +227 -0
  367. package/dist/checks/security/unsafe-secret-comparison.js.map +1 -0
  368. package/dist/checks/testing/index.d.ts +2 -0
  369. package/dist/checks/testing/index.d.ts.map +1 -0
  370. package/dist/checks/testing/index.js +2 -0
  371. package/dist/checks/testing/index.js.map +1 -0
  372. package/dist/checks/testing/mock-implementations-in-production.d.ts +12 -0
  373. package/dist/checks/testing/mock-implementations-in-production.d.ts.map +1 -0
  374. package/dist/checks/testing/mock-implementations-in-production.js +211 -0
  375. package/dist/checks/testing/mock-implementations-in-production.js.map +1 -0
  376. package/dist/display/architecture.d.ts +9 -0
  377. package/dist/display/architecture.d.ts.map +1 -0
  378. package/dist/display/architecture.js +18 -0
  379. package/dist/display/architecture.js.map +1 -0
  380. package/dist/display/index.d.ts +20 -0
  381. package/dist/display/index.d.ts.map +1 -0
  382. package/dist/display/index.js +30 -0
  383. package/dist/display/index.js.map +1 -0
  384. package/dist/display/quality.d.ts +7 -0
  385. package/dist/display/quality.d.ts.map +1 -0
  386. package/dist/display/quality.js +39 -0
  387. package/dist/display/quality.js.map +1 -0
  388. package/dist/display/resilience.d.ts +7 -0
  389. package/dist/display/resilience.d.ts.map +1 -0
  390. package/dist/display/resilience.js +13 -0
  391. package/dist/display/resilience.js.map +1 -0
  392. package/dist/display/security-testing.d.ts +9 -0
  393. package/dist/display/security-testing.d.ts.map +1 -0
  394. package/dist/display/security-testing.js +14 -0
  395. package/dist/display/security-testing.js.map +1 -0
  396. package/dist/display/types.d.ts +6 -0
  397. package/dist/display/types.d.ts.map +1 -0
  398. package/dist/display/types.js +6 -0
  399. package/dist/display/types.js.map +1 -0
  400. package/dist/index.d.ts +19 -0
  401. package/dist/index.d.ts.map +1 -0
  402. package/dist/index.js +21 -0
  403. package/dist/index.js.map +1 -0
  404. package/package.json +55 -0
@@ -0,0 +1,24 @@
1
+ /**
2
+ * @fileoverview Stubbed Implementation Detection Check
3
+ *
4
+ * Detects patterns indicating incomplete or placeholder implementations:
5
+ * - Empty object stubs: `({}) as Type`
6
+ * - Promise.resolve() placeholders
7
+ * - Hardcoded stub returns
8
+ * - Placeholder comments
9
+ *
10
+ * False-positive reduction: the check walks the AST for context to skip:
11
+ * - Promise.resolve() in lifecycle methods (destroy/dispose/close/shutdown/cleanup)
12
+ * - Promise.resolve() inside conditional blocks (guard clauses)
13
+ * - Promise.resolve() in functions with substantive statements
14
+ * - { success: true, data: [] } inside conditional branches or functions with multiple returns
15
+ * - ({}) as T where T is a generic type parameter
16
+ * - ({}) as T used as Proxy target
17
+ */
18
+ /**
19
+ * Check: quality/stubbed-implementation-detection
20
+ *
21
+ * Detects incomplete or placeholder implementations.
22
+ */
23
+ export declare const stubbedImplementationDetection: import("@opensip-cli/fitness").Check;
24
+ //# sourceMappingURL=stubbed-implementation-detection.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stubbed-implementation-detection.d.ts","sourceRoot":"","sources":["../../../src/checks/quality/stubbed-implementation-detection.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;GAgBG;AAgUH;;;;GAIG;AACH,eAAO,MAAM,8BAA8B,sCA8EzC,CAAC"}
@@ -0,0 +1,355 @@
1
+ // @fitness-ignore-file unused-config-options -- Config options reserved for future use or environment-specific
2
+ // @fitness-ignore-file stubbed-implementation-detection -- longDescription documents the patterns this check detects, triggering self-detection
3
+ /**
4
+ * @fileoverview Stubbed Implementation Detection Check
5
+ *
6
+ * Detects patterns indicating incomplete or placeholder implementations:
7
+ * - Empty object stubs: `({}) as Type`
8
+ * - Promise.resolve() placeholders
9
+ * - Hardcoded stub returns
10
+ * - Placeholder comments
11
+ *
12
+ * False-positive reduction: the check walks the AST for context to skip:
13
+ * - Promise.resolve() in lifecycle methods (destroy/dispose/close/shutdown/cleanup)
14
+ * - Promise.resolve() inside conditional blocks (guard clauses)
15
+ * - Promise.resolve() in functions with substantive statements
16
+ * - { success: true, data: [] } inside conditional branches or functions with multiple returns
17
+ * - ({}) as T where T is a generic type parameter
18
+ * - ({}) as T used as Proxy target
19
+ */
20
+ import { defineCheck, isTestFile } from '@opensip-cli/fitness';
21
+ import { findEnclosingFunctionBody, getEnclosingFunctionName, getSharedSourceFile, isInsideConditionalBlock, } from '@opensip-cli/lang-typescript';
22
+ import * as ts from 'typescript';
23
+ /** Placeholder comment patterns - using explicit RegExp constructors for safety */
24
+ const PLACEHOLDER_PATTERNS = [
25
+ new RegExp(String.raw `\/\/\s*Placeholder\s*(implementation|for|:|-)`, 'i'),
26
+ new RegExp(String.raw `\/\/\s*STUB\s*[:|-]`, 'i'),
27
+ new RegExp(String.raw `\/\/\s*Not\s+implemented`, 'i'),
28
+ ];
29
+ /** Primitive types that should be skipped when checking empty object stubs */
30
+ const PRIMITIVE_TYPES = new Set([
31
+ 'string',
32
+ 'number',
33
+ 'boolean',
34
+ 'null',
35
+ 'undefined',
36
+ 'void',
37
+ 'never',
38
+ 'unknown',
39
+ ]);
40
+ /** Pattern for Promise.resolve stubs - matches exact form without backtracking */
41
+ const PROMISE_RESOLVE_PATTERN = new RegExp(String.raw `^Promise\.resolve\((undefined|null|void 0)?\)$`);
42
+ /** Pattern for hardcoded stub returns with success: true */
43
+ const STUB_RETURN_PATTERN = new RegExp(String.raw `success:\s*true[\s\S]*data:\s*(\[\]|null|\{\})`, 'i');
44
+ /** Lifecycle teardown method names that commonly return Promise.resolve() */
45
+ const LIFECYCLE_METHOD_NAMES = new Set(['destroy', 'dispose', 'close', 'shutdown', 'cleanup']);
46
+ // =============================================================================
47
+ // AST HELPER UTILITIES
48
+ // =============================================================================
49
+ // Function-scope helpers (findEnclosingFunctionBody, getEnclosingFunctionName,
50
+ // isInsideConditionalBlock) are imported from @opensip-cli/lang-typescript.
51
+ /**
52
+ * Check whether a function body contains substantive statements beyond a single return.
53
+ * "Substantive" means assignments, method calls, logging, variable declarations with initializers, etc.
54
+ */
55
+ function functionBodyHasSubstantiveStatements(body, returnNode) {
56
+ for (const stmt of body.statements) {
57
+ // Skip the return statement itself
58
+ if (stmt === returnNode)
59
+ continue;
60
+ // Skip variable declarations without initializers (just type annotations)
61
+ if (ts.isVariableStatement(stmt)) {
62
+ const hasInitializer = stmt.declarationList.declarations.some((d) => d.initializer !== undefined);
63
+ if (hasInitializer)
64
+ return true;
65
+ continue;
66
+ }
67
+ // Any other statement (expression statement, if, for, etc.) is substantive
68
+ return true;
69
+ }
70
+ return false;
71
+ }
72
+ /**
73
+ * Recursively check if a node contains an await or call expression before a given position.
74
+ */
75
+ function containsAwaitOrCallBefore(node, returnPos) {
76
+ if (node.getStart() >= returnPos)
77
+ return false;
78
+ if (ts.isAwaitExpression(node))
79
+ return true;
80
+ if (ts.isCallExpression(node) && node.getStart() < returnPos)
81
+ return true;
82
+ let found = false;
83
+ ts.forEachChild(node, (child) => {
84
+ if (!found && containsAwaitOrCallBefore(child, returnPos)) {
85
+ found = true;
86
+ }
87
+ });
88
+ return found;
89
+ }
90
+ function functionBodyHasAwaitOrCallsBefore(body, returnNode) {
91
+ const returnPos = returnNode.getStart();
92
+ for (const stmt of body.statements) {
93
+ if (stmt === returnNode)
94
+ break;
95
+ if (containsAwaitOrCallBefore(stmt, returnPos))
96
+ return true;
97
+ }
98
+ return false;
99
+ }
100
+ /**
101
+ * Check whether the function has multiple return statements (indicating branches, not a stub).
102
+ */
103
+ function functionHasMultipleReturns(body) {
104
+ let returnCount = 0;
105
+ const visit = (node) => {
106
+ if (ts.isReturnStatement(node)) {
107
+ returnCount++;
108
+ }
109
+ // Do not descend into nested functions
110
+ if (ts.isFunctionDeclaration(node) ||
111
+ ts.isFunctionExpression(node) ||
112
+ ts.isArrowFunction(node) ||
113
+ ts.isMethodDeclaration(node)) {
114
+ return;
115
+ }
116
+ ts.forEachChild(node, visit);
117
+ };
118
+ for (const stmt of body.statements) {
119
+ visit(stmt);
120
+ }
121
+ return returnCount > 1;
122
+ }
123
+ /**
124
+ * Check whether a node's type parameters include the given type name.
125
+ */
126
+ function nodeHasTypeParameter(node, typeText, sourceFile) {
127
+ if (!node.typeParameters)
128
+ return false;
129
+ return node.typeParameters.some((tp) => tp.name.getText(sourceFile) === typeText);
130
+ }
131
+ /**
132
+ * Check whether the type in an as-expression refers to a generic type parameter
133
+ * rather than a concrete type. Walks up the AST to find enclosing function/class
134
+ * type parameters and checks if the cast target matches one.
135
+ */
136
+ function isGenericTypeParameter(typeText, node, sourceFile) {
137
+ let current = node.parent;
138
+ while (!ts.isSourceFile(current)) {
139
+ // Check function-like or class declarations for type parameters
140
+ if ((ts.isFunctionDeclaration(current) ||
141
+ ts.isMethodDeclaration(current) ||
142
+ ts.isFunctionExpression(current) ||
143
+ ts.isArrowFunction(current) ||
144
+ ts.isClassDeclaration(current)) &&
145
+ nodeHasTypeParameter(current, typeText, sourceFile)) {
146
+ return true;
147
+ }
148
+ current = current.parent;
149
+ }
150
+ return false;
151
+ }
152
+ /**
153
+ * Check whether the as-expression is the target argument of a `new Proxy(...)` call.
154
+ */
155
+ function isProxyTarget(node, sourceFile) {
156
+ const parent = node.parent;
157
+ // Direct parent should be a NewExpression: new Proxy({} as T, handler)
158
+ if (ts.isNewExpression(parent)) {
159
+ const exprText = parent.expression.getText(sourceFile);
160
+ if (exprText === 'Proxy' && parent.arguments?.[0] === node) {
161
+ return true;
162
+ }
163
+ }
164
+ // Or it could be wrapped in parentheses: new Proxy(({} as T), handler)
165
+ if (ts.isParenthesizedExpression(parent)) {
166
+ return isProxyTarget(parent, sourceFile);
167
+ }
168
+ return false;
169
+ }
170
+ // =============================================================================
171
+ // CHECK FUNCTIONS
172
+ // =============================================================================
173
+ function checkEmptyObjectStub(options) {
174
+ const { node, sourceFile } = options;
175
+ if (!ts.isAsExpression(node) && !ts.isTypeAssertionExpression(node))
176
+ return null;
177
+ const expression = node.expression;
178
+ if (!ts.isObjectLiteralExpression(expression) || expression.properties.length > 0)
179
+ return null;
180
+ const typeText = node.type.getText(sourceFile);
181
+ // Skip primitives and Record types
182
+ const isPrimitive = PRIMITIVE_TYPES.has(typeText);
183
+ const isRecordType = typeText.startsWith('Record<') && typeText.endsWith('>');
184
+ if (isPrimitive || isRecordType)
185
+ return null;
186
+ // Skip if type is a generic type parameter (e.g., T in deepMerge<T>)
187
+ if (isGenericTypeParameter(typeText, node, sourceFile))
188
+ return null;
189
+ // Skip if this is the target of a new Proxy(...) call
190
+ if (isProxyTarget(node, sourceFile))
191
+ return null;
192
+ const { line, character } = sourceFile.getLineAndCharacterOfPosition(node.getStart());
193
+ const lineNum = line + 1;
194
+ const matchText = node.getText(sourceFile);
195
+ return {
196
+ line: lineNum,
197
+ column: character + 1,
198
+ message: `Empty object stub: ({}) as ${typeText} - will crash at runtime`,
199
+ severity: 'error',
200
+ suggestion: `Implement the actual ${typeText} object with all required properties, or use a factory function/builder to create valid instances`,
201
+ match: matchText,
202
+ };
203
+ }
204
+ function checkPromiseResolveStub(options) {
205
+ const { node, sourceFile } = options;
206
+ if (!ts.isReturnStatement(node) || !node.expression || !ts.isCallExpression(node.expression))
207
+ return null;
208
+ const callText = node.expression.getText(sourceFile);
209
+ if (!PROMISE_RESOLVE_PATTERN.test(callText))
210
+ return null;
211
+ // Skip if inside a conditional block (guard clause / early return)
212
+ if (isInsideConditionalBlock(node))
213
+ return null;
214
+ // Skip if enclosing function is a lifecycle teardown method
215
+ const funcName = getEnclosingFunctionName(node, sourceFile);
216
+ if (funcName && LIFECYCLE_METHOD_NAMES.has(funcName))
217
+ return null;
218
+ // Skip if the function body has substantive statements (real work + async wrapping)
219
+ const body = findEnclosingFunctionBody(node);
220
+ if (body && functionBodyHasSubstantiveStatements(body, node))
221
+ return null;
222
+ const { line, character } = sourceFile.getLineAndCharacterOfPosition(node.getStart());
223
+ return {
224
+ line: line + 1,
225
+ column: character + 1,
226
+ message: 'Placeholder return: Promise.resolve() - method does nothing',
227
+ severity: 'error',
228
+ suggestion: 'Implement the actual async logic for this method, or if this is intentional no-op, add a comment explaining why',
229
+ match: callText,
230
+ };
231
+ }
232
+ function checkHardcodedStubReturn(options) {
233
+ const { node, sourceFile } = options;
234
+ if (!ts.isReturnStatement(node) ||
235
+ !node.expression ||
236
+ !ts.isObjectLiteralExpression(node.expression))
237
+ return null;
238
+ const returnText = node.expression.getText(sourceFile);
239
+ if (!STUB_RETURN_PATTERN.test(returnText))
240
+ return null;
241
+ // Skip if inside a conditional block (branch return, not the only path)
242
+ if (isInsideConditionalBlock(node))
243
+ return null;
244
+ // Skip if the function has multiple return statements (indicates branching logic)
245
+ const body = findEnclosingFunctionBody(node);
246
+ if (body && functionHasMultipleReturns(body))
247
+ return null;
248
+ // Skip if the function body contains await expressions or calls before this return
249
+ if (body && functionBodyHasAwaitOrCallsBefore(body, node))
250
+ return null;
251
+ const { line, character } = sourceFile.getLineAndCharacterOfPosition(node.getStart());
252
+ return {
253
+ line: line + 1,
254
+ column: character + 1,
255
+ message: 'Hardcoded stub return: { success: true, data: [] }',
256
+ severity: 'warning',
257
+ suggestion: 'Replace this stub with actual implementation that fetches/processes real data',
258
+ match: returnText.slice(0, 80),
259
+ };
260
+ }
261
+ function checkLineForPlaceholder(line, lineNum) {
262
+ for (const pattern of PLACEHOLDER_PATTERNS) {
263
+ if (pattern.test(line)) {
264
+ return {
265
+ line: lineNum,
266
+ column: 0,
267
+ message: 'Placeholder comment indicates unfinished implementation',
268
+ severity: 'warning',
269
+ suggestion: 'Complete the implementation or create a ticket to track this work, then remove the placeholder comment',
270
+ match: line.trim(),
271
+ };
272
+ }
273
+ }
274
+ return null;
275
+ }
276
+ /**
277
+ * Check: quality/stubbed-implementation-detection
278
+ *
279
+ * Detects incomplete or placeholder implementations.
280
+ */
281
+ export const stubbedImplementationDetection = defineCheck({
282
+ id: '12218d58-5dea-4aba-ba7b-fc1822d03ec4',
283
+ slug: 'stubbed-implementation-detection',
284
+ scope: { languages: ['typescript'], concerns: ['backend', 'frontend', 'cli'] },
285
+ contentFilter: 'raw',
286
+ confidence: 'high',
287
+ description: 'Detects incomplete/placeholder implementations',
288
+ longDescription: `**Purpose:** Detects incomplete or placeholder implementations that will fail at runtime or silently do nothing.
289
+
290
+ **Detects:**
291
+ - Empty object stubs: \`({}) as Type\` where Type is not a primitive or Record (will crash at runtime)
292
+ - Placeholder returns: \`return Promise.resolve(undefined|null|void 0)\` indicating a no-op async method
293
+ - Hardcoded stub returns: \`return { success: true, data: []|null|{} }\` patterns
294
+ - Placeholder comments: \`// Placeholder implementation\`, \`// STUB:\`, \`// Not implemented\`
295
+
296
+ **Skips (not false positives):**
297
+ - Test files (\`*.test.ts\`, files under \`__tests__/\`, \`__fixtures__/\`) — stub patterns in tests are intentional
298
+ - Promise.resolve() in lifecycle methods (destroy, dispose, close, shutdown, cleanup)
299
+ - Promise.resolve() inside conditional blocks (guard clauses)
300
+ - Promise.resolve() in functions with substantive statements (real synchronous work)
301
+ - Hardcoded stub returns inside conditional branches or functions with multiple returns
302
+ - Hardcoded stub returns in functions with await/call expressions before the return
303
+ - \`({}) as T\` where T is a generic type parameter
304
+ - \`({}) as T\` used as a Proxy target
305
+
306
+ **Why it matters:** Stubbed implementations pass type checks but fail at runtime. Detecting them early prevents production crashes and silent data loss.
307
+
308
+ **Scope:** General best practice. Analyzes each file individually (\`analyze\`). Uses TypeScript AST parsing on production files (excludes tests and fixtures).`,
309
+ tags: ['quality', 'code-quality', 'best-practices'],
310
+ fileTypes: ['ts', 'tsx'],
311
+ analyze(content, filePath) {
312
+ const violations = [];
313
+ // Test files routinely use stub patterns (empty type-asserted objects,
314
+ // Promise.resolve()) as intentional fixtures or compile-time drift
315
+ // detectors. Skip AST stub detection in tests; placeholder-comment
316
+ // scanning below is also already test-aware.
317
+ const inTestFile = isTestFile(filePath);
318
+ try {
319
+ const sourceFile = getSharedSourceFile(filePath, content);
320
+ if (!sourceFile)
321
+ return [];
322
+ const visit = (node) => {
323
+ const nodeOptions = { node, sourceFile };
324
+ if (!inTestFile) {
325
+ const emptyStub = checkEmptyObjectStub(nodeOptions);
326
+ if (emptyStub)
327
+ violations.push(emptyStub);
328
+ const promiseStub = checkPromiseResolveStub(nodeOptions);
329
+ if (promiseStub)
330
+ violations.push(promiseStub);
331
+ const hardcodedStub = checkHardcodedStubReturn(nodeOptions);
332
+ if (hardcodedStub)
333
+ violations.push(hardcodedStub);
334
+ }
335
+ ts.forEachChild(node, visit);
336
+ };
337
+ visit(sourceFile);
338
+ // Check for placeholder comments (skip test files — placeholder comments
339
+ // in tests are intentional)
340
+ if (!isTestFile(filePath)) {
341
+ const lines = content.split('\n');
342
+ for (const [i, line] of lines.entries()) {
343
+ const placeholder = checkLineForPlaceholder(line ?? '', i + 1);
344
+ if (placeholder)
345
+ violations.push(placeholder);
346
+ }
347
+ }
348
+ }
349
+ catch {
350
+ // @swallow-ok Skip files that fail to parse
351
+ }
352
+ return violations;
353
+ },
354
+ });
355
+ //# sourceMappingURL=stubbed-implementation-detection.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stubbed-implementation-detection.js","sourceRoot":"","sources":["../../../src/checks/quality/stubbed-implementation-detection.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ /**
2
+ * @fileoverview Unused Configuration Options Check
3
+ *
4
+ * Detects configuration properties that are defined but never accessed.
5
+ */
6
+ /**
7
+ * Check: quality/unused-config-options
8
+ *
9
+ * Detects configuration properties defined but never accessed.
10
+ */
11
+ export declare const unusedConfigOptions: import("@opensip-cli/fitness").Check;
12
+ //# sourceMappingURL=unused-config-options.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"unused-config-options.d.ts","sourceRoot":"","sources":["../../../src/checks/quality/unused-config-options.ts"],"names":[],"mappings":"AAEA;;;;GAIG;AA0PH;;;;GAIG;AACH,eAAO,MAAM,mBAAmB,sCA2B9B,CAAC"}
@@ -0,0 +1,245 @@
1
+ // @fitness-ignore-file toctou-race-condition -- TOCTOU acceptable in this non-concurrent context
2
+ // @fitness-ignore-file unused-config-options -- Config options reserved for future use or environment-specific
3
+ /**
4
+ * @fileoverview Unused Configuration Options Check
5
+ *
6
+ * Detects configuration properties that are defined but never accessed.
7
+ */
8
+ import { logger } from '@opensip-cli/core';
9
+ import { defineCheck } from '@opensip-cli/fitness';
10
+ import { getSharedSourceFile } from '@opensip-cli/lang-typescript';
11
+ import * as ts from 'typescript';
12
+ /**
13
+ * Common property names that are ubiquitous and would cause false positives
14
+ */
15
+ const COMMON_PROPERTY_NAMES = new Set([
16
+ // Very common config properties used everywhere
17
+ 'enabled',
18
+ 'disabled',
19
+ 'timeout',
20
+ 'retries',
21
+ 'debug',
22
+ 'verbose',
23
+ 'name',
24
+ 'type',
25
+ 'id',
26
+ 'key',
27
+ 'value',
28
+ 'data',
29
+ 'options',
30
+ 'config',
31
+ 'settings',
32
+ 'port',
33
+ 'host',
34
+ 'url',
35
+ 'path',
36
+ 'level',
37
+ 'mode',
38
+ ]);
39
+ /**
40
+ * Paths where this check should not run (CLI, scripts, test utilities)
41
+ */
42
+ const NON_CONFIG_CONSUMER_PATTERNS = [
43
+ /\/cli\//,
44
+ /\/scripts\//,
45
+ /\/bin\//,
46
+ /__tests__\//,
47
+ /\.test\./,
48
+ /\.spec\./,
49
+ /\/testing\//,
50
+ // Type definition files only
51
+ /types\.ts$/,
52
+ /interfaces\.ts$/,
53
+ /index\.d\.ts$/,
54
+ ];
55
+ /**
56
+ * Check if a path should be excluded from analysis
57
+ */
58
+ function shouldExcludePath(filePath) {
59
+ return NON_CONFIG_CONSUMER_PATTERNS.some((pattern) => pattern.test(filePath));
60
+ }
61
+ /**
62
+ * Check if interface is a Config/Options interface.
63
+ */
64
+ function isConfigInterface(interfaceName) {
65
+ /* v8 ignore next -- defensive AST/type guard */
66
+ return interfaceName.includes('Config') || interfaceName.includes('Options');
67
+ }
68
+ /**
69
+ * Extract property from interface member.
70
+ */
71
+ function extractPropertyFromMember(member, sourceFile, interfaceName, filePath) {
72
+ /* v8 ignore next -- defensive AST/type guard */
73
+ if (!ts.isPropertySignature(member))
74
+ return null;
75
+ /* v8 ignore next -- defensive AST/type guard */
76
+ if (!ts.isIdentifier(member.name))
77
+ return null;
78
+ const propName = member.name.text;
79
+ // Skip common property names that would cause many false positives
80
+ if (COMMON_PROPERTY_NAMES.has(propName))
81
+ return null;
82
+ const { line } = sourceFile.getLineAndCharacterOfPosition(member.getStart());
83
+ return {
84
+ name: propName,
85
+ interfaceName,
86
+ filePath,
87
+ line: line + 1,
88
+ isOptional: member.questionToken !== undefined,
89
+ };
90
+ }
91
+ /**
92
+ * Extract config properties from interface members
93
+ */
94
+ function extractInterfaceProperties(node, sourceFile, filePath) {
95
+ const properties = [];
96
+ const interfaceName = node.name.text;
97
+ for (const member of node.members) {
98
+ const prop = extractPropertyFromMember(member, sourceFile, interfaceName, filePath);
99
+ if (!prop)
100
+ continue;
101
+ properties.push(prop);
102
+ }
103
+ return properties;
104
+ }
105
+ function isConfigFilePath(filePath) {
106
+ return filePath.includes('config') || filePath.includes('Config');
107
+ }
108
+ async function extractConfigPropertiesFromFile(filePath, files) {
109
+ // @lazy-ok -- visit function's conditionals are not pre-await validation guards
110
+ const content = await files.read(filePath);
111
+ const sourceFile = getSharedSourceFile(filePath, content);
112
+ /* v8 ignore next -- defensive guard */
113
+ if (!sourceFile)
114
+ return [];
115
+ const properties = [];
116
+ const visit = (node) => {
117
+ ts.forEachChild(node, visit);
118
+ if (!ts.isInterfaceDeclaration(node))
119
+ return;
120
+ /* v8 ignore next -- defensive AST/type guard */
121
+ if (!isConfigInterface(node.name.text))
122
+ return;
123
+ properties.push(...extractInterfaceProperties(node, sourceFile, filePath));
124
+ };
125
+ void visit(sourceFile);
126
+ return properties;
127
+ }
128
+ async function collectConfigProperties(files) {
129
+ logger.debug({
130
+ evt: 'fitness.collect_config_properties.start',
131
+ msg: 'Collecting config properties',
132
+ });
133
+ const configProperties = [];
134
+ for (const filePath of files.paths) {
135
+ if (shouldExcludePath(filePath) || !isConfigFilePath(filePath))
136
+ continue;
137
+ try {
138
+ // @fitness-ignore-next-line performance-anti-patterns -- sequential file reading to control memory; FileAccessor is lazy
139
+ const props = await extractConfigPropertiesFromFile(filePath, files);
140
+ configProperties.push(...props);
141
+ /* v8 ignore next 1 -- defensive catch: parse failures already handled */
142
+ }
143
+ catch {
144
+ // @swallow-ok Skip unreadable files
145
+ }
146
+ }
147
+ logger.debug({
148
+ evt: 'fitness.collect_config_properties.complete',
149
+ count: configProperties.length,
150
+ msg: 'Config properties collected',
151
+ });
152
+ return configProperties;
153
+ }
154
+ async function countPropertyAccesses(files) {
155
+ logger.debug({
156
+ evt: 'fitness.count_property_accesses.start',
157
+ msg: 'Counting property accesses across files',
158
+ });
159
+ const accessCounts = new Map();
160
+ for (const filePath of files.paths) {
161
+ try {
162
+ // @fitness-ignore-next-line performance-anti-patterns -- sequential file reading to control memory; FileAccessor is lazy
163
+ const content = await files.read(filePath);
164
+ const sourceFile = getSharedSourceFile(filePath, content);
165
+ /* v8 ignore next -- defensive guard */
166
+ if (!sourceFile)
167
+ continue;
168
+ const visit = (node) => {
169
+ if (ts.isPropertyAccessExpression(node)) {
170
+ const propertyName = node.name.text;
171
+ /* v8 ignore next -- defensive nullish fallback */
172
+ accessCounts.set(propertyName, (accessCounts.get(propertyName) ?? 0) + 1);
173
+ }
174
+ if (ts.isBindingElement(node) && ts.isIdentifier(node.name)) {
175
+ const propertyName = node.name.text;
176
+ /* v8 ignore next -- defensive nullish fallback */
177
+ accessCounts.set(propertyName, (accessCounts.get(propertyName) ?? 0) + 1);
178
+ }
179
+ ts.forEachChild(node, visit);
180
+ };
181
+ void visit(sourceFile);
182
+ /* v8 ignore next 1 -- defensive catch: parse failures already handled */
183
+ }
184
+ catch {
185
+ // @swallow-ok Skip unreadable files
186
+ }
187
+ }
188
+ return accessCounts;
189
+ }
190
+ function createViolationForUnusedProperty(prop) {
191
+ return {
192
+ line: prop.line,
193
+ column: 0,
194
+ message: `Config property '${prop.name}' in ${prop.interfaceName} is never accessed`,
195
+ severity: 'warning',
196
+ suggestion: `Remove unused config property '${prop.name}' from ${prop.interfaceName}, or implement code that uses this configuration option`,
197
+ match: prop.name,
198
+ filePath: prop.filePath,
199
+ };
200
+ }
201
+ function findUnusedProperties(configProperties, accessCounts) {
202
+ const violations = [];
203
+ for (const prop of configProperties) {
204
+ if (prop.isOptional)
205
+ continue;
206
+ /* v8 ignore next -- defensive nullish fallback */
207
+ const count = accessCounts.get(prop.name) ?? 0;
208
+ if (count === 0) {
209
+ violations.push(createViolationForUnusedProperty(prop));
210
+ }
211
+ }
212
+ return violations;
213
+ }
214
+ /**
215
+ * Check: quality/unused-config-options
216
+ *
217
+ * Detects configuration properties defined but never accessed.
218
+ */
219
+ export const unusedConfigOptions = defineCheck({
220
+ id: '09006e97-77fd-4a75-9a9a-d5ed0abb9d9f',
221
+ slug: 'unused-config-options',
222
+ scope: { languages: ['json', 'typescript', 'yaml'], concerns: ['config'] },
223
+ contentFilter: 'raw',
224
+ confidence: 'high',
225
+ description: 'Detects configuration properties defined but never accessed',
226
+ longDescription: `**Purpose:** Detects configuration properties that are defined in Config/Options interfaces but never accessed anywhere in the codebase.
227
+
228
+ **Detects:**
229
+ - Required (non-optional) properties in interfaces containing \`Config\` or \`Options\` in their name
230
+ - Properties with zero \`PropertyAccessExpression\` or \`BindingElement\` references across all scanned files
231
+ - Excludes common property names (\`enabled\`, \`timeout\`, \`port\`, \`host\`, etc.) to reduce false positives
232
+
233
+ **Why it matters:** Unused config properties add cognitive overhead and suggest incomplete implementations or abandoned features that should be cleaned up.
234
+
235
+ **Scope:** General best practice. Cross-file analysis (\`analyzeAll\`). Scans config files for property definitions, then counts access patterns across all production files.`,
236
+ tags: ['quality', 'code-quality', 'maintainability'],
237
+ fileTypes: ['ts', 'tsx'],
238
+ async analyzeAll(files) {
239
+ // @fitness-ignore-next-line async-waterfall-detection -- Both scan all files independently; parallelizing would double peak memory by loading file contents twice concurrently
240
+ const configProperties = await collectConfigProperties(files);
241
+ const accessCounts = await countPropertyAccesses(files);
242
+ return findUnusedProperties(configProperties, accessCounts);
243
+ },
244
+ });
245
+ //# sourceMappingURL=unused-config-options.js.map