@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,1369 @@
1
+ // @fitness-ignore-file file-length-limit -- behavior fixture suite; related scenarios stay together while checks are split into focused tests.
2
+ /**
3
+ * @fileoverview Second branch-behavior fixture suite: targeted scenarios for the
4
+ * highest-impact remaining branches.
5
+ */
6
+ import { mkdirSync, mkdtempSync, rmSync, writeFileSync } from 'node:fs';
7
+ import { tmpdir } from 'node:os';
8
+ import { dirname, join } from 'node:path';
9
+ import { LanguageRegistry, RunScope, runWithScope } from '@opensip-cli/core';
10
+ import { fileCache } from '@opensip-cli/fitness';
11
+ import { typescriptAdapter } from '@opensip-cli/lang-typescript';
12
+ import { afterEach, beforeEach, describe, expect, it } from 'vitest';
13
+ import { checks } from '../index.js';
14
+ // Production simulation: register the TS adapter (see behavior-fixtures.test.ts).
15
+ const langRegistry = new LanguageRegistry();
16
+ langRegistry.register(typescriptAdapter);
17
+ const testScope = new RunScope({ languages: langRegistry });
18
+ let cwd;
19
+ let written = [];
20
+ function fx(rel, content) {
21
+ const abs = join(cwd, rel);
22
+ mkdirSync(dirname(abs), { recursive: true });
23
+ writeFileSync(abs, content);
24
+ written.push(abs);
25
+ return abs;
26
+ }
27
+ function findCheck(slug) {
28
+ const c = checks.find((x) => x.config.slug === slug);
29
+ if (!c)
30
+ throw new Error(`check not found: ${slug}`);
31
+ return c;
32
+ }
33
+ async function runCheck(slug) {
34
+ const check = findCheck(slug);
35
+ await fileCache.prewarm(cwd, ['**/*']);
36
+ return runWithScope(testScope, () => check.run(cwd, { targetFiles: written }));
37
+ }
38
+ beforeEach(() => {
39
+ cwd = mkdtempSync(join(tmpdir(), 'opensip-cov-bp2-'));
40
+ written = [];
41
+ });
42
+ afterEach(() => {
43
+ fileCache.clear();
44
+ rmSync(cwd, { recursive: true, force: true });
45
+ });
46
+ // ---------------------------------------------------------------------------
47
+ // detached-promises — drive isFloatingExpression branches deeply
48
+ // ---------------------------------------------------------------------------
49
+ describe('detached-promises — additional branches', () => {
50
+ it('exercises isAwaitedExpression paren/non-null wrapping', async () => {
51
+ fx('src/x/a.ts', [
52
+ 'export async function f() {',
53
+ ' const x = !!(await fetcher())',
54
+ ' unwrap((await fetcher())!)',
55
+ ' unwrap((await fetcher()))',
56
+ ' ((await fetcher())!).chain()',
57
+ ' return x',
58
+ '}',
59
+ ].join('\n'));
60
+ const result = await runCheck('detached-promises');
61
+ expect(result).toBeDefined();
62
+ });
63
+ it('exercises containsAwaitedReceiver: element access, call descent', async () => {
64
+ fx('src/x/b.ts', [
65
+ 'export async function f() {',
66
+ ' (await x())[0]',
67
+ ' (await x()).foo()',
68
+ ' (await x())()',
69
+ ' ((await x())!).bar()',
70
+ '}',
71
+ ].join('\n'));
72
+ const result = await runCheck('detached-promises');
73
+ expect(result).toBeDefined();
74
+ });
75
+ it('exercises isDefinedAsSyncInSameFile: sync method same class', async () => {
76
+ fx('src/x/c.ts', [
77
+ 'export class Svc {',
78
+ ' syncHelper() { return 1 }',
79
+ ' async asyncHelper() { return 1 }',
80
+ ' async run() {',
81
+ ' this.syncHelper()',
82
+ ' this.asyncHelper()',
83
+ ' }',
84
+ '}',
85
+ ].join('\n'));
86
+ const result = await runCheck('detached-promises');
87
+ expect(result).toBeDefined();
88
+ });
89
+ it('exercises isInAsyncContext for class method declaration', async () => {
90
+ fx('src/x/d.ts', [
91
+ 'export class Svc {',
92
+ ' async run() {',
93
+ ' floatingCall()',
94
+ ' }',
95
+ ' sync() {',
96
+ ' floatingCall()', // not in async — skipped
97
+ ' }',
98
+ '}',
99
+ 'export const arrow = async () => { floatingCall() }',
100
+ 'export const arrowSync = () => { floatingCall() }',
101
+ 'function regular() { floatingCall() }',
102
+ ].join('\n'));
103
+ const result = await runCheck('detached-promises');
104
+ expect(result).toBeDefined();
105
+ });
106
+ it('handles nested receiver chain with non-sync names (Pyroscope.x.y.start fallback)', async () => {
107
+ fx('src/x/e.ts', [
108
+ 'export async function f() {',
109
+ ' Pyroscope.default.start()',
110
+ ' pyroscope.default.start()',
111
+ ' some.deep.chain.lookup()',
112
+ ' someUnknown.method()',
113
+ '}',
114
+ ].join('\n'));
115
+ const result = await runCheck('detached-promises');
116
+ expect(result).toBeDefined();
117
+ });
118
+ });
119
+ // ---------------------------------------------------------------------------
120
+ // throws-documentation — drive rethrow / self-doc branches
121
+ // ---------------------------------------------------------------------------
122
+ describe('throws-documentation — additional branches', () => {
123
+ it('rethrow patterns: bare, this.error, unwrapErr, sanitizedError(err)', async () => {
124
+ fx('src/x/throws.ts', [
125
+ 'export function f1() {',
126
+ ' try { return 1 }',
127
+ ' catch (err) { throw err }',
128
+ '}',
129
+ 'export function f2() {',
130
+ ' try { return 1 }',
131
+ ' catch (e) { throw sanitizedError(e) }',
132
+ '}',
133
+ 'export function f3() {',
134
+ ' try { return 1 }',
135
+ ' catch (err) { throw err.unwrapErr() }',
136
+ '}',
137
+ 'export function f4() {',
138
+ ' try { return 1 }',
139
+ ' catch (err) { throw err.unwrap() }',
140
+ '}',
141
+ 'export class K {',
142
+ ' error?: Error',
143
+ ' m() { throw this.error }',
144
+ ' n() { throw this.cause }',
145
+ ' o() { throw this.innerError }',
146
+ '}',
147
+ 'export function fresh() {',
148
+ ' // not a rethrow — fresh error',
149
+ ' throw new Error("fresh")',
150
+ '}',
151
+ 'export function arrowCallback() {',
152
+ ' return [1].map((_) => { throw new Error("inside cb") })',
153
+ '}',
154
+ 'export const namedArrow = () => { throw new Error("named") }',
155
+ ].join('\n'));
156
+ const result = await runCheck('throws-documentation');
157
+ expect(result).toBeDefined();
158
+ });
159
+ it('self-documenting suffix matching', async () => {
160
+ fx('src/x/typed.ts', [
161
+ 'export class FooApiError extends Error {}',
162
+ 'export function a() { throw new FooApiError() }',
163
+ 'export function b() { throw new ValidationError("x") }',
164
+ 'export function c() { throw new NotFoundError("nf") }',
165
+ 'export function d() { throw new InputValidationError("v") }',
166
+ ].join('\n'));
167
+ const result = await runCheck('throws-documentation');
168
+ expect(result).toBeDefined();
169
+ });
170
+ });
171
+ // ---------------------------------------------------------------------------
172
+ // async-waterfall-detection — broader patterns
173
+ // ---------------------------------------------------------------------------
174
+ describe('async-waterfall-detection — additional branches', () => {
175
+ it('arrow functions, methods, complex sequences', async () => {
176
+ fx('src/x/wf.ts', [
177
+ 'export const arrow = async () => {',
178
+ ' const a = await fetchA()',
179
+ ' const b = await fetchB()',
180
+ ' const c = await fetchC()',
181
+ ' return [a, b, c]',
182
+ '}',
183
+ 'export class Svc {',
184
+ ' async run() {',
185
+ ' const a = await fetchA()',
186
+ ' const b = await fetchB()',
187
+ ' return a + b',
188
+ ' }',
189
+ ' async runDep() {',
190
+ ' const a = await fetchA()',
191
+ ' const b = await fetchB(a)',
192
+ ' return b',
193
+ ' }',
194
+ '}',
195
+ 'export async function notInBlock(): Promise<void> {',
196
+ ' await fetchA()',
197
+ ' await fetchB()',
198
+ ' await fetchC()',
199
+ ' await fetchD()',
200
+ '}',
201
+ 'export async function withIfAndAwait(x: number) {',
202
+ ' if (x > 0) {',
203
+ ' await doIt()',
204
+ ' await doMore()',
205
+ ' } else {',
206
+ ' await doOther()',
207
+ ' }',
208
+ '}',
209
+ 'export async function awaitInParallel() {',
210
+ ' const [a, b] = await Promise.all([fetchA(), fetchB()])',
211
+ ' return a + b',
212
+ '}',
213
+ ].join('\n'));
214
+ const result = await runCheck('async-waterfall-detection');
215
+ expect(result).toBeDefined();
216
+ });
217
+ });
218
+ // ---------------------------------------------------------------------------
219
+ // array-validation — broader patterns
220
+ // ---------------------------------------------------------------------------
221
+ describe('array-validation — additional branches', () => {
222
+ it('Array<T>, ReadonlyArray<T>, union arrays, parenthesized, complex', async () => {
223
+ fx('src/x/arr.ts', [
224
+ 'export function a(items: Array<number>) { return items[0] }',
225
+ 'export function b(items: ReadonlyArray<number>) { return items[0] }',
226
+ 'export function c(items: (string[] | number[])) { return items[0] }',
227
+ 'export function d(items: (string[])) { return items[0] }',
228
+ 'export function e(items: Map<string, number[]>) { return items.get("a")?.[0] }',
229
+ 'export function f(items: { id: string }[]) { return items[0]?.id }',
230
+ 'export function g(items?: number[]) { return items?.length }',
231
+ 'export function h(items: number[] | null) {',
232
+ ' if (!items) return null',
233
+ ' return items[0]',
234
+ '}',
235
+ 'export function safeIsArray(items: unknown) {',
236
+ ' if (!Array.isArray(items)) return null',
237
+ ' return items[0]',
238
+ '}',
239
+ 'export function withZod(items: number[]) {',
240
+ ' z.array(z.number()).parse(items)',
241
+ ' return items[0]',
242
+ '}',
243
+ 'export function withCheck(items: number[]) {',
244
+ ' return checkSomething(items) ? items[0] : null',
245
+ '}',
246
+ 'export function withValidate(items: number[]) {',
247
+ ' return validateInput(items) ? items[0] : null',
248
+ '}',
249
+ ].join('\n'));
250
+ const result = await runCheck('array-validation');
251
+ expect(result).toBeDefined();
252
+ });
253
+ it('skip-paths: tests, mocks, fixtures', async () => {
254
+ fx('src/__tests__/x.ts', 'export function f(items: number[]) { return items[0] }');
255
+ fx('src/__mocks__/y.ts', 'export function f(items: number[]) { return items[0] }');
256
+ fx('src/test-fixtures/z.ts', 'export function f(items: number[]) { return items[0] }');
257
+ const result = await runCheck('array-validation');
258
+ expect(result).toBeDefined();
259
+ });
260
+ });
261
+ // ---------------------------------------------------------------------------
262
+ // numeric-validation — exercise more shapes
263
+ // ---------------------------------------------------------------------------
264
+ describe('numeric-validation — additional branches', () => {
265
+ it('division, multiplication, comparisons, parseInt/parseFloat with guards', async () => {
266
+ fx('src/x/num.ts', [
267
+ 'export function f(a: number, b: number) {',
268
+ ' if (b === 0) throw new RangeError("div0")',
269
+ ' if (Number.isNaN(a)) return 0',
270
+ ' if (!Number.isFinite(a)) return 0',
271
+ ' return a / b',
272
+ '}',
273
+ 'export function p1(s: string) {',
274
+ ' const n = parseInt(s, 10)',
275
+ ' if (Number.isNaN(n)) return 0',
276
+ ' return n',
277
+ '}',
278
+ 'export function p2(s: string) {',
279
+ ' return parseInt(s)', // missing radix
280
+ '}',
281
+ 'export function p3(s: string) {',
282
+ ' return parseFloat(s)',
283
+ '}',
284
+ 'export function p4(s: string) {',
285
+ ' return Number(s)',
286
+ '}',
287
+ 'export function negative(a: number) {',
288
+ ' return -a',
289
+ '}',
290
+ 'export function powAndMod(a: number, b: number) {',
291
+ ' return (a ** b) + (a % b)',
292
+ '}',
293
+ 'export class Calc {',
294
+ ' divide(a: number, b: number) { return a / b }',
295
+ '}',
296
+ ].join('\n'));
297
+ const result = await runCheck('numeric-validation');
298
+ expect(result).toBeDefined();
299
+ });
300
+ });
301
+ // ---------------------------------------------------------------------------
302
+ // null-safety — additional patterns
303
+ // ---------------------------------------------------------------------------
304
+ describe('null-safety — additional branches', () => {
305
+ it('union types, nullable returns, optional chains, non-null assertions', async () => {
306
+ fx('src/x/ns.ts', [
307
+ 'export function f1(x: string | null) {',
308
+ ' return x.length', // unsafe
309
+ '}',
310
+ 'export function f2(x: string | null | undefined) {',
311
+ ' return x?.length',
312
+ '}',
313
+ 'export function f3(x?: { a?: { b?: number } }) {',
314
+ ' return x?.a?.b ?? 0',
315
+ '}',
316
+ 'export function f4(x: number | null) {',
317
+ ' if (typeof x === "number") return x + 1',
318
+ ' return 0',
319
+ '}',
320
+ 'export function f5(x: { items: number[] | null }) {',
321
+ ' return x.items.length', // unsafe nested
322
+ '}',
323
+ 'export class X {',
324
+ ' name?: string',
325
+ ' greet() { return this.name!.toUpperCase() }',
326
+ ' greetSafe() { return this.name?.toUpperCase() ?? "anon" }',
327
+ ' greetCheck() {',
328
+ ' if (this.name === undefined) return ""',
329
+ ' return this.name',
330
+ ' }',
331
+ '}',
332
+ 'export function arr(items?: number[] | null) {',
333
+ ' return items?.[0] ?? 0',
334
+ '}',
335
+ 'export function withTypeOf(v: unknown) {',
336
+ ' if (typeof v === "string") return v.length',
337
+ ' return 0',
338
+ '}',
339
+ ].join('\n'));
340
+ const result = await runCheck('null-safety');
341
+ expect(result).toBeDefined();
342
+ });
343
+ });
344
+ // ---------------------------------------------------------------------------
345
+ // stubbed-implementation-detection — multi-pattern
346
+ // ---------------------------------------------------------------------------
347
+ describe('stubbed-implementation-detection — additional branches', () => {
348
+ it('various stub shapes', async () => {
349
+ fx('src/x/stub.ts', [
350
+ 'export function s1() { return null }',
351
+ 'export function s2(): null { return null }',
352
+ 'export function s3() { return undefined }',
353
+ 'export function s4() { return [] }',
354
+ 'export function s5() { return {} }',
355
+ 'export function s6(): void { }',
356
+ 'export function s7(): void { /* TODO */ }',
357
+ 'export function s8() { throw new Error("not implemented") }',
358
+ 'export function s9() { throw new Error("Not yet implemented") }',
359
+ 'export function s10() { throw new Error("TODO") }',
360
+ 'export function s11() { throw new Error("FIXME") }',
361
+ 'export async function s12() { return null }',
362
+ 'export const arrow = () => null',
363
+ 'export class K {',
364
+ ' m1() { return null }',
365
+ ' m2(): never { throw new Error("nope") }',
366
+ ' m3() { return [] }',
367
+ ' m4() {} // empty',
368
+ ' m5() {',
369
+ ' throw new Error("not implemented")',
370
+ ' }',
371
+ '}',
372
+ 'export function realImpl(a: number, b: number) {',
373
+ ' if (a < 0) throw new RangeError("neg")',
374
+ ' return a + b * 2',
375
+ '}',
376
+ ].join('\n'));
377
+ const result = await runCheck('stubbed-implementation-detection');
378
+ expect(result).toBeDefined();
379
+ });
380
+ });
381
+ // ---------------------------------------------------------------------------
382
+ // di-static-inject-usage — broader scenarios
383
+ // ---------------------------------------------------------------------------
384
+ // ---------------------------------------------------------------------------
385
+ // fastify-route-validation — broader scenarios
386
+ // ---------------------------------------------------------------------------
387
+ describe('fastify-route-validation — additional branches', () => {
388
+ it('POST/PUT/PATCH with options, with arrow handler, with body access without validation', async () => {
389
+ fx('src/routes/r.ts', [
390
+ 'import type { FastifyInstance } from "fastify"',
391
+ 'export async function reg(app: FastifyInstance) {',
392
+ ' app.post("/a", { schema: { body: { type: "object" } } }, async () => ({ ok: true }))',
393
+ ' app.post("/b", async (req, reply) => {',
394
+ ' const body = request.body',
395
+ ' if (!body) return reply.code(400).send({ message: "Missing body" })',
396
+ ' return { ok: true }',
397
+ ' })',
398
+ ' app.post("/c", async (req) => {',
399
+ ' return req.body',
400
+ ' })',
401
+ ' app.put("/d", { schema: { body: {} } }, async () => ({}))',
402
+ ' app.patch("/e", async () => ({}))',
403
+ ' app.get("/f", async () => ({}))', // GET — skipped',
404
+ ' app.post("/g")', // single arg — skipped',
405
+ ' app.post("/h", function(req, reply) { return req.body })',
406
+ ' app.post("/i", { schema: { params: {} } }, async () => ({}))', // schema but no body
407
+ '}',
408
+ ].join('\n'));
409
+ fx('src/routes/zod.ts', [
410
+ 'import { z } from "zod"',
411
+ 'const Body = z.object({ id: z.string() })',
412
+ 'export const reg = (app: any) => {',
413
+ ' app.post("/x", async (req: any) => {',
414
+ ' Body.parse(req.body)',
415
+ ' return { ok: true }',
416
+ ' })',
417
+ '}',
418
+ ].join('\n'));
419
+ fx('src/routes/contracts.ts', [
420
+ '// uses contracts and Schema',
421
+ 'export const reg = (app: any) => {',
422
+ ' app.post("/y", async (req: any) => req.body)',
423
+ '}',
424
+ ].join('\n'));
425
+ const result = await runCheck('fastify-route-validation');
426
+ expect(result).toBeDefined();
427
+ });
428
+ });
429
+ // ---------------------------------------------------------------------------
430
+ // duplicate-utility-functions — additional shapes
431
+ // ---------------------------------------------------------------------------
432
+ describe('duplicate-utility-functions — additional branches', () => {
433
+ it('arrow functions, function expressions, varying arities', async () => {
434
+ fx('src/u/a.ts', [
435
+ 'export const fmt = (s: string) => s.trim()',
436
+ 'export const sum = (a: number, b: number) => a + b',
437
+ 'export function helperX(s: string) { return s.toLowerCase() }',
438
+ ].join('\n'));
439
+ fx('src/u/b.ts', [
440
+ 'export const fmt = (s: string) => s.trim()', // duplicate arrow
441
+ 'export function sum(a: number, b: number) { return a + b }', // same body different syntax
442
+ ].join('\n'));
443
+ fx('src/u/c.ts', ['export const fmt = function(s: string) { return s.trim() }'].join('\n'));
444
+ fx('src/u/d.ts', ['export function unique(name: string) { return `hello ${name}` }'].join('\n'));
445
+ const result = await runCheck('duplicate-utility-functions');
446
+ expect(result).toBeDefined();
447
+ });
448
+ });
449
+ // ---------------------------------------------------------------------------
450
+ // silent-early-returns — broader patterns
451
+ // ---------------------------------------------------------------------------
452
+ describe('silent-early-returns — additional branches', () => {
453
+ it('return null/undefined/empty array, with and without log', async () => {
454
+ fx('src/x/ser.ts', [
455
+ 'export function f1(x: any) { if (!x) return null; return x.id }',
456
+ 'export function f2(x: any) {',
457
+ ' if (!x) {',
458
+ ' logger.warn({ event: "missing" })',
459
+ ' return null',
460
+ ' }',
461
+ ' return x.id',
462
+ '}',
463
+ 'export function f3(items: any[]) { if (!items.length) return; return items[0] }',
464
+ 'export function f4(items: any[]) { if (!items.length) { console.error("empty"); return } return items[0] }',
465
+ 'export function f5(x?: string) { return x ?? null }',
466
+ 'export function f6() { return undefined }',
467
+ 'export function f7(): never { throw new Error("never") }',
468
+ 'export class X {',
469
+ ' m(x: any) { if (!x) return null; return x.id }',
470
+ ' n(x: any) { if (!x) { this.log("oops"); return null } return x.id }',
471
+ ' log(msg: string) { return msg }',
472
+ '}',
473
+ 'export const arrow = (x: any) => x ? x.id : null',
474
+ ].join('\n'));
475
+ const result = await runCheck('silent-early-returns');
476
+ expect(result).toBeDefined();
477
+ });
478
+ });
479
+ // ---------------------------------------------------------------------------
480
+ // missing-input-validation — additional shapes
481
+ // ---------------------------------------------------------------------------
482
+ describe('missing-input-validation — additional branches', () => {
483
+ it('zod parse, safeParse, no validation, arrow handler', async () => {
484
+ fx('src/x/h.ts', [
485
+ 'import { z } from "zod"',
486
+ 'export async function h1(req: any) {',
487
+ ' const Body = z.object({ x: z.string() })',
488
+ ' return Body.parse(req.body)',
489
+ '}',
490
+ 'export async function h2(req: any) {',
491
+ ' const Body = z.object({ x: z.string() })',
492
+ ' const r = Body.safeParse(req.body)',
493
+ ' return r.success ? r.data : null',
494
+ '}',
495
+ 'export async function h3(req: any) {',
496
+ ' return req.body.x', // no validation
497
+ '}',
498
+ 'export const h4 = async (req: any) => req.body.x', // arrow no validation
499
+ 'export class C {',
500
+ ' async handle(req: any) {',
501
+ ' return req.body',
502
+ ' }',
503
+ '}',
504
+ ].join('\n'));
505
+ const result = await runCheck('missing-input-validation');
506
+ expect(result).toBeDefined();
507
+ });
508
+ });
509
+ // ---------------------------------------------------------------------------
510
+ // api-response-validation — additional shapes
511
+ // ---------------------------------------------------------------------------
512
+ describe('api-response-validation — additional branches', () => {
513
+ it('handlers returning typed responses, raw db, or wrapped', async () => {
514
+ fx('src/x/api.ts', [
515
+ 'import { z } from "zod"',
516
+ 'const Resp = z.object({ ok: z.boolean() })',
517
+ 'export async function safe() { return Resp.parse({ ok: true }) }',
518
+ 'export async function unsafe() { return await db.query("SELECT *") }',
519
+ 'export async function arrow1() { return { ok: true } }',
520
+ 'export const arrow2 = async () => Resp.parse({ ok: true })',
521
+ 'export class C {',
522
+ ' async fetch() { return { ok: true } }',
523
+ ' async typed(): Promise<{ ok: boolean }> { return { ok: true } }',
524
+ '}',
525
+ ].join('\n'));
526
+ const result = await runCheck('api-response-validation');
527
+ expect(result).toBeDefined();
528
+ });
529
+ });
530
+ // ---------------------------------------------------------------------------
531
+ // api-contract-validation — broader shapes
532
+ // ---------------------------------------------------------------------------
533
+ describe('api-contract-validation — additional branches', () => {
534
+ it('handler signatures with various forms', async () => {
535
+ fx('src/x/h2.ts', [
536
+ 'export async function h1(req: { body: string }, res: any): Promise<{ ok: boolean }> {',
537
+ ' return { ok: true }',
538
+ '}',
539
+ 'export async function h2(req: any, res: any) {',
540
+ ' try { return { ok: true } } catch (e) { return { ok: false } }',
541
+ '}',
542
+ 'export const arrow = async (req: any) => req',
543
+ 'export class C {',
544
+ ' async handle(req: any, res: any): Promise<unknown> { return req }',
545
+ ' async typed(req: { x: number }): Promise<{ ok: boolean }> { return { ok: true } }',
546
+ '}',
547
+ 'export function sync(req: any) { return req }',
548
+ 'export const noTypeArrow = (req: any) => req',
549
+ ].join('\n'));
550
+ const result = await runCheck('api-contract-validation');
551
+ expect(result).toBeDefined();
552
+ });
553
+ });
554
+ // ---------------------------------------------------------------------------
555
+ // incomplete-regex-escaping — broader scenarios
556
+ // ---------------------------------------------------------------------------
557
+ describe('incomplete-regex-escaping — additional branches', () => {
558
+ it('various RegExp constructions and escapes', async () => {
559
+ fx('src/x/re.ts', [
560
+ 'export function r1(input: string) { return new RegExp(input) }',
561
+ 'export function r2(input: string) {',
562
+ ' const escaped = input.replace(/[.*+?^${}()|[\\]\\\\]/g, "\\\\$&")',
563
+ ' return new RegExp(escaped)',
564
+ '}',
565
+ 'export function r3(prefix: string) {',
566
+ ' return new RegExp(`^${prefix}`)',
567
+ '}',
568
+ 'export const literal = /[a-z]+/g',
569
+ String.raw `export const multi = /^\w{3,8}$/`,
570
+ 'export function r4(input: string) {',
571
+ ' return input.replace(new RegExp(input, "i"), "")',
572
+ '}',
573
+ 'export function r5() {',
574
+ String.raw ` return new RegExp("\\d+", "g")`,
575
+ '}',
576
+ 'export function r6(input: string) {',
577
+ ' // comment about new RegExp',
578
+ ' return input',
579
+ '}',
580
+ ].join('\n'));
581
+ const result = await runCheck('incomplete-regex-escaping');
582
+ expect(result).toBeDefined();
583
+ });
584
+ });
585
+ // ---------------------------------------------------------------------------
586
+ // unused-modules / unused-config-options — branches
587
+ // ---------------------------------------------------------------------------
588
+ describe('unused-config-options — additional branches', () => {
589
+ it('Config interface with optional/required, used and unused fields', async () => {
590
+ fx('src/config/c.ts', [
591
+ 'export interface AppConfig {',
592
+ ' apiUrl: string',
593
+ ' port: number',
594
+ ' optional?: boolean',
595
+ ' unused: string',
596
+ ' unusedOptional?: boolean',
597
+ '}',
598
+ ].join('\n'));
599
+ fx('src/main.ts', [
600
+ 'import type { AppConfig } from "./config/c.js"',
601
+ 'export function start(c: AppConfig) {',
602
+ ' console.log(c.apiUrl)',
603
+ ' console.log(c.port)',
604
+ ' if (c.optional) doIt()',
605
+ ' return c',
606
+ '}',
607
+ ].join('\n'));
608
+ const result = await runCheck('unused-config-options');
609
+ expect(result).toBeDefined();
610
+ });
611
+ });
612
+ // ---------------------------------------------------------------------------
613
+ // drizzle-orm-migration-guardrails — drive remaining branches
614
+ // ---------------------------------------------------------------------------
615
+ describe('drizzle-orm-migration-guardrails — additional branches', () => {
616
+ it('test paths skip, comment lines skip, DATA-LOSS skip', async () => {
617
+ fx('src/db/migrations/m1.test.ts', 'export const x = 1\nDROP TABLE foo');
618
+ fx('src/db/migrations/__tests__/y.ts', 'export const x = 1\nDROP TABLE foo');
619
+ fx('src/db/migrations/m2.ts', [
620
+ '// regular comment',
621
+ '* doc-comment block',
622
+ '',
623
+ '// DATA-LOSS: intentional drop for renamed_users migration',
624
+ 'export const m = sql`DROP TABLE renamed_users`',
625
+ 'export const tr = sql`TRUNCATE TABLE log_old`',
626
+ 'export const a = sql`ALTER TABLE x ALTER COLUMN y TYPE varchar`',
627
+ ].join('\n'));
628
+ fx('src/db/schema/users.ts', [
629
+ 'export const users = pgTable("users", {})',
630
+ 'sql.unsafe("UPDATE users SET active=true")',
631
+ ].join('\n'));
632
+ const result = await runCheck('drizzle-orm-migration-guardrails');
633
+ expect(result).toBeDefined();
634
+ });
635
+ });
636
+ // ---------------------------------------------------------------------------
637
+ // observability-coverage helper — direct unit-test path
638
+ // ---------------------------------------------------------------------------
639
+ // covered by existing dedicated unit tests under
640
+ // src/checks/quality/observability/observability-coverage/__tests__/
641
+ // ---------------------------------------------------------------------------
642
+ // pii-exposure-in-logs — additional patterns
643
+ // ---------------------------------------------------------------------------
644
+ describe('pii-exposure-in-logs — additional branches', () => {
645
+ it('various log methods and PII fields', async () => {
646
+ fx('src/svc/log.ts', [
647
+ 'export function f1(req: any) {',
648
+ ' logger.debug({ user: { email: req.email, password: req.password, ssn: req.ssn } })',
649
+ ' console.log({ creditCard: req.cc })',
650
+ ' console.warn({ phone: req.phone, dob: req.dob })',
651
+ ' console.error("error: " + req.body)',
652
+ ' pino.info({ name: req.name })', // user name
653
+ '}',
654
+ 'export function safe(req: any) {',
655
+ ' logger.info({ event: "user.created", id: req.id })',
656
+ ' logger.info({ requestId: req.requestId })',
657
+ ' console.log("safe message")',
658
+ '}',
659
+ ].join('\n'));
660
+ const result = await runCheck('pii-exposure-in-logs');
661
+ expect(result).toBeDefined();
662
+ });
663
+ });
664
+ // ---------------------------------------------------------------------------
665
+ // logger-event-name-format — drive shape branches
666
+ // ---------------------------------------------------------------------------
667
+ describe('logger-event-name-format — additional branches', () => {
668
+ it('various event-name shapes', async () => {
669
+ fx('src/svc/ev.ts', [
670
+ 'logger.info("user.created")',
671
+ 'logger.info("UserCreated")',
672
+ 'logger.info("user_created")',
673
+ 'logger.info("user-created")',
674
+ 'logger.info({ event: "user.created" })',
675
+ 'logger.info({ event: "userCreated" })',
676
+ 'logger.info({ event: "USER_CREATED" })',
677
+ 'logger.warn({ event: "" })',
678
+ 'logger.error({ event: 123 })',
679
+ 'logger.info({ x: 1 })',
680
+ 'logger.info("plain message")',
681
+ 'logger.info("module.submodule.event_name")',
682
+ ].join('\n'));
683
+ const result = await runCheck('logger-event-name-format');
684
+ expect(result).toBeDefined();
685
+ });
686
+ });
687
+ // ---------------------------------------------------------------------------
688
+ // stream-buffer-size-limits — additional shapes
689
+ // ---------------------------------------------------------------------------
690
+ describe('stream-buffer-size-limits — additional branches', () => {
691
+ it('Readable, Writable, Transform, pipe', async () => {
692
+ fx('src/stream/s.ts', [
693
+ 'import { Readable, Writable, Transform, pipeline } from "stream"',
694
+ 'export const r1 = new Readable()', // unbounded
695
+ 'export const r2 = new Readable({ highWaterMark: 1024 })',
696
+ 'export const w1 = new Writable()', // unbounded
697
+ 'export const w2 = new Writable({ highWaterMark: 4096 })',
698
+ 'export const t1 = new Transform()',
699
+ 'export const t2 = new Transform({ highWaterMark: 8192 })',
700
+ 'export const p = pipeline(r1, w1, () => undefined)',
701
+ ].join('\n'));
702
+ const result = await runCheck('stream-buffer-size-limits');
703
+ expect(result).toBeDefined();
704
+ });
705
+ });
706
+ // ---------------------------------------------------------------------------
707
+ // dispose-pattern-completeness — additional class shapes
708
+ // ---------------------------------------------------------------------------
709
+ describe('dispose-pattern-completeness — additional branches', () => {
710
+ it('various dispose patterns', async () => {
711
+ fx('src/x/d.ts', [
712
+ 'export class A implements Disposable {',
713
+ ' [Symbol.dispose]() {}',
714
+ '}',
715
+ 'export class B implements AsyncDisposable {',
716
+ ' async [Symbol.asyncDispose]() {}',
717
+ '}',
718
+ 'export class C {',
719
+ ' dispose() {}',
720
+ '}',
721
+ 'export class D {',
722
+ ' destroy() {}',
723
+ '}',
724
+ 'export class E {',
725
+ ' async close() {}',
726
+ '}',
727
+ 'export class F {',
728
+ ' private timer: NodeJS.Timer | null = null',
729
+ ' start() { this.timer = setInterval(() => undefined, 100) }',
730
+ ' // missing dispose',
731
+ '}',
732
+ 'export class G {',
733
+ ' private interval: any',
734
+ ' private subscription: any',
735
+ ' start() {',
736
+ ' this.interval = setInterval(() => undefined, 100)',
737
+ ' this.subscription = src.subscribe(() => undefined)',
738
+ ' }',
739
+ ' dispose() {',
740
+ ' if (this.interval) clearInterval(this.interval)',
741
+ ' this.subscription?.unsubscribe()',
742
+ ' }',
743
+ '}',
744
+ ].join('\n'));
745
+ const result = await runCheck('dispose-pattern-completeness');
746
+ expect(result).toBeDefined();
747
+ });
748
+ });
749
+ // ---------------------------------------------------------------------------
750
+ // lifecycle-cleanup-enforcement — additional patterns
751
+ // ---------------------------------------------------------------------------
752
+ describe('lifecycle-cleanup-enforcement — additional branches', () => {
753
+ it('useEffect with intervals, listeners, observers, fetches', async () => {
754
+ fx('src/x/le.tsx', [
755
+ 'import { useEffect } from "react"',
756
+ 'export function A() {',
757
+ ' useEffect(() => {',
758
+ ' const id = setInterval(() => undefined, 100)',
759
+ ' return () => clearInterval(id)',
760
+ ' }, [])',
761
+ ' return null',
762
+ '}',
763
+ 'export function B() {',
764
+ ' useEffect(() => {',
765
+ ' const t = setTimeout(() => undefined, 100)',
766
+ ' return () => clearTimeout(t)',
767
+ ' }, [])',
768
+ ' return null',
769
+ '}',
770
+ 'export function C() {',
771
+ ' useEffect(() => {',
772
+ ' window.addEventListener("resize", onResize)',
773
+ ' return () => window.removeEventListener("resize", onResize)',
774
+ ' }, [])',
775
+ ' return null',
776
+ '}',
777
+ 'export function D() {',
778
+ ' useEffect(() => {',
779
+ ' setInterval(() => undefined, 100)', // missing cleanup
780
+ ' }, [])',
781
+ ' return null',
782
+ '}',
783
+ 'export function E() {',
784
+ ' useEffect(() => {',
785
+ ' const ac = new AbortController()',
786
+ ' fetch("/x", { signal: ac.signal })',
787
+ ' return () => ac.abort()',
788
+ ' }, [])',
789
+ ' return null',
790
+ '}',
791
+ ].join('\n'));
792
+ const result = await runCheck('lifecycle-cleanup-enforcement');
793
+ expect(result).toBeDefined();
794
+ });
795
+ });
796
+ // ---------------------------------------------------------------------------
797
+ // mock-implementations-in-production — drive line 197 branch
798
+ // ---------------------------------------------------------------------------
799
+ describe('mock-implementations-in-production — additional branches', () => {
800
+ it('files in src/ vs __mocks__ vs test paths', async () => {
801
+ fx('src/api/handler.ts', [
802
+ 'export const fakeData = () => [{ id: "fake" }]',
803
+ 'export const mockUser = { id: "mock", isMock: true }',
804
+ 'export class StubClient {',
805
+ ' query() { return [] }',
806
+ '}',
807
+ ].join('\n'));
808
+ fx('src/__mocks__/api.ts', ['export const mockUser = { id: "mock" }'].join('\n'));
809
+ fx('src/x.test.ts', ['export const t = "test"'].join('\n'));
810
+ fx('src/realImpl.ts', ['export class RealClient {', ' query() { return [] }', '}'].join('\n'));
811
+ const result = await runCheck('mock-implementations-in-production');
812
+ expect(result).toBeDefined();
813
+ });
814
+ });
815
+ // ---------------------------------------------------------------------------
816
+ // context-safety — drive several branches
817
+ // ---------------------------------------------------------------------------
818
+ describe('context-safety — additional branches', () => {
819
+ it('various context-related patterns', async () => {
820
+ fx('src/svc/cs.ts', [
821
+ 'export class Foo {',
822
+ ' async method() {',
823
+ ' return this.helper()',
824
+ ' }',
825
+ ' helper() { return 1 }',
826
+ '}',
827
+ 'export const arrow = (this: any) => this.something',
828
+ 'export class Bar {',
829
+ ' data = "x"',
830
+ ' bound = this.method.bind(this)',
831
+ ' method() { return this.data }',
832
+ ' unbound() { return this.method }',
833
+ '}',
834
+ 'export class Baz {',
835
+ ' callback() {',
836
+ ' setTimeout(() => this.run(), 100)', // safe arrow capture',
837
+ ' setTimeout(this.run.bind(this), 100)', // safe bind',
838
+ ' setTimeout(this.run, 100)', // unsafe!',
839
+ ' }',
840
+ ' run() { return 1 }',
841
+ '}',
842
+ ].join('\n'));
843
+ const result = await runCheck('context-leakage');
844
+ expect(result).toBeDefined();
845
+ });
846
+ });
847
+ // ---------------------------------------------------------------------------
848
+ // async-patterns / no-raw-fetch — additional skip-path branches
849
+ // ---------------------------------------------------------------------------
850
+ describe('no-raw-fetch — additional skip patterns', () => {
851
+ it('comment-only lines, fitness check files', async () => {
852
+ fx('src/fitness/src/checks/x.ts', [
853
+ 'export const x = "fetch("', // mention but it is a fitness check file',
854
+ 'await fetch("/x")',
855
+ ].join('\n'));
856
+ fx('src/x.spec.tsx', ['await fetch("/x")'].join('\n'));
857
+ fx('src/x.test.jsx', ['await fetch("/x")'].join('\n'));
858
+ fx('src/api/r.ts', ['// fetch in comment', '/* multi-line comment with fetch( */', 'await fetch("/real")'].join('\n'));
859
+ const result = await runCheck('no-raw-fetch');
860
+ expect(result).toBeDefined();
861
+ });
862
+ });
863
+ // ---------------------------------------------------------------------------
864
+ // toctou-race-condition — additional class/getter/multi-method branches
865
+ // ---------------------------------------------------------------------------
866
+ describe('toctou-race-condition — additional branches', () => {
867
+ it('private field cache, multiple methods, setter/getter', async () => {
868
+ fx('src/x/toc.ts', [
869
+ 'export class C {',
870
+ ' private _cache = new Map<string, number>()',
871
+ ' private store: Map<string, number> = new Map()',
872
+ ' get count() { return this._cache.size }',
873
+ ' set value(v: number) { this._cache.set("v", v) }',
874
+ ' read(id: string) { return this._cache.get(id) }',
875
+ ' write(id: string, v: number) { this._cache.set(id, v) }',
876
+ ' // shared receiver',
877
+ ' async sharedReadUpdate(id: string) {',
878
+ ' const u = await db.find(id)',
879
+ ' return await db.update({ ...u })',
880
+ ' }',
881
+ '}',
882
+ 'export function topLevel(repo: any) {',
883
+ ' const u = repo.find(1)',
884
+ ' repo.update(u)',
885
+ ' return u',
886
+ '}',
887
+ ].join('\n'));
888
+ const result = await runCheck('toctou-race-condition');
889
+ expect(result).toBeDefined();
890
+ });
891
+ });
892
+ // ---------------------------------------------------------------------------
893
+ // memo-list-items — exercise findEnclosingMapCall walk + isInsideUseMemo deep
894
+ // ---------------------------------------------------------------------------
895
+ // ---------------------------------------------------------------------------
896
+ // no-inline-functions — additional branches
897
+ // ---------------------------------------------------------------------------
898
+ // ---------------------------------------------------------------------------
899
+ // platform-checks — additional shapes
900
+ // ---------------------------------------------------------------------------
901
+ // ---------------------------------------------------------------------------
902
+ // flashlist-enforcement — additional shapes
903
+ // ---------------------------------------------------------------------------
904
+ // ---------------------------------------------------------------------------
905
+ // lazy-loading — broader patterns
906
+ // ---------------------------------------------------------------------------
907
+ // ---------------------------------------------------------------------------
908
+ // missing-type-exports — exercise barrel-only fallback and patterns
909
+ // ---------------------------------------------------------------------------
910
+ describe('missing-type-exports — additional branches', () => {
911
+ it('package without exports map (barrel fallback), wildcards', async () => {
912
+ fx('packages/lib/package.json', JSON.stringify({
913
+ name: '@s/lib',
914
+ version: '1.0.0',
915
+ }, null, 2));
916
+ fx('packages/lib/src/index.ts', 'export { Public } from "./pub.js"');
917
+ fx('packages/lib/src/pub.ts', 'export const Public = 1');
918
+ fx('packages/lib/src/internal.ts', 'export const Internal = 2');
919
+ fx('packages/lib/src/wild.ts', 'export const Wild = 3');
920
+ fx('packages/u/src/uses.ts', [
921
+ 'import { Public } from "@s/lib/some/path"',
922
+ 'import { Internal } from "@s/lib/internal"',
923
+ 'export const x = Public',
924
+ 'export const y = Internal',
925
+ ].join('\n'));
926
+ fx('packages/lib2/package.json', JSON.stringify({
927
+ name: '@s/lib2',
928
+ version: '1.0.0',
929
+ exports: {
930
+ '.': './dist/index.js',
931
+ './sub/*': './dist/sub/*.js',
932
+ },
933
+ }, null, 2));
934
+ fx('packages/u2/src/uses.ts', [
935
+ 'import { X } from "@s/lib2/sub/widget"', // wildcard match
936
+ 'import { Y } from "@s/lib2/notexposed"', // not declared
937
+ 'export const z = X',
938
+ 'export const w = Y',
939
+ ].join('\n'));
940
+ const result = await runCheck('missing-type-exports');
941
+ expect(result).toBeDefined();
942
+ });
943
+ });
944
+ // ---------------------------------------------------------------------------
945
+ // circular-import-detection — exercise basic patterns
946
+ // ---------------------------------------------------------------------------
947
+ describe('circular-import-detection — additional branches', () => {
948
+ it('two-cycle, three-cycle, no-cycle', async () => {
949
+ fx('src/c/a.ts', 'import { b } from "./b.js"; export const a = b');
950
+ fx('src/c/b.ts', 'import { a } from "./a.js"; export const b = a');
951
+ fx('src/c/x.ts', 'import { y } from "./y.js"; export const x = y');
952
+ fx('src/c/y.ts', 'import { z } from "./z.js"; export const y = z');
953
+ fx('src/c/z.ts', 'import { x } from "./x.js"; export const z = x');
954
+ fx('src/c/clean.ts', 'export const clean = 1');
955
+ const result = await runCheck('circular-import-detection');
956
+ expect(result).toBeDefined();
957
+ });
958
+ });
959
+ // ---------------------------------------------------------------------------
960
+ // module-coupling-fan-out — additional shapes
961
+ // ---------------------------------------------------------------------------
962
+ describe('module-coupling-fan-out — additional branches', () => {
963
+ it('high-fanout files vs low-fanout', async () => {
964
+ const imports = [];
965
+ for (let i = 0; i < 25; i++) {
966
+ fx(`src/m/m${i}.ts`, `export const m${i} = ${i}`);
967
+ imports.push(`import { m${i} } from "./m${i}.js"`);
968
+ }
969
+ fx('src/m/big.ts', [
970
+ ...imports,
971
+ 'export const total = ' + Array.from({ length: 25 }, (_, i) => `m${i}`).join(' + '),
972
+ ].join('\n'));
973
+ fx('src/m/small.ts', 'import { m0 } from "./m0.js"; export const x = m0');
974
+ const result = await runCheck('module-coupling-fan-out');
975
+ expect(result).toBeDefined();
976
+ });
977
+ });
978
+ // ---------------------------------------------------------------------------
979
+ // typed-inject-scope-mismatch — additional shapes
980
+ // ---------------------------------------------------------------------------
981
+ // ---------------------------------------------------------------------------
982
+ // package-json-exports-field — broader shapes
983
+ // ---------------------------------------------------------------------------
984
+ describe('package-json-exports-field — additional branches', () => {
985
+ it('various exports configurations', async () => {
986
+ fx('package.json', JSON.stringify({
987
+ name: '@scope/test',
988
+ version: '1.0.0',
989
+ type: 'module',
990
+ main: './dist/index.js',
991
+ module: './dist/index.mjs',
992
+ types: './dist/index.d.ts',
993
+ exports: {
994
+ '.': {
995
+ import: './dist/index.js',
996
+ types: './dist/index.d.ts',
997
+ },
998
+ './errors': './dist/errors.js',
999
+ },
1000
+ }, null, 2));
1001
+ fx('src/index.ts', 'export const x = 1');
1002
+ const result = await runCheck('package-json-exports-field');
1003
+ expect(result).toBeDefined();
1004
+ });
1005
+ });
1006
+ // ---------------------------------------------------------------------------
1007
+ // contracts-schema-consistency — additional shapes
1008
+ // ---------------------------------------------------------------------------
1009
+ describe('contracts-schema-consistency — additional branches', () => {
1010
+ it('zod schemas with matching/non-matching types', async () => {
1011
+ fx('src/contracts/schemas.ts', [
1012
+ 'import { z } from "zod"',
1013
+ 'export const UserSchema = z.object({ id: z.string(), name: z.string() })',
1014
+ 'export type User = z.infer<typeof UserSchema>',
1015
+ 'export const ProductSchema = z.object({ id: z.string(), price: z.number() })',
1016
+ 'export interface Product { id: string; price: number }',
1017
+ ].join('\n'));
1018
+ const result = await runCheck('contracts-schema-consistency');
1019
+ expect(result).toBeDefined();
1020
+ });
1021
+ });
1022
+ // ---------------------------------------------------------------------------
1023
+ // tsconfig-extends-validation — broader scenarios
1024
+ // ---------------------------------------------------------------------------
1025
+ describe('tsconfig-extends-validation — additional branches', () => {
1026
+ it('with extends, without extends, with strict, missing strict', async () => {
1027
+ fx('tsconfig.base.json', JSON.stringify({ compilerOptions: { strict: true } }, null, 2));
1028
+ fx('tsconfig.json', JSON.stringify({
1029
+ extends: './tsconfig.base.json',
1030
+ compilerOptions: { target: 'es2022' },
1031
+ }, null, 2));
1032
+ fx('packages/a/tsconfig.json', JSON.stringify({
1033
+ compilerOptions: { strict: false },
1034
+ }, null, 2));
1035
+ fx('packages/b/tsconfig.json', JSON.stringify({
1036
+ compilerOptions: {},
1037
+ }, null, 2));
1038
+ const result = await runCheck('tsconfig-extends-validation');
1039
+ expect(result).toBeDefined();
1040
+ });
1041
+ });
1042
+ // ---------------------------------------------------------------------------
1043
+ // openapi-response-coverage — broader shapes
1044
+ // ---------------------------------------------------------------------------
1045
+ // ---------------------------------------------------------------------------
1046
+ // fastify-schema-coverage — broader scenarios
1047
+ // ---------------------------------------------------------------------------
1048
+ describe('fastify-schema-coverage — additional branches', () => {
1049
+ it('routes with full/partial schemas', async () => {
1050
+ fx('src/routes/r.ts', [
1051
+ 'export const reg = (app: any) => {',
1052
+ ' app.post("/a", { schema: { body: {}, response: { 200: {}, 400: {} } } }, async () => ({}))',
1053
+ ' app.get("/b", { schema: { response: { 200: {} } } }, async () => ({}))',
1054
+ ' app.post("/c", { schema: { body: {} } }, async () => ({}))',
1055
+ ' app.put("/d", async () => ({}))',
1056
+ '}',
1057
+ ].join('\n'));
1058
+ const result = await runCheck('fastify-schema-coverage');
1059
+ expect(result).toBeDefined();
1060
+ });
1061
+ });
1062
+ // ---------------------------------------------------------------------------
1063
+ // dynamodb-scan-detection
1064
+ // ---------------------------------------------------------------------------
1065
+ // ---------------------------------------------------------------------------
1066
+ // no-hardcoded-correlation-id
1067
+ // ---------------------------------------------------------------------------
1068
+ describe('no-hardcoded-correlation-id — additional branches', () => {
1069
+ it('hardcoded vs generated', async () => {
1070
+ fx('src/svc/ci.ts', [
1071
+ 'export function bad() { return "00000000-0000-0000-0000-000000000000" }',
1072
+ 'export function bad2() { return { correlationId: "fixed-id-123" } }',
1073
+ 'export function good() { return crypto.randomUUID() }',
1074
+ 'export function good2() { return generateCorrelationId() }',
1075
+ ].join('\n'));
1076
+ const result = await runCheck('no-hardcoded-correlation-id');
1077
+ expect(result).toBeDefined();
1078
+ });
1079
+ });
1080
+ // ---------------------------------------------------------------------------
1081
+ // context-mutation
1082
+ // ---------------------------------------------------------------------------
1083
+ describe('context-mutation — additional branches', () => {
1084
+ it('mutation vs read-only context access', async () => {
1085
+ fx('src/svc/cm.ts', [
1086
+ 'export function f1(ctx: any) {',
1087
+ ' ctx.user = "x"', // mutation
1088
+ ' ctx.tags.push("a")', // mutation
1089
+ ' return ctx',
1090
+ '}',
1091
+ 'export function f2(ctx: any) {',
1092
+ ' const { user } = ctx', // read
1093
+ ' return user',
1094
+ '}',
1095
+ ].join('\n'));
1096
+ const result = await runCheck('context-mutation');
1097
+ expect(result).toBeDefined();
1098
+ });
1099
+ });
1100
+ // ---------------------------------------------------------------------------
1101
+ // test-only-implementations
1102
+ // ---------------------------------------------------------------------------
1103
+ // ---------------------------------------------------------------------------
1104
+ // openapi-type-source — branches
1105
+ // ---------------------------------------------------------------------------
1106
+ // ---------------------------------------------------------------------------
1107
+ // frontend-client-boundary-placement — additional branches
1108
+ // ---------------------------------------------------------------------------
1109
+ // ---------------------------------------------------------------------------
1110
+ // a11y-form-labels / a11y-semantic-html / accessible-touchables
1111
+ // ---------------------------------------------------------------------------
1112
+ describe('a11y-form-labels — additional branches', () => {
1113
+ it('labeled and unlabeled inputs', async () => {
1114
+ fx('src/c/F.tsx', [
1115
+ 'export function A() {',
1116
+ ' return (<form>',
1117
+ ' <label htmlFor="email">Email</label><input id="email" type="email" />',
1118
+ ' <input type="text" />',
1119
+ ' <input aria-label="Search" type="search" />',
1120
+ ' <input aria-labelledby="lbl" type="text" />',
1121
+ ' <button type="submit">Send</button>',
1122
+ ' </form>)',
1123
+ '}',
1124
+ ].join('\n'));
1125
+ const result = await runCheck('a11y-form-labels');
1126
+ expect(result).toBeDefined();
1127
+ });
1128
+ });
1129
+ describe('a11y-semantic-html — additional branches', () => {
1130
+ it('semantic vs div/span', async () => {
1131
+ fx('src/c/H.tsx', [
1132
+ 'export function A() {',
1133
+ ' return (<div>',
1134
+ ' <div onClick={() => null}>tap</div>',
1135
+ ' <span style={{ cursor: "pointer" }}>also tappable</span>',
1136
+ ' <button onClick={() => null}>OK</button>',
1137
+ ' <header><nav>...</nav></header>',
1138
+ ' <main><article><section>x</section></article></main>',
1139
+ ' </div>)',
1140
+ '}',
1141
+ ].join('\n'));
1142
+ const result = await runCheck('a11y-semantic-html');
1143
+ expect(result).toBeDefined();
1144
+ });
1145
+ });
1146
+ // ---------------------------------------------------------------------------
1147
+ // in-memory-repository-detection — additional shapes
1148
+ // ---------------------------------------------------------------------------
1149
+ describe('in-memory-repository-detection — additional branches', () => {
1150
+ it('multi-storage with class containing UserRepository', async () => {
1151
+ fx('src/r/Reps.ts', [
1152
+ 'export class UserRepository {',
1153
+ ' private byMap = new Map<string, number>()',
1154
+ ' private bySet = new Set<string>()',
1155
+ ' private byArray: { id: string }[] = []',
1156
+ ' private byObject: Record<string, unknown> = {}',
1157
+ ' async listAll() { return [...this.byMap.values()] }',
1158
+ '}',
1159
+ '// UserRepository',
1160
+ ].join('\n'));
1161
+ const result = await runCheck('in-memory-repository-detection');
1162
+ expect(result).toBeDefined();
1163
+ });
1164
+ it('skip when path contains InMemory or Mock or Cache', async () => {
1165
+ fx('src/r/InMemory.ts', ['export class InMemoryRepository {', ' private data = new Map()', '}'].join('\n'));
1166
+ fx('src/r/Mock.ts', ['export class MockUserRepository {', ' private data = new Map()', '}'].join('\n'));
1167
+ const result = await runCheck('in-memory-repository-detection');
1168
+ expect(result).toBeDefined();
1169
+ });
1170
+ });
1171
+ // ---------------------------------------------------------------------------
1172
+ // financial-transaction-ordering — additional shapes
1173
+ // ---------------------------------------------------------------------------
1174
+ // ---------------------------------------------------------------------------
1175
+ // database-index-coverage / database-schema-validation
1176
+ // ---------------------------------------------------------------------------
1177
+ describe('database-index-coverage — additional branches', () => {
1178
+ it('drizzle table with composite index, full-text index, no index', async () => {
1179
+ fx('src/db/s/users.ts', [
1180
+ 'import { pgTable, serial, text, varchar, timestamp, integer, index, uniqueIndex } from "drizzle-orm/pg-core"',
1181
+ 'export const users = pgTable("users", {',
1182
+ ' id: serial("id").primaryKey(),',
1183
+ ' email: varchar("email", { length: 255 }).notNull(),',
1184
+ ' tenantId: integer("tenant_id").notNull(),',
1185
+ ' createdAt: timestamp("created_at").defaultNow().notNull(),',
1186
+ '}, (t) => ({',
1187
+ ' emailIdx: uniqueIndex("email_idx").on(t.email),',
1188
+ ' tenantIdx: index("tenant_idx").on(t.tenantId),',
1189
+ ' composite: index("comp_idx").on(t.tenantId, t.createdAt),',
1190
+ '}))',
1191
+ 'export const noIdx = pgTable("noidx", {',
1192
+ ' id: serial("id").primaryKey(),',
1193
+ ' status: text("status"),',
1194
+ '})',
1195
+ ].join('\n'));
1196
+ const result = await runCheck('database-index-coverage');
1197
+ expect(result).toBeDefined();
1198
+ });
1199
+ });
1200
+ describe('database-schema-validation — additional branches', () => {
1201
+ it('table with various column shapes and constraints', async () => {
1202
+ fx('src/db/s/all.ts', [
1203
+ 'import { pgTable, serial, text, varchar, integer, boolean, timestamp, json, jsonb, uuid, real } from "drizzle-orm/pg-core"',
1204
+ 'export const t = pgTable("t", {',
1205
+ ' id: serial("id").primaryKey(),',
1206
+ ' uuid: uuid("uuid").defaultRandom().notNull(),',
1207
+ ' name: text("name").notNull(),',
1208
+ ' email: varchar("email", { length: 255 }).notNull().unique(),',
1209
+ ' age: integer("age"),',
1210
+ ' active: boolean("active").default(true).notNull(),',
1211
+ ' meta: jsonb("meta").$type<{ x: string }>().notNull().default({}),',
1212
+ ' meta2: json("meta2"),',
1213
+ ' amount: real("amount"),',
1214
+ ' createdAt: timestamp("created_at").defaultNow().notNull(),',
1215
+ '})',
1216
+ ].join('\n'));
1217
+ const result = await runCheck('database-schema-validation');
1218
+ expect(result).toBeDefined();
1219
+ });
1220
+ });
1221
+ // ---------------------------------------------------------------------------
1222
+ // postgres-n-plus-one — additional patterns
1223
+ // ---------------------------------------------------------------------------
1224
+ // ---------------------------------------------------------------------------
1225
+ // typeorm-n-plus-one — additional patterns
1226
+ // ---------------------------------------------------------------------------
1227
+ // ---------------------------------------------------------------------------
1228
+ // sql-injection — additional patterns
1229
+ // ---------------------------------------------------------------------------
1230
+ describe('sql-injection — additional branches', () => {
1231
+ it('various injection and safe patterns', async () => {
1232
+ fx('src/db/s.ts', [
1233
+ 'export async function f1(id: string) { return db.query(`SELECT * FROM x WHERE id = ${id}`) }',
1234
+ 'export async function f2(id: string) { return db.query("SELECT * FROM x WHERE id = $1", [id]) }',
1235
+ 'export async function f3(name: string) {',
1236
+ ' const sql = "SELECT * FROM x WHERE name = \'" + name + "\'"',
1237
+ ' return db.query(sql)',
1238
+ '}',
1239
+ 'export async function f4(name: string) {',
1240
+ ' return db.prepare("SELECT * FROM x WHERE name = ?").execute([name])',
1241
+ '}',
1242
+ 'export async function f5() {',
1243
+ ' // Static string, no injection',
1244
+ ' return db.query("SELECT * FROM x")',
1245
+ '}',
1246
+ 'export async function f6(id: string) {',
1247
+ ' return raw(`SELECT * FROM ${id}`)', // raw helper, also dangerous',
1248
+ '}',
1249
+ ].join('\n'));
1250
+ const result = await runCheck('sql-injection');
1251
+ expect(result).toBeDefined();
1252
+ });
1253
+ });
1254
+ // ---------------------------------------------------------------------------
1255
+ // input-sanitization — additional patterns
1256
+ // ---------------------------------------------------------------------------
1257
+ describe('input-sanitization — additional branches', () => {
1258
+ it('various sources of user input and sinks', async () => {
1259
+ fx('src/api/risk.ts', [
1260
+ 'import { exec, execSync, spawn } from "child_process"',
1261
+ 'import * as fs from "fs"',
1262
+ 'import * as path from "path"',
1263
+ 'export function f1(req: any) { return fs.readFileSync(path.join("/etc", req.body.file)) }',
1264
+ 'export function f2(req: any) { return fs.readFileSync(req.body.file) }', // direct
1265
+ 'export function f3(req: any) { return exec("ls " + req.body.dir) }',
1266
+ 'export function f4(req: any) { return execSync(`grep ${req.body.pattern} log.txt`) }',
1267
+ 'export function f5(req: any) { return spawn("git", ["log", "--", req.body.path]) }',
1268
+ 'export function f6(req: any) {',
1269
+ ' return `<div dangerous>${req.body.html}</div>`',
1270
+ '}',
1271
+ 'export function f7(req: any) {',
1272
+ ' return `<a href="${req.body.url}">click</a>`',
1273
+ '}',
1274
+ 'export function f8(safe: string) {',
1275
+ ' return fs.readFileSync(path.resolve("/etc/hosts"))',
1276
+ '}',
1277
+ ].join('\n'));
1278
+ const result = await runCheck('input-sanitization');
1279
+ expect(result).toBeDefined();
1280
+ });
1281
+ });
1282
+ // ---------------------------------------------------------------------------
1283
+ // unsafe-secret-comparison — additional patterns
1284
+ // ---------------------------------------------------------------------------
1285
+ describe('unsafe-secret-comparison — additional branches', () => {
1286
+ it('various comparison patterns', async () => {
1287
+ fx('src/auth/u.ts', [
1288
+ 'import { timingSafeEqual } from "crypto"',
1289
+ 'export function f1(secret: string, token: string) { return secret === token }',
1290
+ 'export function f2(secret: string, token: string) { return secret == token }',
1291
+ 'export function f3(a: Buffer, b: Buffer) { return a.equals(b) }',
1292
+ 'export function f4(secret: string, token: string) {',
1293
+ ' if (secret.length !== token.length) return false',
1294
+ ' return timingSafeEqual(Buffer.from(secret), Buffer.from(token))',
1295
+ '}',
1296
+ 'export function f5(apiKey: string, expected: string) { return apiKey === expected }',
1297
+ 'export function f6(password: string, hash: string) { return password === hash }',
1298
+ 'export function f7(unrelated: number, other: number) { return unrelated === other }',
1299
+ ].join('\n'));
1300
+ const result = await runCheck('unsafe-secret-comparison');
1301
+ expect(result).toBeDefined();
1302
+ });
1303
+ });
1304
+ // ---------------------------------------------------------------------------
1305
+ // no-any-types — additional patterns
1306
+ // ---------------------------------------------------------------------------
1307
+ describe('no-any-types — additional branches', () => {
1308
+ it('various any forms', async () => {
1309
+ fx('src/t/a.ts', [
1310
+ 'export const a: any = {}',
1311
+ 'export function f1(x: any) { return x }',
1312
+ 'export function f2(): any { return null }',
1313
+ 'export const arr: any[] = []',
1314
+ 'export const map: { [k: string]: any } = {}',
1315
+ 'export const m2: Record<string, any> = {}',
1316
+ 'export const cast = (x: unknown) => x as any',
1317
+ 'export type T<X = any> = X',
1318
+ 'export interface I { x: any }',
1319
+ 'export class C { v: any = null }',
1320
+ ].join('\n'));
1321
+ const result = await runCheck('no-any-types');
1322
+ expect(result).toBeDefined();
1323
+ });
1324
+ });
1325
+ // ---------------------------------------------------------------------------
1326
+ // result-pattern-consistency — additional branches
1327
+ // ---------------------------------------------------------------------------
1328
+ describe('result-pattern-consistency — additional branches', () => {
1329
+ it('Result vs throw mixing', async () => {
1330
+ fx('src/svc/r.ts', [
1331
+ 'type Ok<T> = { ok: true; value: T }',
1332
+ 'type Err<E> = { ok: false; error: E }',
1333
+ 'type Result<T, E> = Ok<T> | Err<E>',
1334
+ 'export function ok<T>(v: T): Ok<T> { return { ok: true, value: v } }',
1335
+ 'export function err<E>(e: E): Err<E> { return { ok: false, error: e } }',
1336
+ 'export function viaResult(): Result<number, string> { return ok(1) }',
1337
+ 'export function viaThrow() { throw new Error("oops") }',
1338
+ 'export function bothPatterns(x: number) {',
1339
+ ' if (x < 0) return err("neg")',
1340
+ ' if (x === 0) throw new Error("zero")',
1341
+ ' return ok(x)',
1342
+ '}',
1343
+ 'export function caughtRethrow() {',
1344
+ ' try { return ok(1) }',
1345
+ ' catch (e) { throw e }',
1346
+ '}',
1347
+ 'export function legitimateThrow() {',
1348
+ ' throw new ValidationError("bad")',
1349
+ '}',
1350
+ 'export function isValidator(): boolean {',
1351
+ ' if (!Number.isFinite(1)) throw new Error("not finite")',
1352
+ ' return true',
1353
+ '}',
1354
+ ].join('\n'));
1355
+ const result = await runCheck('result-pattern-consistency');
1356
+ expect(result).toBeDefined();
1357
+ });
1358
+ it('throws in registry / store / adapter paths (allowed)', async () => {
1359
+ fx('src/registry/x.ts', 'export function f() { throw new Error("ok") }');
1360
+ fx('src/store/x.ts', 'export function f() { throw new Error("ok") }');
1361
+ fx('src/adapter/x.ts', 'export function f() { throw new Error("ok") }');
1362
+ fx('src/x-registry.ts', 'export function f() { throw new Error("ok") }');
1363
+ fx('src/x-adapter.ts', 'export function f() { throw new Error("ok") }');
1364
+ fx('src/x-store.ts', 'export function f() { throw new Error("ok") }');
1365
+ const result = await runCheck('result-pattern-consistency');
1366
+ expect(result).toBeDefined();
1367
+ });
1368
+ });
1369
+ //# sourceMappingURL=branch-fixtures-2.test.js.map