driftdetect-detectors 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 (509) hide show
  1. package/dist/accessibility/alt-text.d.ts +63 -0
  2. package/dist/accessibility/alt-text.d.ts.map +1 -0
  3. package/dist/accessibility/alt-text.js +100 -0
  4. package/dist/accessibility/alt-text.js.map +1 -0
  5. package/dist/accessibility/aria-roles.d.ts +65 -0
  6. package/dist/accessibility/aria-roles.d.ts.map +1 -0
  7. package/dist/accessibility/aria-roles.js +87 -0
  8. package/dist/accessibility/aria-roles.js.map +1 -0
  9. package/dist/accessibility/focus-management.d.ts +62 -0
  10. package/dist/accessibility/focus-management.d.ts.map +1 -0
  11. package/dist/accessibility/focus-management.js +88 -0
  12. package/dist/accessibility/focus-management.js.map +1 -0
  13. package/dist/accessibility/heading-hierarchy.d.ts +66 -0
  14. package/dist/accessibility/heading-hierarchy.d.ts.map +1 -0
  15. package/dist/accessibility/heading-hierarchy.js +94 -0
  16. package/dist/accessibility/heading-hierarchy.js.map +1 -0
  17. package/dist/accessibility/index.d.ts +25 -0
  18. package/dist/accessibility/index.d.ts.map +1 -0
  19. package/dist/accessibility/index.js +21 -0
  20. package/dist/accessibility/index.js.map +1 -0
  21. package/dist/accessibility/keyboard-nav.d.ts +63 -0
  22. package/dist/accessibility/keyboard-nav.d.ts.map +1 -0
  23. package/dist/accessibility/keyboard-nav.js +86 -0
  24. package/dist/accessibility/keyboard-nav.js.map +1 -0
  25. package/dist/accessibility/semantic-html.d.ts +76 -0
  26. package/dist/accessibility/semantic-html.d.ts.map +1 -0
  27. package/dist/accessibility/semantic-html.js +204 -0
  28. package/dist/accessibility/semantic-html.js.map +1 -0
  29. package/dist/api/client-patterns.d.ts +121 -0
  30. package/dist/api/client-patterns.d.ts.map +1 -0
  31. package/dist/api/client-patterns.js +478 -0
  32. package/dist/api/client-patterns.js.map +1 -0
  33. package/dist/api/error-format.d.ts +140 -0
  34. package/dist/api/error-format.d.ts.map +1 -0
  35. package/dist/api/error-format.js +614 -0
  36. package/dist/api/error-format.js.map +1 -0
  37. package/dist/api/http-methods.d.ts +255 -0
  38. package/dist/api/http-methods.d.ts.map +1 -0
  39. package/dist/api/http-methods.js +890 -0
  40. package/dist/api/http-methods.js.map +1 -0
  41. package/dist/api/index.d.ts +16 -0
  42. package/dist/api/index.d.ts.map +1 -0
  43. package/dist/api/index.js +37 -0
  44. package/dist/api/index.js.map +1 -0
  45. package/dist/api/pagination.d.ts +133 -0
  46. package/dist/api/pagination.d.ts.map +1 -0
  47. package/dist/api/pagination.js +521 -0
  48. package/dist/api/pagination.js.map +1 -0
  49. package/dist/api/response-envelope.d.ts +261 -0
  50. package/dist/api/response-envelope.d.ts.map +1 -0
  51. package/dist/api/response-envelope.js +1050 -0
  52. package/dist/api/response-envelope.js.map +1 -0
  53. package/dist/api/retry-patterns.d.ts +117 -0
  54. package/dist/api/retry-patterns.d.ts.map +1 -0
  55. package/dist/api/retry-patterns.js +480 -0
  56. package/dist/api/retry-patterns.js.map +1 -0
  57. package/dist/api/route-structure.d.ts +128 -0
  58. package/dist/api/route-structure.d.ts.map +1 -0
  59. package/dist/api/route-structure.js +738 -0
  60. package/dist/api/route-structure.js.map +1 -0
  61. package/dist/auth/audit-logging.d.ts +80 -0
  62. package/dist/auth/audit-logging.d.ts.map +1 -0
  63. package/dist/auth/audit-logging.js +370 -0
  64. package/dist/auth/audit-logging.js.map +1 -0
  65. package/dist/auth/index.d.ts +33 -0
  66. package/dist/auth/index.d.ts.map +1 -0
  67. package/dist/auth/index.js +49 -0
  68. package/dist/auth/index.js.map +1 -0
  69. package/dist/auth/middleware-usage.d.ts +65 -0
  70. package/dist/auth/middleware-usage.d.ts.map +1 -0
  71. package/dist/auth/middleware-usage.js +192 -0
  72. package/dist/auth/middleware-usage.js.map +1 -0
  73. package/dist/auth/permission-checks.d.ts +60 -0
  74. package/dist/auth/permission-checks.d.ts.map +1 -0
  75. package/dist/auth/permission-checks.js +159 -0
  76. package/dist/auth/permission-checks.js.map +1 -0
  77. package/dist/auth/rbac-patterns.d.ts +68 -0
  78. package/dist/auth/rbac-patterns.d.ts.map +1 -0
  79. package/dist/auth/rbac-patterns.js +143 -0
  80. package/dist/auth/rbac-patterns.js.map +1 -0
  81. package/dist/auth/resource-ownership.d.ts +77 -0
  82. package/dist/auth/resource-ownership.d.ts.map +1 -0
  83. package/dist/auth/resource-ownership.js +324 -0
  84. package/dist/auth/resource-ownership.js.map +1 -0
  85. package/dist/auth/token-handling.d.ts +64 -0
  86. package/dist/auth/token-handling.d.ts.map +1 -0
  87. package/dist/auth/token-handling.js +151 -0
  88. package/dist/auth/token-handling.js.map +1 -0
  89. package/dist/base/ast-detector.d.ts +421 -0
  90. package/dist/base/ast-detector.d.ts.map +1 -0
  91. package/dist/base/ast-detector.js +699 -0
  92. package/dist/base/ast-detector.js.map +1 -0
  93. package/dist/base/base-detector.d.ts +366 -0
  94. package/dist/base/base-detector.d.ts.map +1 -0
  95. package/dist/base/base-detector.js +170 -0
  96. package/dist/base/base-detector.js.map +1 -0
  97. package/dist/base/index.d.ts +12 -0
  98. package/dist/base/index.d.ts.map +1 -0
  99. package/dist/base/index.js +17 -0
  100. package/dist/base/index.js.map +1 -0
  101. package/dist/base/regex-detector.d.ts +421 -0
  102. package/dist/base/regex-detector.d.ts.map +1 -0
  103. package/dist/base/regex-detector.js +537 -0
  104. package/dist/base/regex-detector.js.map +1 -0
  105. package/dist/base/structural-detector.d.ts +424 -0
  106. package/dist/base/structural-detector.d.ts.map +1 -0
  107. package/dist/base/structural-detector.js +731 -0
  108. package/dist/base/structural-detector.js.map +1 -0
  109. package/dist/base/types.d.ts +53 -0
  110. package/dist/base/types.d.ts.map +1 -0
  111. package/dist/base/types.js +5 -0
  112. package/dist/base/types.js.map +1 -0
  113. package/dist/components/component-structure.d.ts +163 -0
  114. package/dist/components/component-structure.d.ts.map +1 -0
  115. package/dist/components/component-structure.js +500 -0
  116. package/dist/components/component-structure.js.map +1 -0
  117. package/dist/components/composition.d.ts +287 -0
  118. package/dist/components/composition.d.ts.map +1 -0
  119. package/dist/components/composition.js +1123 -0
  120. package/dist/components/composition.js.map +1 -0
  121. package/dist/components/duplicate-detection.d.ts +251 -0
  122. package/dist/components/duplicate-detection.d.ts.map +1 -0
  123. package/dist/components/duplicate-detection.js +804 -0
  124. package/dist/components/duplicate-detection.js.map +1 -0
  125. package/dist/components/index.d.ts +16 -0
  126. package/dist/components/index.d.ts.map +1 -0
  127. package/dist/components/index.js +51 -0
  128. package/dist/components/index.js.map +1 -0
  129. package/dist/components/near-duplicate.d.ts +402 -0
  130. package/dist/components/near-duplicate.d.ts.map +1 -0
  131. package/dist/components/near-duplicate.js +1090 -0
  132. package/dist/components/near-duplicate.js.map +1 -0
  133. package/dist/components/props-patterns.d.ts +194 -0
  134. package/dist/components/props-patterns.d.ts.map +1 -0
  135. package/dist/components/props-patterns.js +795 -0
  136. package/dist/components/props-patterns.js.map +1 -0
  137. package/dist/components/ref-forwarding.d.ts +250 -0
  138. package/dist/components/ref-forwarding.d.ts.map +1 -0
  139. package/dist/components/ref-forwarding.js +832 -0
  140. package/dist/components/ref-forwarding.js.map +1 -0
  141. package/dist/components/state-patterns.d.ts +291 -0
  142. package/dist/components/state-patterns.d.ts.map +1 -0
  143. package/dist/components/state-patterns.js +970 -0
  144. package/dist/components/state-patterns.js.map +1 -0
  145. package/dist/config/config-validation.d.ts +74 -0
  146. package/dist/config/config-validation.d.ts.map +1 -0
  147. package/dist/config/config-validation.js +446 -0
  148. package/dist/config/config-validation.js.map +1 -0
  149. package/dist/config/default-values.d.ts +72 -0
  150. package/dist/config/default-values.d.ts.map +1 -0
  151. package/dist/config/default-values.js +386 -0
  152. package/dist/config/default-values.js.map +1 -0
  153. package/dist/config/env-naming.d.ts +73 -0
  154. package/dist/config/env-naming.d.ts.map +1 -0
  155. package/dist/config/env-naming.js +429 -0
  156. package/dist/config/env-naming.js.map +1 -0
  157. package/dist/config/environment-detection.d.ts +72 -0
  158. package/dist/config/environment-detection.d.ts.map +1 -0
  159. package/dist/config/environment-detection.js +400 -0
  160. package/dist/config/environment-detection.js.map +1 -0
  161. package/dist/config/feature-flags.d.ts +72 -0
  162. package/dist/config/feature-flags.d.ts.map +1 -0
  163. package/dist/config/feature-flags.js +384 -0
  164. package/dist/config/feature-flags.js.map +1 -0
  165. package/dist/config/index.d.ts +27 -0
  166. package/dist/config/index.d.ts.map +1 -0
  167. package/dist/config/index.js +43 -0
  168. package/dist/config/index.js.map +1 -0
  169. package/dist/config/required-optional.d.ts +71 -0
  170. package/dist/config/required-optional.d.ts.map +1 -0
  171. package/dist/config/required-optional.js +344 -0
  172. package/dist/config/required-optional.js.map +1 -0
  173. package/dist/data-access/connection-pooling.d.ts +63 -0
  174. package/dist/data-access/connection-pooling.d.ts.map +1 -0
  175. package/dist/data-access/connection-pooling.js +297 -0
  176. package/dist/data-access/connection-pooling.js.map +1 -0
  177. package/dist/data-access/dto-patterns.d.ts +64 -0
  178. package/dist/data-access/dto-patterns.d.ts.map +1 -0
  179. package/dist/data-access/dto-patterns.js +291 -0
  180. package/dist/data-access/dto-patterns.js.map +1 -0
  181. package/dist/data-access/index.d.ts +31 -0
  182. package/dist/data-access/index.d.ts.map +1 -0
  183. package/dist/data-access/index.js +49 -0
  184. package/dist/data-access/index.js.map +1 -0
  185. package/dist/data-access/n-plus-one.d.ts +60 -0
  186. package/dist/data-access/n-plus-one.d.ts.map +1 -0
  187. package/dist/data-access/n-plus-one.js +264 -0
  188. package/dist/data-access/n-plus-one.js.map +1 -0
  189. package/dist/data-access/query-patterns.d.ts +64 -0
  190. package/dist/data-access/query-patterns.d.ts.map +1 -0
  191. package/dist/data-access/query-patterns.js +314 -0
  192. package/dist/data-access/query-patterns.js.map +1 -0
  193. package/dist/data-access/repository-pattern.d.ts +62 -0
  194. package/dist/data-access/repository-pattern.d.ts.map +1 -0
  195. package/dist/data-access/repository-pattern.js +257 -0
  196. package/dist/data-access/repository-pattern.js.map +1 -0
  197. package/dist/data-access/transaction-patterns.d.ts +61 -0
  198. package/dist/data-access/transaction-patterns.d.ts.map +1 -0
  199. package/dist/data-access/transaction-patterns.js +277 -0
  200. package/dist/data-access/transaction-patterns.js.map +1 -0
  201. package/dist/data-access/validation-patterns.d.ts +62 -0
  202. package/dist/data-access/validation-patterns.d.ts.map +1 -0
  203. package/dist/data-access/validation-patterns.js +301 -0
  204. package/dist/data-access/validation-patterns.js.map +1 -0
  205. package/dist/documentation/deprecation.d.ts +62 -0
  206. package/dist/documentation/deprecation.d.ts.map +1 -0
  207. package/dist/documentation/deprecation.js +83 -0
  208. package/dist/documentation/deprecation.js.map +1 -0
  209. package/dist/documentation/example-code.d.ts +64 -0
  210. package/dist/documentation/example-code.d.ts.map +1 -0
  211. package/dist/documentation/example-code.js +79 -0
  212. package/dist/documentation/example-code.js.map +1 -0
  213. package/dist/documentation/index.d.ts +22 -0
  214. package/dist/documentation/index.d.ts.map +1 -0
  215. package/dist/documentation/index.js +19 -0
  216. package/dist/documentation/index.js.map +1 -0
  217. package/dist/documentation/jsdoc-patterns.d.ts +72 -0
  218. package/dist/documentation/jsdoc-patterns.d.ts.map +1 -0
  219. package/dist/documentation/jsdoc-patterns.js +92 -0
  220. package/dist/documentation/jsdoc-patterns.js.map +1 -0
  221. package/dist/documentation/readme-structure.d.ts +67 -0
  222. package/dist/documentation/readme-structure.d.ts.map +1 -0
  223. package/dist/documentation/readme-structure.js +76 -0
  224. package/dist/documentation/readme-structure.js.map +1 -0
  225. package/dist/documentation/todo-patterns.d.ts +67 -0
  226. package/dist/documentation/todo-patterns.d.ts.map +1 -0
  227. package/dist/documentation/todo-patterns.js +73 -0
  228. package/dist/documentation/todo-patterns.js.map +1 -0
  229. package/dist/errors/async-errors.d.ts +72 -0
  230. package/dist/errors/async-errors.d.ts.map +1 -0
  231. package/dist/errors/async-errors.js +214 -0
  232. package/dist/errors/async-errors.js.map +1 -0
  233. package/dist/errors/circuit-breaker.d.ts +53 -0
  234. package/dist/errors/circuit-breaker.d.ts.map +1 -0
  235. package/dist/errors/circuit-breaker.js +241 -0
  236. package/dist/errors/circuit-breaker.js.map +1 -0
  237. package/dist/errors/error-codes.d.ts +73 -0
  238. package/dist/errors/error-codes.d.ts.map +1 -0
  239. package/dist/errors/error-codes.js +211 -0
  240. package/dist/errors/error-codes.js.map +1 -0
  241. package/dist/errors/error-logging.d.ts +73 -0
  242. package/dist/errors/error-logging.d.ts.map +1 -0
  243. package/dist/errors/error-logging.js +256 -0
  244. package/dist/errors/error-logging.js.map +1 -0
  245. package/dist/errors/error-propagation.d.ts +73 -0
  246. package/dist/errors/error-propagation.d.ts.map +1 -0
  247. package/dist/errors/error-propagation.js +244 -0
  248. package/dist/errors/error-propagation.js.map +1 -0
  249. package/dist/errors/exception-hierarchy.d.ts +75 -0
  250. package/dist/errors/exception-hierarchy.d.ts.map +1 -0
  251. package/dist/errors/exception-hierarchy.js +259 -0
  252. package/dist/errors/exception-hierarchy.js.map +1 -0
  253. package/dist/errors/index.d.ts +31 -0
  254. package/dist/errors/index.d.ts.map +1 -0
  255. package/dist/errors/index.js +49 -0
  256. package/dist/errors/index.js.map +1 -0
  257. package/dist/errors/try-catch-placement.d.ts +73 -0
  258. package/dist/errors/try-catch-placement.d.ts.map +1 -0
  259. package/dist/errors/try-catch-placement.js +214 -0
  260. package/dist/errors/try-catch-placement.js.map +1 -0
  261. package/dist/index.d.ts +221 -0
  262. package/dist/index.d.ts.map +1 -0
  263. package/dist/index.js +245 -0
  264. package/dist/index.js.map +1 -0
  265. package/dist/logging/context-fields.d.ts +48 -0
  266. package/dist/logging/context-fields.d.ts.map +1 -0
  267. package/dist/logging/context-fields.js +160 -0
  268. package/dist/logging/context-fields.js.map +1 -0
  269. package/dist/logging/correlation-ids.d.ts +44 -0
  270. package/dist/logging/correlation-ids.d.ts.map +1 -0
  271. package/dist/logging/correlation-ids.js +144 -0
  272. package/dist/logging/correlation-ids.js.map +1 -0
  273. package/dist/logging/health-checks.d.ts +45 -0
  274. package/dist/logging/health-checks.d.ts.map +1 -0
  275. package/dist/logging/health-checks.js +165 -0
  276. package/dist/logging/health-checks.js.map +1 -0
  277. package/dist/logging/index.d.ts +31 -0
  278. package/dist/logging/index.d.ts.map +1 -0
  279. package/dist/logging/index.js +49 -0
  280. package/dist/logging/index.js.map +1 -0
  281. package/dist/logging/log-levels.d.ts +46 -0
  282. package/dist/logging/log-levels.d.ts.map +1 -0
  283. package/dist/logging/log-levels.js +178 -0
  284. package/dist/logging/log-levels.js.map +1 -0
  285. package/dist/logging/metric-naming.d.ts +46 -0
  286. package/dist/logging/metric-naming.d.ts.map +1 -0
  287. package/dist/logging/metric-naming.js +157 -0
  288. package/dist/logging/metric-naming.js.map +1 -0
  289. package/dist/logging/pii-redaction.d.ts +44 -0
  290. package/dist/logging/pii-redaction.d.ts.map +1 -0
  291. package/dist/logging/pii-redaction.js +166 -0
  292. package/dist/logging/pii-redaction.js.map +1 -0
  293. package/dist/logging/structured-format.d.ts +53 -0
  294. package/dist/logging/structured-format.d.ts.map +1 -0
  295. package/dist/logging/structured-format.js +235 -0
  296. package/dist/logging/structured-format.js.map +1 -0
  297. package/dist/performance/bundle-size.d.ts +79 -0
  298. package/dist/performance/bundle-size.d.ts.map +1 -0
  299. package/dist/performance/bundle-size.js +276 -0
  300. package/dist/performance/bundle-size.js.map +1 -0
  301. package/dist/performance/caching-patterns.d.ts +78 -0
  302. package/dist/performance/caching-patterns.d.ts.map +1 -0
  303. package/dist/performance/caching-patterns.js +257 -0
  304. package/dist/performance/caching-patterns.js.map +1 -0
  305. package/dist/performance/code-splitting.d.ts +86 -0
  306. package/dist/performance/code-splitting.d.ts.map +1 -0
  307. package/dist/performance/code-splitting.js +447 -0
  308. package/dist/performance/code-splitting.js.map +1 -0
  309. package/dist/performance/debounce-throttle.d.ts +75 -0
  310. package/dist/performance/debounce-throttle.d.ts.map +1 -0
  311. package/dist/performance/debounce-throttle.js +232 -0
  312. package/dist/performance/debounce-throttle.js.map +1 -0
  313. package/dist/performance/index.d.ts +28 -0
  314. package/dist/performance/index.d.ts.map +1 -0
  315. package/dist/performance/index.js +39 -0
  316. package/dist/performance/index.js.map +1 -0
  317. package/dist/performance/lazy-loading.d.ts +75 -0
  318. package/dist/performance/lazy-loading.d.ts.map +1 -0
  319. package/dist/performance/lazy-loading.js +233 -0
  320. package/dist/performance/lazy-loading.js.map +1 -0
  321. package/dist/performance/memoization.d.ts +75 -0
  322. package/dist/performance/memoization.d.ts.map +1 -0
  323. package/dist/performance/memoization.js +251 -0
  324. package/dist/performance/memoization.js.map +1 -0
  325. package/dist/registry/detector-registry.d.ts +266 -0
  326. package/dist/registry/detector-registry.d.ts.map +1 -0
  327. package/dist/registry/detector-registry.js +526 -0
  328. package/dist/registry/detector-registry.js.map +1 -0
  329. package/dist/registry/index.d.ts +10 -0
  330. package/dist/registry/index.d.ts.map +1 -0
  331. package/dist/registry/index.js +10 -0
  332. package/dist/registry/index.js.map +1 -0
  333. package/dist/registry/loader.d.ts +232 -0
  334. package/dist/registry/loader.d.ts.map +1 -0
  335. package/dist/registry/loader.js +419 -0
  336. package/dist/registry/loader.js.map +1 -0
  337. package/dist/registry/types.d.ts +111 -0
  338. package/dist/registry/types.d.ts.map +1 -0
  339. package/dist/registry/types.js +19 -0
  340. package/dist/registry/types.js.map +1 -0
  341. package/dist/security/csp-headers.d.ts +78 -0
  342. package/dist/security/csp-headers.d.ts.map +1 -0
  343. package/dist/security/csp-headers.js +401 -0
  344. package/dist/security/csp-headers.js.map +1 -0
  345. package/dist/security/csrf-protection.d.ts +72 -0
  346. package/dist/security/csrf-protection.d.ts.map +1 -0
  347. package/dist/security/csrf-protection.js +344 -0
  348. package/dist/security/csrf-protection.js.map +1 -0
  349. package/dist/security/index.d.ts +30 -0
  350. package/dist/security/index.d.ts.map +1 -0
  351. package/dist/security/index.js +48 -0
  352. package/dist/security/index.js.map +1 -0
  353. package/dist/security/input-sanitization.d.ts +74 -0
  354. package/dist/security/input-sanitization.d.ts.map +1 -0
  355. package/dist/security/input-sanitization.js +373 -0
  356. package/dist/security/input-sanitization.js.map +1 -0
  357. package/dist/security/rate-limiting.d.ts +81 -0
  358. package/dist/security/rate-limiting.d.ts.map +1 -0
  359. package/dist/security/rate-limiting.js +535 -0
  360. package/dist/security/rate-limiting.js.map +1 -0
  361. package/dist/security/secret-management.d.ts +83 -0
  362. package/dist/security/secret-management.d.ts.map +1 -0
  363. package/dist/security/secret-management.js +547 -0
  364. package/dist/security/secret-management.js.map +1 -0
  365. package/dist/security/sql-injection.d.ts +76 -0
  366. package/dist/security/sql-injection.d.ts.map +1 -0
  367. package/dist/security/sql-injection.js +383 -0
  368. package/dist/security/sql-injection.js.map +1 -0
  369. package/dist/security/xss-prevention.d.ts +80 -0
  370. package/dist/security/xss-prevention.d.ts.map +1 -0
  371. package/dist/security/xss-prevention.js +416 -0
  372. package/dist/security/xss-prevention.js.map +1 -0
  373. package/dist/structural/barrel-exports.d.ts +178 -0
  374. package/dist/structural/barrel-exports.d.ts.map +1 -0
  375. package/dist/structural/barrel-exports.js +553 -0
  376. package/dist/structural/barrel-exports.js.map +1 -0
  377. package/dist/structural/circular-deps.d.ts +140 -0
  378. package/dist/structural/circular-deps.d.ts.map +1 -0
  379. package/dist/structural/circular-deps.js +422 -0
  380. package/dist/structural/circular-deps.js.map +1 -0
  381. package/dist/structural/co-location.d.ts +202 -0
  382. package/dist/structural/co-location.d.ts.map +1 -0
  383. package/dist/structural/co-location.js +640 -0
  384. package/dist/structural/co-location.js.map +1 -0
  385. package/dist/structural/directory-structure.d.ts +151 -0
  386. package/dist/structural/directory-structure.d.ts.map +1 -0
  387. package/dist/structural/directory-structure.js +457 -0
  388. package/dist/structural/directory-structure.js.map +1 -0
  389. package/dist/structural/file-naming.d.ts +61 -0
  390. package/dist/structural/file-naming.d.ts.map +1 -0
  391. package/dist/structural/file-naming.js +231 -0
  392. package/dist/structural/file-naming.js.map +1 -0
  393. package/dist/structural/import-ordering.d.ts +212 -0
  394. package/dist/structural/import-ordering.d.ts.map +1 -0
  395. package/dist/structural/import-ordering.js +821 -0
  396. package/dist/structural/import-ordering.js.map +1 -0
  397. package/dist/structural/index.d.ts +23 -0
  398. package/dist/structural/index.d.ts.map +1 -0
  399. package/dist/structural/index.js +26 -0
  400. package/dist/structural/index.js.map +1 -0
  401. package/dist/structural/module-boundaries.d.ts +164 -0
  402. package/dist/structural/module-boundaries.d.ts.map +1 -0
  403. package/dist/structural/module-boundaries.js +616 -0
  404. package/dist/structural/module-boundaries.js.map +1 -0
  405. package/dist/structural/package-boundaries.d.ts +182 -0
  406. package/dist/structural/package-boundaries.d.ts.map +1 -0
  407. package/dist/structural/package-boundaries.js +602 -0
  408. package/dist/structural/package-boundaries.js.map +1 -0
  409. package/dist/styling/class-naming.d.ts +263 -0
  410. package/dist/styling/class-naming.d.ts.map +1 -0
  411. package/dist/styling/class-naming.js +892 -0
  412. package/dist/styling/class-naming.js.map +1 -0
  413. package/dist/styling/color-usage.d.ts +213 -0
  414. package/dist/styling/color-usage.d.ts.map +1 -0
  415. package/dist/styling/color-usage.js +732 -0
  416. package/dist/styling/color-usage.js.map +1 -0
  417. package/dist/styling/design-tokens.d.ts +212 -0
  418. package/dist/styling/design-tokens.d.ts.map +1 -0
  419. package/dist/styling/design-tokens.js +748 -0
  420. package/dist/styling/design-tokens.js.map +1 -0
  421. package/dist/styling/index.d.ts +16 -0
  422. package/dist/styling/index.d.ts.map +1 -0
  423. package/dist/styling/index.js +56 -0
  424. package/dist/styling/index.js.map +1 -0
  425. package/dist/styling/responsive.d.ts +304 -0
  426. package/dist/styling/responsive.d.ts.map +1 -0
  427. package/dist/styling/responsive.js +888 -0
  428. package/dist/styling/responsive.js.map +1 -0
  429. package/dist/styling/spacing-scale.d.ts +248 -0
  430. package/dist/styling/spacing-scale.d.ts.map +1 -0
  431. package/dist/styling/spacing-scale.js +865 -0
  432. package/dist/styling/spacing-scale.js.map +1 -0
  433. package/dist/styling/tailwind-patterns.d.ts +305 -0
  434. package/dist/styling/tailwind-patterns.d.ts.map +1 -0
  435. package/dist/styling/tailwind-patterns.js +1181 -0
  436. package/dist/styling/tailwind-patterns.js.map +1 -0
  437. package/dist/styling/typography.d.ts +281 -0
  438. package/dist/styling/typography.d.ts.map +1 -0
  439. package/dist/styling/typography.js +1004 -0
  440. package/dist/styling/typography.js.map +1 -0
  441. package/dist/styling/z-index-scale.d.ts +270 -0
  442. package/dist/styling/z-index-scale.d.ts.map +1 -0
  443. package/dist/styling/z-index-scale.js +714 -0
  444. package/dist/styling/z-index-scale.js.map +1 -0
  445. package/dist/testing/co-location.d.ts +42 -0
  446. package/dist/testing/co-location.d.ts.map +1 -0
  447. package/dist/testing/co-location.js +134 -0
  448. package/dist/testing/co-location.js.map +1 -0
  449. package/dist/testing/describe-naming.d.ts +47 -0
  450. package/dist/testing/describe-naming.d.ts.map +1 -0
  451. package/dist/testing/describe-naming.js +150 -0
  452. package/dist/testing/describe-naming.js.map +1 -0
  453. package/dist/testing/file-naming.d.ts +44 -0
  454. package/dist/testing/file-naming.d.ts.map +1 -0
  455. package/dist/testing/file-naming.js +131 -0
  456. package/dist/testing/file-naming.js.map +1 -0
  457. package/dist/testing/fixture-patterns.d.ts +52 -0
  458. package/dist/testing/fixture-patterns.d.ts.map +1 -0
  459. package/dist/testing/fixture-patterns.js +228 -0
  460. package/dist/testing/fixture-patterns.js.map +1 -0
  461. package/dist/testing/index.d.ts +31 -0
  462. package/dist/testing/index.d.ts.map +1 -0
  463. package/dist/testing/index.js +49 -0
  464. package/dist/testing/index.js.map +1 -0
  465. package/dist/testing/mock-patterns.d.ts +53 -0
  466. package/dist/testing/mock-patterns.d.ts.map +1 -0
  467. package/dist/testing/mock-patterns.js +264 -0
  468. package/dist/testing/mock-patterns.js.map +1 -0
  469. package/dist/testing/setup-teardown.d.ts +55 -0
  470. package/dist/testing/setup-teardown.d.ts.map +1 -0
  471. package/dist/testing/setup-teardown.js +262 -0
  472. package/dist/testing/setup-teardown.js.map +1 -0
  473. package/dist/testing/test-structure.d.ts +51 -0
  474. package/dist/testing/test-structure.d.ts.map +1 -0
  475. package/dist/testing/test-structure.js +225 -0
  476. package/dist/testing/test-structure.js.map +1 -0
  477. package/dist/types/any-usage.d.ts +99 -0
  478. package/dist/types/any-usage.d.ts.map +1 -0
  479. package/dist/types/any-usage.js +641 -0
  480. package/dist/types/any-usage.js.map +1 -0
  481. package/dist/types/file-location.d.ts +76 -0
  482. package/dist/types/file-location.d.ts.map +1 -0
  483. package/dist/types/file-location.js +395 -0
  484. package/dist/types/file-location.js.map +1 -0
  485. package/dist/types/generic-patterns.d.ts +97 -0
  486. package/dist/types/generic-patterns.d.ts.map +1 -0
  487. package/dist/types/generic-patterns.js +615 -0
  488. package/dist/types/generic-patterns.js.map +1 -0
  489. package/dist/types/index.d.ts +31 -0
  490. package/dist/types/index.d.ts.map +1 -0
  491. package/dist/types/index.js +43 -0
  492. package/dist/types/index.js.map +1 -0
  493. package/dist/types/interface-vs-type.d.ts +81 -0
  494. package/dist/types/interface-vs-type.d.ts.map +1 -0
  495. package/dist/types/interface-vs-type.js +440 -0
  496. package/dist/types/interface-vs-type.js.map +1 -0
  497. package/dist/types/naming-conventions.d.ts +84 -0
  498. package/dist/types/naming-conventions.d.ts.map +1 -0
  499. package/dist/types/naming-conventions.js +455 -0
  500. package/dist/types/naming-conventions.js.map +1 -0
  501. package/dist/types/type-assertions.d.ts +98 -0
  502. package/dist/types/type-assertions.d.ts.map +1 -0
  503. package/dist/types/type-assertions.js +639 -0
  504. package/dist/types/type-assertions.js.map +1 -0
  505. package/dist/types/utility-types.d.ts +110 -0
  506. package/dist/types/utility-types.d.ts.map +1 -0
  507. package/dist/types/utility-types.js +547 -0
  508. package/dist/types/utility-types.js.map +1 -0
  509. package/package.json +44 -0
@@ -0,0 +1,890 @@
1
+ /**
2
+ * HTTP Methods Detector - HTTP method usage pattern detection
3
+ *
4
+ * Detects HTTP method usage patterns including:
5
+ * - HTTP method usage (GET, POST, PUT, PATCH, DELETE, HEAD, OPTIONS)
6
+ * - RESTful method conventions (GET for read, POST for create, PUT/PATCH for update, DELETE for remove)
7
+ * - Express/Fastify method handlers (router.get, router.post, etc.)
8
+ * - Next.js App Router method exports (export function GET, POST, etc.)
9
+ * - Fetch API method usage (fetch with method option)
10
+ * - Axios method usage (axios.get, axios.post, etc.)
11
+ *
12
+ * Flags violations:
13
+ * - Using POST for read operations (should be GET)
14
+ * - Using GET for mutations (should be POST/PUT/PATCH/DELETE)
15
+ * - Missing method handlers for common operations
16
+ * - Inconsistent method usage across similar endpoints
17
+ * - Using PUT when PATCH is more appropriate (partial updates)
18
+ *
19
+ * @requirements 10.2 - THE API_Detector SHALL detect HTTP method usage patterns (POST vs PUT vs PATCH)
20
+ */
21
+ import { RegexDetector } from '../base/index.js';
22
+ // ============================================================================
23
+ // Constants
24
+ // ============================================================================
25
+ /**
26
+ * All supported HTTP methods
27
+ */
28
+ export const HTTP_METHODS = [
29
+ 'GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'HEAD', 'OPTIONS'
30
+ ];
31
+ /**
32
+ * HTTP methods for read operations
33
+ */
34
+ export const READ_METHODS = ['GET', 'HEAD', 'OPTIONS'];
35
+ /**
36
+ * HTTP methods for mutation operations
37
+ */
38
+ export const MUTATION_METHODS = ['POST', 'PUT', 'PATCH', 'DELETE'];
39
+ /**
40
+ * RESTful method conventions mapping
41
+ */
42
+ export const RESTFUL_METHOD_CONVENTIONS = {
43
+ // Read operations should use GET
44
+ read: ['GET'],
45
+ get: ['GET'],
46
+ fetch: ['GET'],
47
+ list: ['GET'],
48
+ find: ['GET'],
49
+ search: ['GET'],
50
+ query: ['GET'],
51
+ // Create operations should use POST
52
+ create: ['POST'],
53
+ add: ['POST'],
54
+ insert: ['POST'],
55
+ new: ['POST'],
56
+ // Update operations should use PUT or PATCH
57
+ update: ['PUT', 'PATCH'],
58
+ edit: ['PUT', 'PATCH'],
59
+ modify: ['PUT', 'PATCH'],
60
+ change: ['PUT', 'PATCH'],
61
+ replace: ['PUT'],
62
+ // Partial update operations should use PATCH
63
+ patch: ['PATCH'],
64
+ partial: ['PATCH'],
65
+ // Delete operations should use DELETE
66
+ delete: ['DELETE'],
67
+ remove: ['DELETE'],
68
+ destroy: ['DELETE'],
69
+ };
70
+ /**
71
+ * Keywords indicating read operations
72
+ */
73
+ export const READ_OPERATION_KEYWORDS = new Set([
74
+ 'get', 'fetch', 'find', 'list', 'search', 'query', 'read', 'load', 'retrieve',
75
+ 'show', 'view', 'display', 'check', 'verify', 'validate', 'exists', 'count',
76
+ ]);
77
+ /**
78
+ * Keywords indicating mutation operations
79
+ */
80
+ export const MUTATION_OPERATION_KEYWORDS = new Set([
81
+ 'create', 'add', 'insert', 'new', 'post', 'submit', 'save',
82
+ 'update', 'edit', 'modify', 'change', 'patch', 'put', 'replace',
83
+ 'delete', 'remove', 'destroy', 'clear', 'reset', 'cancel',
84
+ ]);
85
+ /**
86
+ * Keywords indicating partial update operations
87
+ */
88
+ export const PARTIAL_UPDATE_KEYWORDS = new Set([
89
+ 'patch', 'partial', 'update', 'modify', 'change', 'edit',
90
+ ]);
91
+ /**
92
+ * Keywords indicating full replacement operations
93
+ */
94
+ export const FULL_REPLACEMENT_KEYWORDS = new Set([
95
+ 'replace', 'set', 'overwrite', 'reset',
96
+ ]);
97
+ /**
98
+ * Express/Fastify route handler patterns
99
+ */
100
+ export const EXPRESS_METHOD_PATTERNS = [
101
+ // TypeScript/JavaScript patterns - Express/Fastify route handler (router.get, app.post)
102
+ /(?:router|app|server|fastify)\.(get|post|put|patch|delete|head|options)\s*\(\s*['"`]([^'"`]+)['"`]/gi,
103
+ // router.route('/path').get(handler).post(handler)
104
+ /\.route\s*\(\s*['"`]([^'"`]+)['"`]\s*\)\s*\.(get|post|put|patch|delete|head|options)\s*\(/gi,
105
+ // Python patterns - FastAPI, Flask
106
+ /@(?:app|router)\.(get|post|put|patch|delete|head|options)\s*\(\s*['"`]([^'"`]+)['"`]/gi,
107
+ /@api_view\s*\(\s*\[\s*['"`](GET|POST|PUT|PATCH|DELETE)['"`]/gi,
108
+ ];
109
+ /**
110
+ * Next.js App Router method export patterns
111
+ */
112
+ export const NEXTJS_METHOD_EXPORT_PATTERN = /export\s+(?:async\s+)?function\s+(GET|POST|PUT|PATCH|DELETE|HEAD|OPTIONS)\s*\(/gi;
113
+ /**
114
+ * Fetch API method patterns
115
+ */
116
+ export const FETCH_METHOD_PATTERNS = [
117
+ // fetch(url, { method: 'POST' }) - matches fetch with method option in config object
118
+ /fetch\s*\(\s*[^,]+,\s*\{[^}]*method\s*:\s*['"`](GET|POST|PUT|PATCH|DELETE|HEAD|OPTIONS)['"`]/gi,
119
+ ];
120
+ /**
121
+ * Axios method patterns
122
+ */
123
+ export const AXIOS_METHOD_PATTERNS = [
124
+ // axios.get(url), axios.post(url, data)
125
+ /axios\.(get|post|put|patch|delete|head|options)\s*\(/gi,
126
+ // axios({ method: 'POST', url: ... })
127
+ /axios\s*\(\s*\{[^}]*method\s*:\s*['"`](GET|POST|PUT|PATCH|DELETE|HEAD|OPTIONS)['"`]/gi,
128
+ // axios.request({ method: 'POST' })
129
+ /axios\.request\s*\(\s*\{[^}]*method\s*:\s*['"`](GET|POST|PUT|PATCH|DELETE|HEAD|OPTIONS)['"`]/gi,
130
+ ];
131
+ /**
132
+ * Generic HTTP client patterns
133
+ */
134
+ export const HTTP_CLIENT_PATTERNS = [
135
+ // http.get, http.post, etc.
136
+ /(?:http|client|api)\.(get|post|put|patch|delete|head|options)\s*\(/gi,
137
+ // request({ method: 'POST' })
138
+ /request\s*\(\s*\{[^}]*method\s*:\s*['"`](GET|POST|PUT|PATCH|DELETE|HEAD|OPTIONS)['"`]/gi,
139
+ // got.get, got.post, etc.
140
+ /got\.(get|post|put|patch|delete|head|options)\s*\(/gi,
141
+ // ky.get, ky.post, etc.
142
+ /ky\.(get|post|put|patch|delete|head|options)\s*\(/gi,
143
+ // superagent.get, superagent.post, etc.
144
+ /superagent\.(get|post|put|patch|delete|head|options)\s*\(/gi,
145
+ ];
146
+ /**
147
+ * File patterns to exclude from detection
148
+ */
149
+ export const EXCLUDED_FILE_PATTERNS = [
150
+ /\.test\.[jt]sx?$/,
151
+ /\.spec\.[jt]sx?$/,
152
+ /\.stories\.[jt]sx?$/,
153
+ /\.d\.ts$/,
154
+ /node_modules\//,
155
+ /\.mock\.[jt]sx?$/,
156
+ ];
157
+ // ============================================================================
158
+ // Helper Functions
159
+ // ============================================================================
160
+ /**
161
+ * Check if a file should be excluded from detection
162
+ */
163
+ export function shouldExcludeFile(filePath) {
164
+ return EXCLUDED_FILE_PATTERNS.some(pattern => pattern.test(filePath));
165
+ }
166
+ /**
167
+ * Normalize HTTP method to uppercase
168
+ */
169
+ export function normalizeMethod(method) {
170
+ return method.toUpperCase();
171
+ }
172
+ /**
173
+ * Check if a method is a read method
174
+ */
175
+ export function isReadMethod(method) {
176
+ return READ_METHODS.includes(method);
177
+ }
178
+ /**
179
+ * Check if a method is a mutation method
180
+ */
181
+ export function isMutationMethod(method) {
182
+ return MUTATION_METHODS.includes(method);
183
+ }
184
+ /**
185
+ * Infer operation type from context (route path, function name, etc.)
186
+ */
187
+ export function inferOperationType(context, routePath) {
188
+ const lowerContext = context.toLowerCase();
189
+ const lowerPath = routePath?.toLowerCase() || '';
190
+ // Check for delete operations
191
+ if (lowerContext.includes('delete') ||
192
+ lowerContext.includes('remove') ||
193
+ lowerContext.includes('destroy')) {
194
+ return 'delete';
195
+ }
196
+ // Check for create operations
197
+ if (lowerContext.includes('create') ||
198
+ lowerContext.includes('add') ||
199
+ lowerContext.includes('insert') ||
200
+ lowerContext.includes('new')) {
201
+ return 'create';
202
+ }
203
+ // Check for update operations
204
+ if (lowerContext.includes('update') ||
205
+ lowerContext.includes('edit') ||
206
+ lowerContext.includes('modify') ||
207
+ lowerContext.includes('patch') ||
208
+ lowerContext.includes('put')) {
209
+ return 'update';
210
+ }
211
+ // Check for read operations
212
+ for (const keyword of READ_OPERATION_KEYWORDS) {
213
+ if (lowerContext.includes(keyword) || lowerPath.includes(keyword)) {
214
+ return 'read';
215
+ }
216
+ }
217
+ return 'unknown';
218
+ }
219
+ /**
220
+ * Check if position is inside a comment
221
+ */
222
+ function isInsideComment(content, index) {
223
+ const beforeIndex = content.slice(0, index);
224
+ // Check for single-line comment
225
+ const lastNewline = beforeIndex.lastIndexOf('\n');
226
+ const currentLine = beforeIndex.slice(lastNewline + 1);
227
+ if (currentLine.includes('//')) {
228
+ const commentStart = currentLine.indexOf('//');
229
+ const positionInLine = index - lastNewline - 1;
230
+ if (positionInLine > commentStart) {
231
+ return true;
232
+ }
233
+ }
234
+ // Check for multi-line comment
235
+ const lastBlockCommentStart = beforeIndex.lastIndexOf('/*');
236
+ const lastBlockCommentEnd = beforeIndex.lastIndexOf('*/');
237
+ if (lastBlockCommentStart > lastBlockCommentEnd) {
238
+ return true;
239
+ }
240
+ return false;
241
+ }
242
+ /**
243
+ * Get line and column from index
244
+ */
245
+ function getPositionFromIndex(content, index) {
246
+ const beforeMatch = content.slice(0, index);
247
+ const lineNumber = beforeMatch.split('\n').length;
248
+ const lastNewline = beforeMatch.lastIndexOf('\n');
249
+ const column = index - lastNewline;
250
+ return { line: lineNumber, column };
251
+ }
252
+ /**
253
+ * Detect Express/Fastify route handlers
254
+ */
255
+ export function detectExpressHandlers(content, file) {
256
+ const results = [];
257
+ const lines = content.split('\n');
258
+ for (const pattern of EXPRESS_METHOD_PATTERNS) {
259
+ const regex = new RegExp(pattern.source, pattern.flags);
260
+ let match;
261
+ while ((match = regex.exec(content)) !== null) {
262
+ if (isInsideComment(content, match.index)) {
263
+ continue;
264
+ }
265
+ const { line, column } = getPositionFromIndex(content, match.index);
266
+ // Handle different capture group orders
267
+ let method;
268
+ let routePath;
269
+ if (pattern.source.includes('\\.route')) {
270
+ // .route('/path').get() pattern - path is first, method is second
271
+ routePath = match[1];
272
+ method = match[2] || 'GET';
273
+ }
274
+ else {
275
+ // router.get('/path') pattern - method is first, path is second
276
+ method = match[1] || 'GET';
277
+ routePath = match[2];
278
+ }
279
+ const normalizedMethod = normalizeMethod(method);
280
+ const lineContent = lines[line - 1] || '';
281
+ results.push({
282
+ type: 'express-handler',
283
+ method: normalizedMethod,
284
+ file,
285
+ line,
286
+ column,
287
+ matchedText: match[0],
288
+ routePath,
289
+ operationType: inferOperationType(lineContent, routePath),
290
+ context: lineContent,
291
+ });
292
+ }
293
+ }
294
+ return results;
295
+ }
296
+ /**
297
+ * Detect Next.js App Router method exports
298
+ */
299
+ export function detectNextjsMethodExports(content, file) {
300
+ const results = [];
301
+ const lines = content.split('\n');
302
+ // Only check files that look like Next.js route files
303
+ if (!file.includes('/app/') && !file.includes('\\app\\')) {
304
+ return results;
305
+ }
306
+ const regex = new RegExp(NEXTJS_METHOD_EXPORT_PATTERN.source, NEXTJS_METHOD_EXPORT_PATTERN.flags);
307
+ let match;
308
+ while ((match = regex.exec(content)) !== null) {
309
+ if (isInsideComment(content, match.index)) {
310
+ continue;
311
+ }
312
+ const { line, column } = getPositionFromIndex(content, match.index);
313
+ const method = normalizeMethod(match[1] || 'GET');
314
+ const lineContent = lines[line - 1] || '';
315
+ // Infer route path from file path
316
+ const routeMatch = file.match(/\/app(\/(?:api\/)?[^/]+(?:\/[^/]+)*?)\/route\.[jt]sx?$/);
317
+ const routePath = routeMatch ? routeMatch[1] : undefined;
318
+ results.push({
319
+ type: 'nextjs-app-router',
320
+ method,
321
+ file,
322
+ line,
323
+ column,
324
+ matchedText: match[0],
325
+ routePath,
326
+ operationType: inferOperationType(lineContent, routePath),
327
+ context: lineContent,
328
+ });
329
+ }
330
+ return results;
331
+ }
332
+ /**
333
+ * Detect Fetch API method usage
334
+ */
335
+ export function detectFetchApiUsage(content, file) {
336
+ const results = [];
337
+ const lines = content.split('\n');
338
+ for (const pattern of FETCH_METHOD_PATTERNS) {
339
+ const regex = new RegExp(pattern.source, pattern.flags);
340
+ let match;
341
+ while ((match = regex.exec(content)) !== null) {
342
+ if (isInsideComment(content, match.index)) {
343
+ continue;
344
+ }
345
+ const { line, column } = getPositionFromIndex(content, match.index);
346
+ const method = normalizeMethod(match[1] || 'GET');
347
+ const lineContent = lines[line - 1] || '';
348
+ results.push({
349
+ type: 'fetch-api',
350
+ method,
351
+ file,
352
+ line,
353
+ column,
354
+ matchedText: match[0],
355
+ operationType: inferOperationType(lineContent),
356
+ context: lineContent,
357
+ });
358
+ }
359
+ }
360
+ return results;
361
+ }
362
+ /**
363
+ * Detect Axios method usage
364
+ */
365
+ export function detectAxiosUsage(content, file) {
366
+ const results = [];
367
+ const lines = content.split('\n');
368
+ for (const pattern of AXIOS_METHOD_PATTERNS) {
369
+ const regex = new RegExp(pattern.source, pattern.flags);
370
+ let match;
371
+ while ((match = regex.exec(content)) !== null) {
372
+ if (isInsideComment(content, match.index)) {
373
+ continue;
374
+ }
375
+ const { line, column } = getPositionFromIndex(content, match.index);
376
+ const method = normalizeMethod(match[1] || 'GET');
377
+ const lineContent = lines[line - 1] || '';
378
+ results.push({
379
+ type: 'axios-method',
380
+ method,
381
+ file,
382
+ line,
383
+ column,
384
+ matchedText: match[0],
385
+ operationType: inferOperationType(lineContent),
386
+ context: lineContent,
387
+ });
388
+ }
389
+ }
390
+ return results;
391
+ }
392
+ /**
393
+ * Detect generic HTTP client usage
394
+ */
395
+ export function detectHttpClientUsage(content, file) {
396
+ const results = [];
397
+ const lines = content.split('\n');
398
+ for (const pattern of HTTP_CLIENT_PATTERNS) {
399
+ const regex = new RegExp(pattern.source, pattern.flags);
400
+ let match;
401
+ while ((match = regex.exec(content)) !== null) {
402
+ if (isInsideComment(content, match.index)) {
403
+ continue;
404
+ }
405
+ const { line, column } = getPositionFromIndex(content, match.index);
406
+ const method = normalizeMethod(match[1] || 'GET');
407
+ const lineContent = lines[line - 1] || '';
408
+ results.push({
409
+ type: 'http-client',
410
+ method,
411
+ file,
412
+ line,
413
+ column,
414
+ matchedText: match[0],
415
+ operationType: inferOperationType(lineContent),
416
+ context: lineContent,
417
+ });
418
+ }
419
+ }
420
+ return results;
421
+ }
422
+ // ============================================================================
423
+ // Violation Detection Functions
424
+ // ============================================================================
425
+ /**
426
+ * Detect POST used for read operations
427
+ */
428
+ export function detectPostForReadViolations(methodUsages, file) {
429
+ const violations = [];
430
+ for (const usage of methodUsages) {
431
+ if (usage.method !== 'POST')
432
+ continue;
433
+ const context = (usage.context || '').toLowerCase();
434
+ const routePath = (usage.routePath || '').toLowerCase();
435
+ // Check if this looks like a read operation
436
+ let isReadOperation = false;
437
+ for (const keyword of READ_OPERATION_KEYWORDS) {
438
+ if (context.includes(keyword) || routePath.includes(keyword)) {
439
+ isReadOperation = true;
440
+ break;
441
+ }
442
+ }
443
+ // Also check for common read patterns in route paths
444
+ if (routePath.includes('/search') ||
445
+ routePath.includes('/find') ||
446
+ routePath.includes('/list') ||
447
+ routePath.includes('/query')) {
448
+ isReadOperation = true;
449
+ }
450
+ if (isReadOperation) {
451
+ violations.push({
452
+ type: 'post-for-read',
453
+ file,
454
+ line: usage.line,
455
+ column: usage.column,
456
+ endLine: usage.line,
457
+ endColumn: usage.column + usage.matchedText.length,
458
+ method: usage.method,
459
+ issue: `Using POST for read operation. Consider using GET for idempotent read operations.`,
460
+ suggestedFix: 'Use GET method for read operations',
461
+ suggestedMethod: 'GET',
462
+ lineContent: usage.context || '',
463
+ });
464
+ }
465
+ }
466
+ return violations;
467
+ }
468
+ /**
469
+ * Detect GET used for mutation operations
470
+ */
471
+ export function detectGetForMutationViolations(methodUsages, file) {
472
+ const violations = [];
473
+ for (const usage of methodUsages) {
474
+ if (usage.method !== 'GET')
475
+ continue;
476
+ const context = (usage.context || '').toLowerCase();
477
+ const routePath = (usage.routePath || '').toLowerCase();
478
+ // Check if this looks like a mutation operation
479
+ let isMutationOperation = false;
480
+ let suggestedMethod = 'POST';
481
+ // Check for delete operations
482
+ if (context.includes('delete') ||
483
+ context.includes('remove') ||
484
+ routePath.includes('/delete') ||
485
+ routePath.includes('/remove')) {
486
+ isMutationOperation = true;
487
+ suggestedMethod = 'DELETE';
488
+ }
489
+ // Check for create operations
490
+ else if (context.includes('create') ||
491
+ context.includes('add') ||
492
+ context.includes('insert') ||
493
+ routePath.includes('/create') ||
494
+ routePath.includes('/add')) {
495
+ isMutationOperation = true;
496
+ suggestedMethod = 'POST';
497
+ }
498
+ // Check for update operations
499
+ else if (context.includes('update') ||
500
+ context.includes('edit') ||
501
+ context.includes('modify') ||
502
+ routePath.includes('/update') ||
503
+ routePath.includes('/edit')) {
504
+ isMutationOperation = true;
505
+ suggestedMethod = 'PATCH';
506
+ }
507
+ if (isMutationOperation) {
508
+ violations.push({
509
+ type: 'get-for-mutation',
510
+ file,
511
+ line: usage.line,
512
+ column: usage.column,
513
+ endLine: usage.line,
514
+ endColumn: usage.column + usage.matchedText.length,
515
+ method: usage.method,
516
+ issue: `Using GET for mutation operation. GET requests should be idempotent and not modify server state.`,
517
+ suggestedFix: `Use ${suggestedMethod} method for this operation`,
518
+ suggestedMethod,
519
+ lineContent: usage.context || '',
520
+ });
521
+ }
522
+ }
523
+ return violations;
524
+ }
525
+ /**
526
+ * Detect PUT used when PATCH is more appropriate
527
+ */
528
+ export function detectPutForPartialUpdateViolations(methodUsages, file) {
529
+ const violations = [];
530
+ for (const usage of methodUsages) {
531
+ if (usage.method !== 'PUT')
532
+ continue;
533
+ const context = (usage.context || '').toLowerCase();
534
+ const routePath = (usage.routePath || '').toLowerCase();
535
+ // Check if this looks like a partial update operation
536
+ let isPartialUpdate = false;
537
+ for (const keyword of PARTIAL_UPDATE_KEYWORDS) {
538
+ if (context.includes(keyword) && !context.includes('replace')) {
539
+ isPartialUpdate = true;
540
+ break;
541
+ }
542
+ }
543
+ // Check route path for partial update indicators
544
+ if (routePath.includes('/patch') ||
545
+ routePath.includes('/partial') ||
546
+ (routePath.includes('/update') && !routePath.includes('/replace'))) {
547
+ isPartialUpdate = true;
548
+ }
549
+ // Check for full replacement indicators (these are OK with PUT)
550
+ for (const keyword of FULL_REPLACEMENT_KEYWORDS) {
551
+ if (context.includes(keyword) || routePath.includes(keyword)) {
552
+ isPartialUpdate = false;
553
+ break;
554
+ }
555
+ }
556
+ if (isPartialUpdate) {
557
+ violations.push({
558
+ type: 'put-for-partial',
559
+ file,
560
+ line: usage.line,
561
+ column: usage.column,
562
+ endLine: usage.line,
563
+ endColumn: usage.column + usage.matchedText.length,
564
+ method: usage.method,
565
+ issue: `Using PUT for partial update. PUT should replace the entire resource; use PATCH for partial updates.`,
566
+ suggestedFix: 'Use PATCH method for partial updates',
567
+ suggestedMethod: 'PATCH',
568
+ lineContent: usage.context || '',
569
+ });
570
+ }
571
+ }
572
+ return violations;
573
+ }
574
+ /**
575
+ * Detect inconsistent method usage across similar endpoints
576
+ */
577
+ export function detectInconsistentMethodUsage(methodUsages, file) {
578
+ const violations = [];
579
+ // Group usages by operation type
580
+ const operationGroups = new Map();
581
+ for (const usage of methodUsages) {
582
+ if (usage.operationType && usage.operationType !== 'unknown') {
583
+ const existing = operationGroups.get(usage.operationType) || [];
584
+ existing.push(usage);
585
+ operationGroups.set(usage.operationType, existing);
586
+ }
587
+ }
588
+ // Check for inconsistencies within each operation type
589
+ for (const [operationType, usages] of operationGroups) {
590
+ if (usages.length < 2)
591
+ continue;
592
+ const methodCounts = new Map();
593
+ for (const usage of usages) {
594
+ methodCounts.set(usage.method, (methodCounts.get(usage.method) || 0) + 1);
595
+ }
596
+ // Find the dominant method
597
+ let dominantMethod = null;
598
+ let maxCount = 0;
599
+ for (const [method, count] of methodCounts) {
600
+ if (count > maxCount) {
601
+ maxCount = count;
602
+ dominantMethod = method;
603
+ }
604
+ }
605
+ // Flag usages that don't match the dominant method
606
+ if (dominantMethod && methodCounts.size > 1) {
607
+ for (const usage of usages) {
608
+ if (usage.method !== dominantMethod) {
609
+ violations.push({
610
+ type: 'inconsistent-method',
611
+ file,
612
+ line: usage.line,
613
+ column: usage.column,
614
+ endLine: usage.line,
615
+ endColumn: usage.column + usage.matchedText.length,
616
+ method: usage.method,
617
+ issue: `Inconsistent HTTP method for ${operationType} operation. Most ${operationType} operations use ${dominantMethod}.`,
618
+ suggestedFix: `Consider using ${dominantMethod} for consistency`,
619
+ suggestedMethod: dominantMethod,
620
+ lineContent: usage.context || '',
621
+ });
622
+ }
623
+ }
624
+ }
625
+ }
626
+ return violations;
627
+ }
628
+ // ============================================================================
629
+ // Main Analysis Function
630
+ // ============================================================================
631
+ /**
632
+ * Analyze HTTP method patterns in a file
633
+ */
634
+ export function analyzeHttpMethods(content, file) {
635
+ // Skip excluded files
636
+ if (shouldExcludeFile(file)) {
637
+ return {
638
+ methodUsages: [],
639
+ violations: [],
640
+ methodsUsed: new Set(),
641
+ usesRestfulConventions: true,
642
+ patternAdherenceConfidence: 1.0,
643
+ };
644
+ }
645
+ // Detect all HTTP method usages
646
+ const expressHandlers = detectExpressHandlers(content, file);
647
+ const nextjsExports = detectNextjsMethodExports(content, file);
648
+ const fetchUsages = detectFetchApiUsage(content, file);
649
+ const axiosUsages = detectAxiosUsage(content, file);
650
+ const httpClientUsages = detectHttpClientUsage(content, file);
651
+ const methodUsages = [
652
+ ...expressHandlers,
653
+ ...nextjsExports,
654
+ ...fetchUsages,
655
+ ...axiosUsages,
656
+ ...httpClientUsages,
657
+ ];
658
+ // Collect all methods used
659
+ const methodsUsed = new Set();
660
+ for (const usage of methodUsages) {
661
+ methodsUsed.add(usage.method);
662
+ }
663
+ // Detect violations
664
+ const postForReadViolations = detectPostForReadViolations(methodUsages, file);
665
+ const getForMutationViolations = detectGetForMutationViolations(methodUsages, file);
666
+ const putForPartialViolations = detectPutForPartialUpdateViolations(methodUsages, file);
667
+ const inconsistentViolations = detectInconsistentMethodUsage(methodUsages, file);
668
+ const violations = [
669
+ ...postForReadViolations,
670
+ ...getForMutationViolations,
671
+ ...putForPartialViolations,
672
+ ...inconsistentViolations,
673
+ ];
674
+ // Determine if file uses RESTful conventions
675
+ const usesRestfulConventions = violations.length === 0 && methodUsages.length > 0;
676
+ // Calculate confidence
677
+ let patternAdherenceConfidence = 1.0;
678
+ if (methodUsages.length > 0 && violations.length > 0) {
679
+ patternAdherenceConfidence = Math.max(0, 1 - (violations.length / methodUsages.length));
680
+ }
681
+ else if (methodUsages.length === 0) {
682
+ patternAdherenceConfidence = 0.5; // No HTTP methods detected
683
+ }
684
+ return {
685
+ methodUsages,
686
+ violations,
687
+ methodsUsed,
688
+ usesRestfulConventions,
689
+ patternAdherenceConfidence,
690
+ };
691
+ }
692
+ // ============================================================================
693
+ // HTTP Methods Detector Class
694
+ // ============================================================================
695
+ /**
696
+ * Detector for HTTP method usage patterns
697
+ *
698
+ * Identifies HTTP method usage patterns and flags violations of RESTful conventions.
699
+ *
700
+ * @requirements 10.2 - THE API_Detector SHALL detect HTTP method usage patterns (POST vs PUT vs PATCH)
701
+ */
702
+ export class HttpMethodsDetector extends RegexDetector {
703
+ id = 'api/http-methods';
704
+ category = 'api';
705
+ subcategory = 'http-methods';
706
+ name = 'HTTP Methods Detector';
707
+ description = 'Detects HTTP method usage patterns and flags RESTful convention violations';
708
+ supportedLanguages = ['typescript', 'javascript', 'python'];
709
+ /**
710
+ * Detect HTTP method patterns and violations
711
+ */
712
+ async detect(context) {
713
+ const patterns = [];
714
+ const violations = [];
715
+ // Analyze the file
716
+ const analysis = analyzeHttpMethods(context.content, context.file);
717
+ // Create pattern matches for method usages by type
718
+ const patternTypes = new Set(analysis.methodUsages.map(u => u.type));
719
+ for (const patternType of patternTypes) {
720
+ const firstOfType = analysis.methodUsages.find(u => u.type === patternType);
721
+ if (firstOfType) {
722
+ patterns.push({
723
+ patternId: `${this.id}/${patternType}`,
724
+ location: {
725
+ file: context.file,
726
+ line: firstOfType.line,
727
+ column: firstOfType.column,
728
+ },
729
+ confidence: 1.0,
730
+ isOutlier: false,
731
+ });
732
+ }
733
+ }
734
+ // Create pattern matches for each HTTP method used
735
+ for (const method of analysis.methodsUsed) {
736
+ const firstUsage = analysis.methodUsages.find(u => u.method === method);
737
+ if (firstUsage) {
738
+ patterns.push({
739
+ patternId: `${this.id}/method-${method.toLowerCase()}`,
740
+ location: {
741
+ file: context.file,
742
+ line: firstUsage.line,
743
+ column: firstUsage.column,
744
+ },
745
+ confidence: 1.0,
746
+ isOutlier: false,
747
+ });
748
+ }
749
+ }
750
+ // Create violations
751
+ for (const violation of analysis.violations) {
752
+ violations.push(this.createViolation(violation));
753
+ }
754
+ return this.createResult(patterns, violations, analysis.patternAdherenceConfidence);
755
+ }
756
+ /**
757
+ * Create a Violation from HttpMethodViolationInfo
758
+ */
759
+ createViolation(info) {
760
+ const severityMap = {
761
+ 'post-for-read': 'warning',
762
+ 'get-for-mutation': 'error',
763
+ 'put-for-partial': 'info',
764
+ 'inconsistent-method': 'info',
765
+ 'missing-method-handler': 'info',
766
+ 'non-restful-method': 'warning',
767
+ };
768
+ const violation = {
769
+ id: `${this.id}-${info.file}-${info.line}-${info.column}`,
770
+ patternId: this.id,
771
+ severity: severityMap[info.type] || 'warning',
772
+ file: info.file,
773
+ range: {
774
+ start: { line: info.line - 1, character: info.column - 1 },
775
+ end: { line: info.endLine - 1, character: info.endColumn - 1 },
776
+ },
777
+ message: info.issue,
778
+ explanation: this.getExplanation(info.type),
779
+ expected: info.suggestedMethod || 'Appropriate HTTP method',
780
+ actual: info.method,
781
+ aiExplainAvailable: true,
782
+ aiFixAvailable: !!info.suggestedMethod,
783
+ firstSeen: new Date(),
784
+ occurrences: 1,
785
+ };
786
+ if (info.suggestedMethod) {
787
+ const quickFix = this.createQuickFixForViolation(info);
788
+ if (quickFix) {
789
+ violation.quickFix = quickFix;
790
+ }
791
+ }
792
+ return violation;
793
+ }
794
+ /**
795
+ * Get explanation for a violation type
796
+ */
797
+ getExplanation(type) {
798
+ const explanations = {
799
+ 'post-for-read': 'GET requests are idempotent and cacheable, making them ideal for read operations. ' +
800
+ 'Using POST for reads prevents caching and violates REST conventions. ' +
801
+ 'Exception: Complex queries with large payloads may use POST.',
802
+ 'get-for-mutation': 'GET requests should be safe and idempotent - they should not modify server state. ' +
803
+ 'Using GET for mutations can cause unintended side effects from browser prefetching, ' +
804
+ 'link crawlers, and cached responses.',
805
+ 'put-for-partial': 'PUT is intended to replace an entire resource. For partial updates, use PATCH. ' +
806
+ 'This follows REST semantics and makes the API behavior more predictable.',
807
+ 'inconsistent-method': 'Using different HTTP methods for similar operations makes the API harder to understand. ' +
808
+ 'Consistent method usage improves API discoverability and reduces errors.',
809
+ 'missing-method-handler': 'Common CRUD operations should have corresponding HTTP method handlers. ' +
810
+ 'Missing handlers may indicate incomplete API implementation.',
811
+ 'non-restful-method': 'RESTful APIs use HTTP methods to indicate the action being performed. ' +
812
+ 'Using verbs in URLs or non-standard methods reduces API clarity.',
813
+ };
814
+ return explanations[type] || 'Follow RESTful HTTP method conventions for consistency.';
815
+ }
816
+ /**
817
+ * Create a quick fix for a violation
818
+ */
819
+ createQuickFixForViolation(info) {
820
+ if (!info.suggestedMethod) {
821
+ return undefined;
822
+ }
823
+ // Determine the replacement text based on the pattern
824
+ const oldMethod = info.method.toLowerCase();
825
+ const newMethod = info.suggestedMethod.toLowerCase();
826
+ // Create a replacement that changes the method in the matched text
827
+ const newText = info.lineContent.replace(new RegExp(`\\b${oldMethod}\\b`, 'i'), newMethod);
828
+ return {
829
+ title: `Change HTTP method from ${info.method} to ${info.suggestedMethod}`,
830
+ kind: 'quickfix',
831
+ edit: {
832
+ changes: {
833
+ [info.file]: [
834
+ {
835
+ range: {
836
+ start: { line: info.line - 1, character: 0 },
837
+ end: { line: info.line - 1, character: info.lineContent.length },
838
+ },
839
+ newText,
840
+ },
841
+ ],
842
+ },
843
+ },
844
+ isPreferred: true,
845
+ confidence: 0.7,
846
+ preview: `Replace '${info.method}' with '${info.suggestedMethod}'`,
847
+ };
848
+ }
849
+ /**
850
+ * Generate a quick fix for a violation
851
+ */
852
+ generateQuickFix(violation) {
853
+ // Check if this is an HTTP method violation
854
+ if (!violation.patternId.startsWith('api/http-methods')) {
855
+ return null;
856
+ }
857
+ // Extract the suggested method from the expected field
858
+ const suggestedMethod = violation.expected;
859
+ if (!suggestedMethod || !HTTP_METHODS.includes(suggestedMethod)) {
860
+ return null;
861
+ }
862
+ return {
863
+ title: `Change HTTP method to ${suggestedMethod}`,
864
+ kind: 'quickfix',
865
+ edit: {
866
+ changes: {
867
+ [violation.file]: [
868
+ {
869
+ range: violation.range,
870
+ newText: suggestedMethod,
871
+ },
872
+ ],
873
+ },
874
+ },
875
+ isPreferred: true,
876
+ confidence: 0.7,
877
+ preview: `Replace '${violation.actual}' with '${suggestedMethod}'`,
878
+ };
879
+ }
880
+ }
881
+ // ============================================================================
882
+ // Factory Function
883
+ // ============================================================================
884
+ /**
885
+ * Create a new HttpMethodsDetector instance
886
+ */
887
+ export function createHttpMethodsDetector() {
888
+ return new HttpMethodsDetector();
889
+ }
890
+ //# sourceMappingURL=http-methods.js.map