@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,658 @@
1
+ // @fitness-ignore-file file-length-limit -- behavior fixture suite; related scenarios stay together while checks are split into focused tests.
2
+ /**
3
+ * @fileoverview Targeted behavior tests for resilience and remaining
4
+ * mid-tier checks (context-leakage, async patterns, throws-documentation,
5
+ * dispose-pattern-completeness, openapi-type-source, etc.).
6
+ */
7
+ import { mkdirSync, mkdtempSync, rmSync, writeFileSync } from 'node:fs';
8
+ import { tmpdir } from 'node:os';
9
+ import { dirname, join } from 'node:path';
10
+ import { LanguageRegistry, RunScope, runWithScope } from '@opensip-cli/core';
11
+ import { fileCache } from '@opensip-cli/fitness';
12
+ import { typescriptAdapter } from '@opensip-cli/lang-typescript';
13
+ import { afterEach, beforeEach, describe, expect, it } from 'vitest';
14
+ import { checks } from '../index.js';
15
+ // Production simulation: register the TS adapter (see behavior-fixtures.test.ts).
16
+ const langRegistry = new LanguageRegistry();
17
+ langRegistry.register(typescriptAdapter);
18
+ const testScope = new RunScope({ languages: langRegistry });
19
+ let cwd;
20
+ let written = [];
21
+ function fx(rel, content) {
22
+ const abs = join(cwd, rel);
23
+ mkdirSync(dirname(abs), { recursive: true });
24
+ writeFileSync(abs, content);
25
+ written.push(abs);
26
+ return abs;
27
+ }
28
+ function findCheck(slug) {
29
+ const c = checks.find((x) => x.config.slug === slug);
30
+ if (!c)
31
+ throw new Error(`check not found: ${slug}`);
32
+ return c;
33
+ }
34
+ async function runCheck(slug) {
35
+ const check = findCheck(slug);
36
+ await fileCache.prewarm(cwd, ['**/*']);
37
+ return runWithScope(testScope, () => check.run(cwd, { targetFiles: written }));
38
+ }
39
+ beforeEach(() => {
40
+ cwd = mkdtempSync(join(tmpdir(), 'opensip-cov3-'));
41
+ written = [];
42
+ });
43
+ afterEach(() => {
44
+ fileCache.clear();
45
+ rmSync(cwd, { recursive: true, force: true });
46
+ });
47
+ // ---------------------------------------------------------------------------
48
+ // context-leakage (resilience/context-leakage)
49
+ // ---------------------------------------------------------------------------
50
+ describe('context-leakage — branch coverage', () => {
51
+ it('flags module-level let with a *Context type', async () => {
52
+ fx('src/svc/leak.ts', [
53
+ 'declare class RequestContext {}',
54
+ 'export let activeContext: RequestContext | null = null',
55
+ 'export function setCtx(c: RequestContext) { activeContext = c }',
56
+ ].join('\n'));
57
+ const result = await runCheck('context-leakage');
58
+ expect(result.signals.length).toBeGreaterThanOrEqual(1);
59
+ });
60
+ it('flags module-level var with a *Ctx type', async () => {
61
+ fx('src/svc/leak2.ts', ['declare class TenantCtx {}', 'export var currentCtx: TenantCtx | null = null'].join('\n'));
62
+ const result = await runCheck('context-leakage');
63
+ expect(result.signals.length).toBeGreaterThanOrEqual(1);
64
+ });
65
+ it('skips const declarations (cannot be reassigned)', async () => {
66
+ fx('src/svc/safe-const.ts', [
67
+ 'declare class RequestContext {}',
68
+ 'export const fixedContext: RequestContext | null = null',
69
+ ].join('\n'));
70
+ const result = await runCheck('context-leakage');
71
+ expect(result.signals).toHaveLength(0);
72
+ });
73
+ it('skips AsyncLocalStorage-typed declarations', async () => {
74
+ fx('src/svc/als.ts', [
75
+ 'import { AsyncLocalStorage } from "async_hooks"',
76
+ 'export let store: AsyncLocalStorage<unknown> = new AsyncLocalStorage()',
77
+ ].join('\n'));
78
+ const result = await runCheck('context-leakage');
79
+ expect(result.signals).toHaveLength(0);
80
+ });
81
+ it('skips OTel metric instrument lazy-init shape', async () => {
82
+ fx('src/svc/metrics.ts', [
83
+ 'declare class Counter {}',
84
+ 'declare class Histogram {}',
85
+ 'export let counter: Counter | null = null',
86
+ 'export let hist: Histogram | null = null',
87
+ ].join('\n'));
88
+ const result = await runCheck('context-leakage');
89
+ expect(result.signals).toHaveLength(0);
90
+ });
91
+ it('skips wrapper generic types like Injector<Context>', async () => {
92
+ fx('src/svc/wrapper.ts', [
93
+ 'declare class Injector<T> {}',
94
+ 'declare class AppContext {}',
95
+ 'export let inj: Injector<AppContext> | null = null',
96
+ ].join('\n'));
97
+ const result = await runCheck('context-leakage');
98
+ // Injector<...> outer type is in PROCESS_SCOPED_WRAPPER_TYPES → not flagged.
99
+ expect(result.signals).toHaveLength(0);
100
+ });
101
+ it('flags class field with Context type when class is request-scoped (has tenantId param)', async () => {
102
+ fx('src/svc/cls-leak.ts', [
103
+ 'declare class RequestContext {}',
104
+ 'export class Handler {',
105
+ ' private ctx: RequestContext | null = null',
106
+ ' serve(tenantId: string) { return tenantId }',
107
+ '}',
108
+ ].join('\n'));
109
+ const result = await runCheck('context-leakage');
110
+ expect(result.signals.length).toBeGreaterThanOrEqual(1);
111
+ });
112
+ it('flags class field when class has requestId or correlationId field', async () => {
113
+ fx('src/svc/cls-id.ts', [
114
+ 'declare class TenantContext {}',
115
+ 'export class Handler {',
116
+ ' requestId = ""',
117
+ ' private state: TenantContext | null = null',
118
+ '}',
119
+ ].join('\n'));
120
+ const result = await runCheck('context-leakage');
121
+ expect(result.signals.length).toBeGreaterThanOrEqual(1);
122
+ });
123
+ it('does not flag readonly or static class properties', async () => {
124
+ fx('src/svc/readonly.ts', [
125
+ 'declare class RequestContext {}',
126
+ 'export class Handler {',
127
+ ' serve(tenantId: string) { return tenantId }',
128
+ ' readonly ctx: RequestContext | null = null',
129
+ ' static defaultCtx: RequestContext | null = null',
130
+ '}',
131
+ ].join('\n'));
132
+ const result = await runCheck('context-leakage');
133
+ expect(result.signals).toHaveLength(0);
134
+ });
135
+ it('skips DBOS step classes via decorator detection', async () => {
136
+ fx('src/svc/dbos.ts', [
137
+ 'declare const DBOS: { step: () => MethodDecorator; workflow: () => MethodDecorator }',
138
+ 'declare class RequestContext {}',
139
+ 'export class StepHost {',
140
+ ' private ctx: RequestContext | null = null',
141
+ ' @DBOS.step()',
142
+ ' run(tenantId: string) { return tenantId }',
143
+ '}',
144
+ ].join('\n'));
145
+ const result = await runCheck('context-leakage');
146
+ // DBOS step host is skipped.
147
+ expect(result.signals).toHaveLength(0);
148
+ });
149
+ it('skips files under dbos/steps/ paths', async () => {
150
+ fx('src/dbos/steps/runner.ts', ['declare class RequestContext {}', 'export let active: RequestContext | null = null'].join('\n'));
151
+ const result = await runCheck('context-leakage');
152
+ expect(result.signals).toHaveLength(0);
153
+ });
154
+ it('skips test files', async () => {
155
+ fx('src/svc/foo.test.ts', [
156
+ 'declare class RequestContext {}',
157
+ 'export let activeContext: RequestContext | null = null',
158
+ ].join('\n'));
159
+ const result = await runCheck('context-leakage');
160
+ expect(result.signals).toHaveLength(0);
161
+ });
162
+ it('quick-bails on files without "context" or "ctx" substring', async () => {
163
+ fx('src/svc/no-ctx.ts', 'export const x = 1');
164
+ const result = await runCheck('context-leakage');
165
+ expect(result.signals).toHaveLength(0);
166
+ });
167
+ });
168
+ // ---------------------------------------------------------------------------
169
+ // detached-promises (resilience/detached-promises)
170
+ // ---------------------------------------------------------------------------
171
+ describe('detached-promises — branch coverage', () => {
172
+ it('flags fire-and-forget Promise calls in async context', async () => {
173
+ fx('src/async/detached.ts', [
174
+ 'declare function expensiveTask(): Promise<void>',
175
+ 'export async function f() {',
176
+ ' expensiveTask()', // missing await
177
+ ' await Promise.resolve()',
178
+ '}',
179
+ ].join('\n'));
180
+ const result = await runCheck('detached-promises');
181
+ expect(result).toBeDefined();
182
+ });
183
+ it('skips Promise calls with .catch() handler', async () => {
184
+ fx('src/async/handled.ts', [
185
+ 'declare function task(): Promise<void>',
186
+ 'export async function f() {',
187
+ ' task().catch(() => {})',
188
+ '}',
189
+ ].join('\n'));
190
+ const result = await runCheck('detached-promises');
191
+ expect(result).toBeDefined();
192
+ });
193
+ it('skips known sync calls (e.g. console.log, .push, .set)', async () => {
194
+ fx('src/async/sync.ts', [
195
+ 'export async function f() {',
196
+ ' console.log("hi")',
197
+ ' const arr: number[] = []',
198
+ ' arr.push(1)',
199
+ ' const map = new Map<string, number>()',
200
+ ' map.set("a", 1)',
201
+ '}',
202
+ ].join('\n'));
203
+ const result = await runCheck('detached-promises');
204
+ expect(result.signals).toHaveLength(0);
205
+ });
206
+ it('skips calls outside async context', async () => {
207
+ fx('src/async/sync-fn.ts', [
208
+ 'declare function task(): Promise<void>',
209
+ 'export function nonAsync() {',
210
+ ' task()',
211
+ '}',
212
+ ].join('\n'));
213
+ const result = await runCheck('detached-promises');
214
+ expect(result).toBeDefined();
215
+ });
216
+ });
217
+ // ---------------------------------------------------------------------------
218
+ // no-unbounded-concurrency (resilience/no-unbounded-concurrency)
219
+ // ---------------------------------------------------------------------------
220
+ describe('no-unbounded-concurrency — branch coverage', () => {
221
+ it('flags Promise.all over an unbounded array', async () => {
222
+ fx('src/async/parallel.ts', [
223
+ 'declare function loadOne(id: number): Promise<unknown>',
224
+ 'export async function loadAll(ids: number[]) {',
225
+ ' return await Promise.all(ids.map(loadOne))',
226
+ '}',
227
+ ].join('\n'));
228
+ const result = await runCheck('no-unbounded-concurrency');
229
+ expect(result).toBeDefined();
230
+ });
231
+ it('skips files using bounded concurrency primitives (p-limit, etc.)', async () => {
232
+ fx('src/async/bounded.ts', [
233
+ 'import pLimit from "p-limit"',
234
+ 'declare function loadOne(id: number): Promise<unknown>',
235
+ 'const limit = pLimit(5)',
236
+ 'export async function loadAll(ids: number[]) {',
237
+ ' return await Promise.all(ids.map((id) => limit(() => loadOne(id))))',
238
+ '}',
239
+ ].join('\n'));
240
+ const result = await runCheck('no-unbounded-concurrency');
241
+ expect(result.signals).toHaveLength(0);
242
+ });
243
+ });
244
+ // ---------------------------------------------------------------------------
245
+ // no-raw-fetch
246
+ // ---------------------------------------------------------------------------
247
+ describe('no-raw-fetch — branch coverage', () => {
248
+ it('flags raw fetch() calls', async () => {
249
+ fx('src/api/raw.ts', ['export async function f() {', ' return fetch("/api/x")', '}'].join('\n'));
250
+ const result = await runCheck('no-raw-fetch');
251
+ expect(result).toBeDefined();
252
+ });
253
+ it('skips files inside test directories', async () => {
254
+ fx('src/__tests__/raw.test.ts', ['export async function f() {', ' return fetch("/api/x")', '}'].join('\n'));
255
+ const result = await runCheck('no-raw-fetch');
256
+ expect(result).toBeDefined();
257
+ });
258
+ });
259
+ // ---------------------------------------------------------------------------
260
+ // await-result-unwrap
261
+ // ---------------------------------------------------------------------------
262
+ // ---------------------------------------------------------------------------
263
+ // throws-documentation
264
+ // ---------------------------------------------------------------------------
265
+ describe('throws-documentation — extra branch coverage', () => {
266
+ it('handles arrow functions and methods that throw', async () => {
267
+ fx('src/throws/arrow.ts', [
268
+ 'export const validateA = (x: string): string => {',
269
+ ' if (!x) throw new Error("empty")',
270
+ ' return x',
271
+ '}',
272
+ 'export class C {',
273
+ ' validate(x: string): string {',
274
+ ' if (!x) throw new Error("empty")',
275
+ ' return x',
276
+ ' }',
277
+ '}',
278
+ ].join('\n'));
279
+ const result = await runCheck('throws-documentation');
280
+ expect(result).toBeDefined();
281
+ });
282
+ it('skips functions that re-throw (catch + throw)', async () => {
283
+ fx('src/throws/rethrow.ts', ['export function f() {', ' try { return 1 } catch (e) { throw e }', '}'].join('\n'));
284
+ const result = await runCheck('throws-documentation');
285
+ expect(result).toBeDefined();
286
+ });
287
+ it('skips test files', async () => {
288
+ fx('src/throws/foo.test.ts', ['export function f() { throw new Error("test") }'].join('\n'));
289
+ const result = await runCheck('throws-documentation');
290
+ expect(result).toBeDefined();
291
+ });
292
+ });
293
+ // ---------------------------------------------------------------------------
294
+ // dispose-pattern-completeness
295
+ // ---------------------------------------------------------------------------
296
+ describe('dispose-pattern-completeness — branch coverage', () => {
297
+ it('flags dispose() bodies that do not clean up subscriptions/intervals', async () => {
298
+ fx('src/lifecycle/dispose.ts', [
299
+ 'export interface IDisposable { dispose(): void }',
300
+ 'export class Holder implements IDisposable {',
301
+ ' private interval = setInterval(() => undefined, 1000)',
302
+ ' private sub = { unsubscribe() {} }',
303
+ ' dispose(): void {}', // empty - does not clear interval or unsubscribe
304
+ '}',
305
+ ].join('\n'));
306
+ const result = await runCheck('dispose-pattern-completeness');
307
+ expect(result).toBeDefined();
308
+ });
309
+ it('does not flag dispose() that cleans up everything', async () => {
310
+ fx('src/lifecycle/dispose-clean.ts', [
311
+ 'export interface IDisposable { dispose(): void }',
312
+ 'export class Holder implements IDisposable {',
313
+ ' private interval: NodeJS.Timeout | null = null',
314
+ ' private sub = { unsubscribe() {} }',
315
+ ' dispose(): void {',
316
+ ' if (this.interval) clearInterval(this.interval)',
317
+ ' this.sub.unsubscribe()',
318
+ ' }',
319
+ '}',
320
+ ].join('\n'));
321
+ const result = await runCheck('dispose-pattern-completeness');
322
+ expect(result).toBeDefined();
323
+ });
324
+ it('handles classes without IDisposable interface', async () => {
325
+ fx('src/lifecycle/no-disposable.ts', ['export class Plain {', ' start() { return 1 }', '}'].join('\n'));
326
+ const result = await runCheck('dispose-pattern-completeness');
327
+ expect(result).toBeDefined();
328
+ });
329
+ });
330
+ // ---------------------------------------------------------------------------
331
+ // openapi-type-source
332
+ // ---------------------------------------------------------------------------
333
+ // ---------------------------------------------------------------------------
334
+ // drizzle-orm-migration-guardrails
335
+ // ---------------------------------------------------------------------------
336
+ describe('drizzle-orm-migration-guardrails — branch coverage', () => {
337
+ it('runs over drizzle migration files with risky DDL', async () => {
338
+ fx('src/db/migrations/001_drop_col.ts', [
339
+ 'import { sql } from "drizzle-orm"',
340
+ 'export const up = sql`ALTER TABLE users DROP COLUMN email`',
341
+ 'export const down = sql`ALTER TABLE users ADD COLUMN email VARCHAR(255)`',
342
+ ].join('\n'));
343
+ const result = await runCheck('drizzle-orm-migration-guardrails');
344
+ expect(result).toBeDefined();
345
+ });
346
+ it('runs over safe DDL (CREATE TABLE / ADD COLUMN)', async () => {
347
+ fx('src/db/migrations/002_create.ts', [
348
+ 'import { sql } from "drizzle-orm"',
349
+ 'export const up = sql`CREATE TABLE users (id SERIAL PRIMARY KEY)`',
350
+ ].join('\n'));
351
+ const result = await runCheck('drizzle-orm-migration-guardrails');
352
+ expect(result).toBeDefined();
353
+ });
354
+ });
355
+ // ---------------------------------------------------------------------------
356
+ // silent-early-returns
357
+ // ---------------------------------------------------------------------------
358
+ describe('silent-early-returns — extra branch coverage', () => {
359
+ it('flags return null/false/undefined as guard clauses', async () => {
360
+ fx('src/handlers/silent.ts', [
361
+ 'export function fetchUser(id: string) {',
362
+ ' if (!id) return null',
363
+ ' if (id.length > 100) return false',
364
+ ' return { id }',
365
+ '}',
366
+ ].join('\n'));
367
+ const result = await runCheck('silent-early-returns');
368
+ expect(result).toBeDefined();
369
+ });
370
+ it('skips returns inside .map() / .filter() predicate callbacks', async () => {
371
+ fx('src/handlers/predicate.ts', [
372
+ 'export function f(arr: number[]) {',
373
+ ' return arr.map((x) => {',
374
+ ' if (x < 0) return null',
375
+ ' return x * 2',
376
+ ' })',
377
+ '}',
378
+ ].join('\n'));
379
+ const result = await runCheck('silent-early-returns');
380
+ expect(result).toBeDefined();
381
+ });
382
+ it('skips functions named with "validate"/"is"/"check" prefixes', async () => {
383
+ fx('src/handlers/validators.ts', [
384
+ 'export function isValid(x: number): boolean {',
385
+ ' if (!x) return false',
386
+ ' return true',
387
+ '}',
388
+ 'export function checkInput(s: string): boolean {',
389
+ ' if (!s) return false',
390
+ ' return true',
391
+ '}',
392
+ ].join('\n'));
393
+ const result = await runCheck('silent-early-returns');
394
+ expect(result).toBeDefined();
395
+ });
396
+ });
397
+ // ---------------------------------------------------------------------------
398
+ // stream-buffer-size-limits
399
+ // ---------------------------------------------------------------------------
400
+ describe('stream-buffer-size-limits — branch coverage', () => {
401
+ it('flags unbounded chunk accumulation', async () => {
402
+ fx('src/streams/unbounded.ts', [
403
+ 'export async function readAll(stream: AsyncIterable<Buffer>) {',
404
+ ' const chunks: Buffer[] = []',
405
+ ' for await (const chunk of stream) {',
406
+ ' chunks.push(chunk)',
407
+ ' }',
408
+ ' return Buffer.concat(chunks)',
409
+ '}',
410
+ ].join('\n'));
411
+ const result = await runCheck('stream-buffer-size-limits');
412
+ expect(result).toBeDefined();
413
+ });
414
+ it('skips files without stream-related patterns', async () => {
415
+ fx('src/streams/none.ts', 'export const x = 1');
416
+ const result = await runCheck('stream-buffer-size-limits');
417
+ expect(result).toBeDefined();
418
+ });
419
+ });
420
+ // ---------------------------------------------------------------------------
421
+ // toctou-race-condition
422
+ // ---------------------------------------------------------------------------
423
+ describe('toctou-race-condition — branch coverage', () => {
424
+ it('flags read-modify-write on a shared Map / Set', async () => {
425
+ fx('src/cache/toctou.ts', [
426
+ 'export class Counter {',
427
+ ' private state = new Map<string, number>()',
428
+ ' increment(key: string) {',
429
+ ' const v = this.state.get(key) ?? 0',
430
+ ' this.state.set(key, v + 1)',
431
+ ' }',
432
+ '}',
433
+ ].join('\n'));
434
+ const result = await runCheck('toctou-race-condition');
435
+ expect(result).toBeDefined();
436
+ });
437
+ it('skips atomic operations and immediate increments', async () => {
438
+ fx('src/cache/atomic.ts', [
439
+ 'export class Plain {',
440
+ ' private values: number[] = []',
441
+ ' add(v: number) { this.values.push(v) }',
442
+ '}',
443
+ ].join('\n'));
444
+ const result = await runCheck('toctou-race-condition');
445
+ expect(result).toBeDefined();
446
+ });
447
+ });
448
+ // ---------------------------------------------------------------------------
449
+ // array-validation
450
+ // ---------------------------------------------------------------------------
451
+ describe('array-validation — branch coverage', () => {
452
+ it('flags array parameters without length validation', async () => {
453
+ fx('src/util/arr.ts', [
454
+ 'export function processItems(items: string[]): number {',
455
+ ' return items.length + (items[0]?.length ?? 0)',
456
+ '}',
457
+ ].join('\n'));
458
+ const result = await runCheck('array-validation');
459
+ expect(result).toBeDefined();
460
+ });
461
+ it('skips functions that already validate array length', async () => {
462
+ fx('src/util/arr-safe.ts', [
463
+ 'export function processItems(items: string[]): number {',
464
+ ' if (!Array.isArray(items)) throw new Error("not array")',
465
+ ' if (items.length === 0) return 0',
466
+ ' return items.length',
467
+ '}',
468
+ ].join('\n'));
469
+ const result = await runCheck('array-validation');
470
+ expect(result).toBeDefined();
471
+ });
472
+ });
473
+ // ---------------------------------------------------------------------------
474
+ // financial-transaction-ordering
475
+ // ---------------------------------------------------------------------------
476
+ // ---------------------------------------------------------------------------
477
+ // database-index-coverage
478
+ // ---------------------------------------------------------------------------
479
+ describe('database-index-coverage — branch coverage', () => {
480
+ it('flags broad SELECT * queries', async () => {
481
+ fx('src/repos/wide.ts', [
482
+ 'declare const db: { query(sql: string): Promise<unknown> }',
483
+ 'export async function listAll() {',
484
+ ' return db.query("SELECT * FROM users")',
485
+ '}',
486
+ ].join('\n'));
487
+ const result = await runCheck('database-index-coverage');
488
+ expect(result).toBeDefined();
489
+ });
490
+ it('flags leading-wildcard LIKE queries', async () => {
491
+ fx('src/repos/wildcard.ts', [
492
+ 'declare const db: { query(sql: string): Promise<unknown> }',
493
+ 'export async function search() {',
494
+ ' return db.query("SELECT id FROM users WHERE name LIKE \'%bob%\'")',
495
+ '}',
496
+ ].join('\n'));
497
+ const result = await runCheck('database-index-coverage');
498
+ expect(result).toBeDefined();
499
+ });
500
+ it('flags db.find() / db.findOne() without WHERE', async () => {
501
+ fx('src/repos/find.ts', [
502
+ 'declare const db: { users: { find(): Promise<unknown>; findOne(): Promise<unknown> } }',
503
+ 'export async function f() { return db.users.find() }',
504
+ 'export async function g() { return db.users.findOne() }',
505
+ ].join('\n'));
506
+ const result = await runCheck('database-index-coverage');
507
+ expect(result).toBeDefined();
508
+ });
509
+ });
510
+ // ---------------------------------------------------------------------------
511
+ // missing-input-validation (more branches)
512
+ // ---------------------------------------------------------------------------
513
+ describe('missing-input-validation — extra branch coverage', () => {
514
+ it('runs over a fastify handler reading req.body without validation', async () => {
515
+ fx('src/routes/no-validation.ts', [
516
+ 'import fastify from "fastify"',
517
+ 'const app = fastify()',
518
+ 'app.post("/users", async (req, res) => {',
519
+ ' const body = req.body as { name: string }',
520
+ ' return { name: body.name }',
521
+ '})',
522
+ ].join('\n'));
523
+ const result = await runCheck('missing-input-validation');
524
+ expect(result).toBeDefined();
525
+ });
526
+ it('skips handlers that use Zod schema parsing', async () => {
527
+ fx('src/routes/zod-validated.ts', [
528
+ 'import { z } from "zod"',
529
+ 'const Schema = z.object({ name: z.string() })',
530
+ 'export function handle(input: unknown) {',
531
+ ' const body = Schema.parse(input)',
532
+ ' return body',
533
+ '}',
534
+ ].join('\n'));
535
+ const result = await runCheck('missing-input-validation');
536
+ expect(result).toBeDefined();
537
+ });
538
+ });
539
+ // ---------------------------------------------------------------------------
540
+ // duplicate-utility-functions (more variants)
541
+ // ---------------------------------------------------------------------------
542
+ describe('duplicate-utility-functions — extra coverage', () => {
543
+ it('compares many functions across files', async () => {
544
+ fx('src/utils/a.ts', [
545
+ 'export function snakeCase(s: string): string {',
546
+ ' return s.replaceAll(/[A-Z]/g, (m) => "_" + m.toLowerCase())',
547
+ '}',
548
+ 'export function kebabCase(s: string): string {',
549
+ ' return s.replaceAll(/[A-Z]/g, (m) => "-" + m.toLowerCase())',
550
+ '}',
551
+ ].join('\n'));
552
+ fx('src/utils/b.ts', [
553
+ 'export function snakeCase(input: string): string {',
554
+ ' return input.replaceAll(/[A-Z]/g, (m) => "_" + m.toLowerCase())',
555
+ '}',
556
+ ].join('\n'));
557
+ fx('src/utils/c.ts', ['export function unique() { return Math.random() }'].join('\n'));
558
+ const result = await runCheck('duplicate-utility-functions');
559
+ expect(result).toBeDefined();
560
+ });
561
+ it('handles empty/single function files gracefully', async () => {
562
+ fx('src/utils/single.ts', ['export function loneFn() { return 1 }'].join('\n'));
563
+ const result = await runCheck('duplicate-utility-functions');
564
+ expect(result).toBeDefined();
565
+ });
566
+ });
567
+ // ---------------------------------------------------------------------------
568
+ // circular-import-detection
569
+ // ---------------------------------------------------------------------------
570
+ describe('circular-import-detection — branch coverage', () => {
571
+ it('flags simple A→B→A circular imports', async () => {
572
+ fx('src/cyc/a.ts', 'import { b } from "./b.js"\nexport const a = () => b()');
573
+ fx('src/cyc/b.ts', 'import { a } from "./a.js"\nexport const b = () => a()');
574
+ const result = await runCheck('circular-import-detection');
575
+ expect(result).toBeDefined();
576
+ });
577
+ it('handles longer cycles A→B→C→A', async () => {
578
+ fx('src/cyc/x.ts', 'import { y } from "./y.js"\nexport const x = () => y()');
579
+ fx('src/cyc/y.ts', 'import { z } from "./z.js"\nexport const y = () => z()');
580
+ fx('src/cyc/z.ts', 'import { x } from "./x.js"\nexport const z = () => x()');
581
+ const result = await runCheck('circular-import-detection');
582
+ expect(result).toBeDefined();
583
+ });
584
+ it('does not flag acyclic graphs', async () => {
585
+ fx('src/dag/a.ts', 'import { b } from "./b.js"\nexport const a = () => b()');
586
+ fx('src/dag/b.ts', 'export const b = () => 1');
587
+ const result = await runCheck('circular-import-detection');
588
+ expect(result).toBeDefined();
589
+ });
590
+ });
591
+ // ---------------------------------------------------------------------------
592
+ // no-any-types
593
+ // ---------------------------------------------------------------------------
594
+ describe('no-any-types — branch coverage', () => {
595
+ it('flags explicit any annotations', async () => {
596
+ fx('src/types/any.ts', [
597
+ 'export function f(x: any): any { return x }',
598
+ 'export const v: any = 1',
599
+ 'export const arr: any[] = []',
600
+ ].join('\n'));
601
+ const result = await runCheck('no-any-types');
602
+ expect(result).toBeDefined();
603
+ });
604
+ it('skips test files', async () => {
605
+ fx('src/types/foo.test.ts', ['export function f(x: any): any { return x }'].join('\n'));
606
+ const result = await runCheck('no-any-types');
607
+ expect(result).toBeDefined();
608
+ });
609
+ it('skips files annotated with /* @any-ok */', async () => {
610
+ fx('src/types/annotated.ts', ['/* @any-ok */', 'export function f(x: any): any { return x }'].join('\n'));
611
+ const result = await runCheck('no-any-types');
612
+ expect(result).toBeDefined();
613
+ });
614
+ });
615
+ // ---------------------------------------------------------------------------
616
+ // incomplete-regex-escaping
617
+ // ---------------------------------------------------------------------------
618
+ describe('incomplete-regex-escaping — branch coverage', () => {
619
+ it('flags replace(/[abc]/g, "$&") that misses many specials', async () => {
620
+ fx('src/regex/bad.ts', [
621
+ 'export function bad(s: string) {',
622
+ String.raw ` return s.replace(/[abc]/g, "\\$&")`,
623
+ '}',
624
+ ].join('\n'));
625
+ const result = await runCheck('incomplete-regex-escaping');
626
+ expect(result).toBeDefined();
627
+ });
628
+ it('skips full character class escaping', async () => {
629
+ fx('src/regex/ok.ts', [
630
+ 'export function ok(s: string) {',
631
+ String.raw ` return s.replace(/[\\\^$.*+?()[\]{}|]/g, "\\$&")`,
632
+ '}',
633
+ ].join('\n'));
634
+ const result = await runCheck('incomplete-regex-escaping');
635
+ expect(result).toBeDefined();
636
+ });
637
+ });
638
+ // ---------------------------------------------------------------------------
639
+ // contracts-schema-consistency
640
+ // ---------------------------------------------------------------------------
641
+ describe('contracts-schema-consistency — branch coverage', () => {
642
+ it('runs over zod schema declarations', async () => {
643
+ fx('src/schemas/user.ts', [
644
+ 'import { z } from "zod"',
645
+ 'export const UserSchema = z.object({ id: z.string(), name: z.string() })',
646
+ 'export const CreateUserSchema = z.object({ name: z.string() })',
647
+ 'export type User = z.infer<typeof UserSchema>',
648
+ ].join('\n'));
649
+ const result = await runCheck('contracts-schema-consistency');
650
+ expect(result).toBeDefined();
651
+ });
652
+ it('skips files without zod schemas', async () => {
653
+ fx('src/schemas/no-zod.ts', 'export const x = 1');
654
+ const result = await runCheck('contracts-schema-consistency');
655
+ expect(result).toBeDefined();
656
+ });
657
+ });
658
+ //# sourceMappingURL=behavior-fixtures-3.test.js.map