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,821 @@
1
+ /**
2
+ * Import Ordering Detector - Import organization detection
3
+ *
4
+ * Detects import grouping patterns and import sorting patterns.
5
+ * Identifies how imports are organized (external packages first, then internal modules,
6
+ * then relative imports), whether they are sorted alphabetically within groups,
7
+ * and whether blank lines separate groups.
8
+ *
9
+ * @requirements 7.5 - THE Structural_Detector SHALL detect import ordering and grouping patterns
10
+ */
11
+ import { StructuralDetector } from '../base/index.js';
12
+ /**
13
+ * Common Node.js built-in modules
14
+ */
15
+ export const BUILTIN_MODULES = [
16
+ 'assert', 'buffer', 'child_process', 'cluster', 'console', 'constants',
17
+ 'crypto', 'dgram', 'dns', 'domain', 'events', 'fs', 'http', 'https',
18
+ 'module', 'net', 'os', 'path', 'perf_hooks', 'process', 'punycode',
19
+ 'querystring', 'readline', 'repl', 'stream', 'string_decoder', 'sys',
20
+ 'timers', 'tls', 'tty', 'url', 'util', 'v8', 'vm', 'worker_threads', 'zlib',
21
+ // Node.js prefixed modules
22
+ 'node:assert', 'node:buffer', 'node:child_process', 'node:cluster',
23
+ 'node:console', 'node:constants', 'node:crypto', 'node:dgram', 'node:dns',
24
+ 'node:domain', 'node:events', 'node:fs', 'node:http', 'node:https',
25
+ 'node:module', 'node:net', 'node:os', 'node:path', 'node:perf_hooks',
26
+ 'node:process', 'node:punycode', 'node:querystring', 'node:readline',
27
+ 'node:repl', 'node:stream', 'node:string_decoder', 'node:sys', 'node:timers',
28
+ 'node:tls', 'node:tty', 'node:url', 'node:util', 'node:v8', 'node:vm',
29
+ 'node:worker_threads', 'node:zlib',
30
+ ];
31
+ /**
32
+ * Common internal alias patterns
33
+ * Note: @types/ is excluded as it's an external package namespace
34
+ */
35
+ export const INTERNAL_ALIAS_PATTERNS = [
36
+ /^@\//, // @/components
37
+ /^~\//, // ~/utils
38
+ /^@(?!types\/)[a-z]+\//, // @app/, @lib/, @drift/ (but not @types/)
39
+ /^#/, // #utils (Node.js subpath imports)
40
+ ];
41
+ // ============================================================================
42
+ // Helper Functions
43
+ // ============================================================================
44
+ /**
45
+ * Python standard library modules (subset of most common)
46
+ */
47
+ export const PYTHON_STDLIB_MODULES = [
48
+ 'abc', 'argparse', 'asyncio', 'base64', 'collections', 'contextlib',
49
+ 'copy', 'csv', 'dataclasses', 'datetime', 'decimal', 'enum', 'functools',
50
+ 'hashlib', 'http', 'importlib', 'inspect', 'io', 'itertools', 'json',
51
+ 'logging', 'math', 'multiprocessing', 'os', 'pathlib', 'pickle', 'random',
52
+ 're', 'shutil', 'socket', 'sqlite3', 'ssl', 'string', 'subprocess', 'sys',
53
+ 'tempfile', 'threading', 'time', 'traceback', 'typing', 'unittest', 'urllib',
54
+ 'uuid', 'warnings', 'xml', 'zipfile',
55
+ ];
56
+ /**
57
+ * Determine the type of a Python import based on its source
58
+ */
59
+ export function getPythonImportType(source) {
60
+ // Check for standard library modules
61
+ const baseModule = source.split('.')[0] || source;
62
+ if (PYTHON_STDLIB_MODULES.includes(baseModule)) {
63
+ return 'builtin';
64
+ }
65
+ // Check for relative imports
66
+ if (source.startsWith('.')) {
67
+ if (source === '.') {
68
+ return 'index';
69
+ }
70
+ if (source.startsWith('..')) {
71
+ return 'parent';
72
+ }
73
+ return 'sibling';
74
+ }
75
+ // Everything else is external (third-party)
76
+ return 'external';
77
+ }
78
+ /**
79
+ * Parse Python import statements from file content
80
+ */
81
+ export function parsePythonImports(content) {
82
+ const imports = [];
83
+ const lines = content.split('\n');
84
+ // Python import patterns
85
+ const importPatterns = [
86
+ // import module
87
+ /^import\s+(\S+)/,
88
+ // from module import ...
89
+ /^from\s+(\S+)\s+import/,
90
+ ];
91
+ for (let i = 0; i < lines.length; i++) {
92
+ const line = lines[i];
93
+ const trimmedLine = line.trim();
94
+ const lineNumber = i + 1;
95
+ // Skip empty lines and comments
96
+ if (!trimmedLine || trimmedLine.startsWith('#')) {
97
+ continue;
98
+ }
99
+ // Skip if we're past the import section (Python convention: imports at top)
100
+ if (!trimmedLine.startsWith('import') && !trimmedLine.startsWith('from') &&
101
+ imports.length > 0 && !trimmedLine.startsWith('(') && !trimmedLine.endsWith(',')) {
102
+ // Check if this looks like code (not a continuation)
103
+ if (/^(def|class|async|@|\w+\s*=)/.test(trimmedLine)) {
104
+ break;
105
+ }
106
+ }
107
+ // Try to match import patterns
108
+ for (const pattern of importPatterns) {
109
+ const match = trimmedLine.match(pattern);
110
+ if (match && match[1]) {
111
+ const source = match[1];
112
+ imports.push({
113
+ source,
114
+ type: getPythonImportType(source),
115
+ line: lineNumber,
116
+ statement: trimmedLine,
117
+ isTypeOnly: trimmedLine.includes('TYPE_CHECKING') || trimmedLine.includes('typing'),
118
+ isSideEffect: false,
119
+ });
120
+ break;
121
+ }
122
+ }
123
+ }
124
+ return imports;
125
+ }
126
+ /**
127
+ * Determine the type of an import based on its source
128
+ */
129
+ export function getImportType(source) {
130
+ // Check for built-in modules
131
+ const baseModule = source.split('/')[0] || source;
132
+ if (BUILTIN_MODULES.includes(baseModule)) {
133
+ return 'builtin';
134
+ }
135
+ // Check for internal aliases
136
+ for (const pattern of INTERNAL_ALIAS_PATTERNS) {
137
+ if (pattern.test(source)) {
138
+ return 'internal';
139
+ }
140
+ }
141
+ // Check for relative imports
142
+ if (source === '.' || source === './') {
143
+ return 'index';
144
+ }
145
+ if (source.startsWith('./')) {
146
+ return 'sibling';
147
+ }
148
+ if (source.startsWith('../')) {
149
+ return 'parent';
150
+ }
151
+ // Everything else is external (from node_modules)
152
+ return 'external';
153
+ }
154
+ /**
155
+ * Parse import statements from file content
156
+ */
157
+ export function parseImports(content, filePath) {
158
+ // Use Python parser for .py files
159
+ if (filePath?.endsWith('.py')) {
160
+ return parsePythonImports(content);
161
+ }
162
+ const imports = [];
163
+ const lines = content.split('\n');
164
+ // Regex patterns for different import styles
165
+ const importPatterns = [
166
+ // Standard import: import { foo } from 'bar'
167
+ /^import\s+(?:type\s+)?(?:\{[^}]*\}|\*\s+as\s+\w+|\w+(?:\s*,\s*\{[^}]*\})?)\s+from\s+['"]([^'"]+)['"]/,
168
+ // Side-effect import: import 'bar'
169
+ /^import\s+['"]([^'"]+)['"]/,
170
+ // Dynamic import at top level (less common but valid)
171
+ /^(?:const|let|var)\s+\w+\s*=\s*(?:await\s+)?import\s*\(\s*['"]([^'"]+)['"]\s*\)/,
172
+ ];
173
+ let inMultilineImport = false;
174
+ let multilineStart = 0;
175
+ let multilineContent = '';
176
+ for (let i = 0; i < lines.length; i++) {
177
+ const line = lines[i];
178
+ const trimmedLine = line.trim();
179
+ const lineNumber = i + 1;
180
+ // Skip empty lines and comments
181
+ if (!trimmedLine || trimmedLine.startsWith('//') || trimmedLine.startsWith('/*')) {
182
+ continue;
183
+ }
184
+ // Handle multiline imports
185
+ if (inMultilineImport) {
186
+ multilineContent += ' ' + trimmedLine;
187
+ if (trimmedLine.includes('from')) {
188
+ inMultilineImport = false;
189
+ const fullStatement = multilineContent;
190
+ for (const pattern of importPatterns) {
191
+ const match = fullStatement.match(pattern);
192
+ if (match && match[1]) {
193
+ const source = match[1];
194
+ imports.push({
195
+ source,
196
+ type: getImportType(source),
197
+ line: multilineStart,
198
+ statement: fullStatement,
199
+ isTypeOnly: fullStatement.includes('import type'),
200
+ isSideEffect: !fullStatement.includes('from'),
201
+ });
202
+ break;
203
+ }
204
+ }
205
+ multilineContent = '';
206
+ }
207
+ continue;
208
+ }
209
+ // Check if this is the start of a multiline import
210
+ if (trimmedLine.startsWith('import') && !trimmedLine.includes('from') && !trimmedLine.match(/^import\s+['"]/)) {
211
+ inMultilineImport = true;
212
+ multilineStart = lineNumber;
213
+ multilineContent = trimmedLine;
214
+ continue;
215
+ }
216
+ // Try to match single-line imports
217
+ for (const pattern of importPatterns) {
218
+ const match = trimmedLine.match(pattern);
219
+ if (match && match[1]) {
220
+ const source = match[1];
221
+ imports.push({
222
+ source,
223
+ type: getImportType(source),
224
+ line: lineNumber,
225
+ statement: trimmedLine,
226
+ isTypeOnly: trimmedLine.includes('import type'),
227
+ isSideEffect: !trimmedLine.includes('from'),
228
+ });
229
+ break;
230
+ }
231
+ }
232
+ }
233
+ return imports;
234
+ }
235
+ /**
236
+ * Check if imports are sorted alphabetically
237
+ */
238
+ export function areImportsSorted(imports) {
239
+ if (imports.length <= 1) {
240
+ return true;
241
+ }
242
+ for (let i = 1; i < imports.length; i++) {
243
+ const prev = imports[i - 1].source.toLowerCase();
244
+ const curr = imports[i].source.toLowerCase();
245
+ if (prev > curr) {
246
+ return false;
247
+ }
248
+ }
249
+ return true;
250
+ }
251
+ /**
252
+ * Detect import groups based on blank lines and import types
253
+ */
254
+ export function detectImportGroups(imports, content) {
255
+ if (imports.length === 0) {
256
+ return [];
257
+ }
258
+ const lines = content.split('\n');
259
+ const groups = [];
260
+ let currentGroup = [];
261
+ let currentType = null;
262
+ for (let i = 0; i < imports.length; i++) {
263
+ const imp = imports[i];
264
+ const prevImp = imports[i - 1];
265
+ // Check if there's a blank line between this import and the previous one
266
+ let hasBlankLineBefore = false;
267
+ if (prevImp) {
268
+ for (let lineNum = prevImp.line; lineNum < imp.line - 1; lineNum++) {
269
+ const line = lines[lineNum];
270
+ if (line !== undefined && line.trim() === '') {
271
+ hasBlankLineBefore = true;
272
+ break;
273
+ }
274
+ }
275
+ }
276
+ // Start a new group if:
277
+ // 1. This is the first import
278
+ // 2. There's a blank line before this import
279
+ // 3. The import type changed (and we're detecting type-based grouping)
280
+ const _typeChanged = currentType !== null && imp.type !== currentType;
281
+ void _typeChanged; // Suppress unused variable warning - kept for future type-based grouping detection
282
+ const shouldStartNewGroup = currentGroup.length === 0 || hasBlankLineBefore;
283
+ if (shouldStartNewGroup && currentGroup.length > 0) {
284
+ groups.push({
285
+ type: currentType,
286
+ imports: currentGroup,
287
+ startLine: currentGroup[0].line,
288
+ endLine: currentGroup[currentGroup.length - 1].line,
289
+ isSorted: areImportsSorted(currentGroup),
290
+ });
291
+ currentGroup = [];
292
+ }
293
+ currentGroup.push(imp);
294
+ currentType = imp.type;
295
+ }
296
+ // Add the last group
297
+ if (currentGroup.length > 0) {
298
+ groups.push({
299
+ type: currentType,
300
+ imports: currentGroup,
301
+ startLine: currentGroup[0].line,
302
+ endLine: currentGroup[currentGroup.length - 1].line,
303
+ isSorted: areImportsSorted(currentGroup),
304
+ });
305
+ }
306
+ return groups;
307
+ }
308
+ /**
309
+ * Check if groups are separated by blank lines
310
+ */
311
+ export function hasBlankLineSeparators(groups, content) {
312
+ if (groups.length <= 1) {
313
+ return true; // No separators needed for single group
314
+ }
315
+ const lines = content.split('\n');
316
+ for (let i = 1; i < groups.length; i++) {
317
+ const prevGroup = groups[i - 1];
318
+ const currGroup = groups[i];
319
+ // Check for blank line between groups
320
+ let hasBlankLine = false;
321
+ for (let lineNum = prevGroup.endLine; lineNum < currGroup.startLine - 1; lineNum++) {
322
+ const line = lines[lineNum];
323
+ if (line !== undefined && line.trim() === '') {
324
+ hasBlankLine = true;
325
+ break;
326
+ }
327
+ }
328
+ if (!hasBlankLine) {
329
+ return false;
330
+ }
331
+ }
332
+ return true;
333
+ }
334
+ /**
335
+ * Check if imports are grouped by type
336
+ */
337
+ export function areImportsGroupedByType(groups) {
338
+ if (groups.length === 0) {
339
+ return true;
340
+ }
341
+ // Check if each group contains only one type of import
342
+ for (const group of groups) {
343
+ const types = new Set(group.imports.map(imp => imp.type));
344
+ if (types.size > 1) {
345
+ return false;
346
+ }
347
+ }
348
+ return true;
349
+ }
350
+ /**
351
+ * Get the order of import types from groups
352
+ */
353
+ export function getGroupOrder(groups) {
354
+ const order = [];
355
+ const seen = new Set();
356
+ for (const group of groups) {
357
+ for (const imp of group.imports) {
358
+ if (!seen.has(imp.type)) {
359
+ seen.add(imp.type);
360
+ order.push(imp.type);
361
+ }
362
+ }
363
+ }
364
+ return order;
365
+ }
366
+ /**
367
+ * Analyze import ordering in a single file
368
+ */
369
+ export function analyzeFileImports(content, filePath) {
370
+ const imports = parseImports(content, filePath);
371
+ const groups = detectImportGroups(imports, content);
372
+ const isGrouped = areImportsGroupedByType(groups);
373
+ const hasSeparators = hasBlankLineSeparators(groups, content);
374
+ const isSortedWithinGroups = groups.every(g => g.isSorted);
375
+ const groupOrder = getGroupOrder(groups);
376
+ return {
377
+ imports,
378
+ groups,
379
+ isGrouped,
380
+ hasBlankLineSeparators: hasSeparators,
381
+ isSortedWithinGroups,
382
+ groupOrder,
383
+ };
384
+ }
385
+ /**
386
+ * Analyze import ordering patterns across multiple files
387
+ */
388
+ export function analyzeImportOrdering(fileContents) {
389
+ let filesAnalyzed = 0;
390
+ let filesWithGroupedImports = 0;
391
+ let filesWithSortedImports = 0;
392
+ let filesWithBlankLineSeparators = 0;
393
+ const groupOrders = [];
394
+ for (const [filePath, content] of fileContents) {
395
+ const analysis = analyzeFileImports(content, filePath);
396
+ // Skip files with no imports or only one import
397
+ if (analysis.imports.length <= 1) {
398
+ continue;
399
+ }
400
+ filesAnalyzed++;
401
+ if (analysis.isGrouped) {
402
+ filesWithGroupedImports++;
403
+ }
404
+ if (analysis.isSortedWithinGroups) {
405
+ filesWithSortedImports++;
406
+ }
407
+ if (analysis.hasBlankLineSeparators) {
408
+ filesWithBlankLineSeparators++;
409
+ }
410
+ if (analysis.groupOrder.length > 0) {
411
+ groupOrders.push(analysis.groupOrder);
412
+ }
413
+ }
414
+ // Calculate patterns
415
+ let groupingPattern;
416
+ let sortingPattern;
417
+ let confidence;
418
+ if (filesAnalyzed === 0) {
419
+ return {
420
+ groupingPattern: 'unknown',
421
+ sortingPattern: 'unknown',
422
+ confidence: 0,
423
+ filesAnalyzed: 0,
424
+ filesWithGroupedImports: 0,
425
+ filesWithSortedImports: 0,
426
+ filesWithBlankLineSeparators: 0,
427
+ dominantGroupOrder: [],
428
+ patternConsistency: 0,
429
+ };
430
+ }
431
+ const groupedRatio = filesWithGroupedImports / filesAnalyzed;
432
+ const sortedRatio = filesWithSortedImports / filesAnalyzed;
433
+ // Determine grouping pattern
434
+ if (groupedRatio >= 0.8) {
435
+ groupingPattern = 'grouped';
436
+ }
437
+ else if (groupedRatio <= 0.2) {
438
+ groupingPattern = 'ungrouped';
439
+ }
440
+ else {
441
+ groupingPattern = 'mixed';
442
+ }
443
+ // Determine sorting pattern
444
+ if (sortedRatio >= 0.8) {
445
+ sortingPattern = 'alphabetical';
446
+ }
447
+ else if (sortedRatio <= 0.2) {
448
+ sortingPattern = 'unsorted';
449
+ }
450
+ else {
451
+ sortingPattern = 'mixed';
452
+ }
453
+ // Find dominant group order
454
+ const dominantGroupOrder = findDominantGroupOrder(groupOrders);
455
+ // Calculate pattern consistency
456
+ const patternConsistency = calculatePatternConsistency(groupOrders, dominantGroupOrder);
457
+ // Calculate overall confidence
458
+ confidence = (groupedRatio + sortedRatio + patternConsistency) / 3;
459
+ return {
460
+ groupingPattern,
461
+ sortingPattern,
462
+ confidence,
463
+ filesAnalyzed,
464
+ filesWithGroupedImports,
465
+ filesWithSortedImports,
466
+ filesWithBlankLineSeparators,
467
+ dominantGroupOrder,
468
+ patternConsistency,
469
+ };
470
+ }
471
+ /**
472
+ * Find the most common group order
473
+ */
474
+ function findDominantGroupOrder(groupOrders) {
475
+ if (groupOrders.length === 0) {
476
+ return [];
477
+ }
478
+ // Convert orders to strings for comparison
479
+ const orderCounts = new Map();
480
+ for (const order of groupOrders) {
481
+ const key = order.join(',');
482
+ if (!orderCounts.has(key)) {
483
+ orderCounts.set(key, { order, count: 0 });
484
+ }
485
+ orderCounts.get(key).count++;
486
+ }
487
+ // Find the most common order
488
+ let maxCount = 0;
489
+ let dominantOrder = [];
490
+ for (const { order, count } of orderCounts.values()) {
491
+ if (count > maxCount) {
492
+ maxCount = count;
493
+ dominantOrder = order;
494
+ }
495
+ }
496
+ return dominantOrder;
497
+ }
498
+ /**
499
+ * Calculate how consistently files follow the dominant pattern
500
+ */
501
+ function calculatePatternConsistency(groupOrders, dominantOrder) {
502
+ if (groupOrders.length === 0 || dominantOrder.length === 0) {
503
+ return 0;
504
+ }
505
+ const dominantKey = dominantOrder.join(',');
506
+ let matchingFiles = 0;
507
+ for (const order of groupOrders) {
508
+ if (order.join(',') === dominantKey) {
509
+ matchingFiles++;
510
+ }
511
+ }
512
+ return matchingFiles / groupOrders.length;
513
+ }
514
+ /**
515
+ * Get the expected group order description
516
+ */
517
+ export function getGroupOrderDescription(order) {
518
+ if (order.length === 0) {
519
+ return 'no specific order';
520
+ }
521
+ const typeNames = {
522
+ builtin: 'Node.js built-ins',
523
+ external: 'external packages',
524
+ internal: 'internal aliases',
525
+ parent: 'parent imports',
526
+ sibling: 'sibling imports',
527
+ index: 'index imports',
528
+ };
529
+ return order.map(t => typeNames[t]).join(' → ');
530
+ }
531
+ // ============================================================================
532
+ // Import Ordering Detector Class
533
+ // ============================================================================
534
+ /**
535
+ * Detector for import ordering and grouping patterns
536
+ *
537
+ * Identifies how imports are organized in a project:
538
+ * - Grouping by type (external, internal, relative)
539
+ * - Alphabetical sorting within groups
540
+ * - Blank line separators between groups
541
+ *
542
+ * @requirements 7.5 - THE Structural_Detector SHALL detect import ordering and grouping patterns
543
+ */
544
+ export class ImportOrderingDetector extends StructuralDetector {
545
+ id = 'structural/import-ordering';
546
+ category = 'structural';
547
+ subcategory = 'import-ordering';
548
+ name = 'Import Ordering Detector';
549
+ description = 'Detects import grouping and sorting patterns';
550
+ supportedLanguages = [
551
+ 'typescript',
552
+ 'javascript',
553
+ 'python',
554
+ ];
555
+ /**
556
+ * Detect import ordering patterns in the project
557
+ */
558
+ async detect(context) {
559
+ const patterns = [];
560
+ const violations = [];
561
+ // Analyze the current file's imports
562
+ const fileAnalysis = analyzeFileImports(context.content, context.file);
563
+ // Skip files with no imports or only one import
564
+ if (fileAnalysis.imports.length <= 1) {
565
+ return this.createResult(patterns, violations, 0);
566
+ }
567
+ // Build file contents map for project-wide analysis
568
+ const fileContents = new Map();
569
+ fileContents.set(context.file, context.content);
570
+ // Analyze project-wide patterns (using available context)
571
+ const projectAnalysis = analyzeImportOrdering(fileContents);
572
+ // Create pattern matches
573
+ if (projectAnalysis.groupingPattern !== 'unknown') {
574
+ patterns.push(this.createGroupingPattern(context.file, projectAnalysis));
575
+ }
576
+ if (projectAnalysis.sortingPattern !== 'unknown') {
577
+ patterns.push(this.createSortingPattern(context.file, projectAnalysis));
578
+ }
579
+ if (projectAnalysis.dominantGroupOrder.length > 0) {
580
+ patterns.push(this.createGroupOrderPattern(context.file, projectAnalysis));
581
+ }
582
+ // Check for violations in the current file
583
+ const groupingViolation = this.checkGroupingConsistency(context.file, fileAnalysis, projectAnalysis);
584
+ if (groupingViolation) {
585
+ violations.push(groupingViolation);
586
+ }
587
+ const sortingViolation = this.checkSortingConsistency(context.file, fileAnalysis, projectAnalysis);
588
+ if (sortingViolation) {
589
+ violations.push(sortingViolation);
590
+ }
591
+ const separatorViolation = this.checkBlankLineSeparators(context.file, fileAnalysis, projectAnalysis);
592
+ if (separatorViolation) {
593
+ violations.push(separatorViolation);
594
+ }
595
+ return this.createResult(patterns, violations, projectAnalysis.confidence);
596
+ }
597
+ /**
598
+ * Generate a quick fix for import ordering violations
599
+ */
600
+ generateQuickFix(violation) {
601
+ if (violation.patternId === 'structural/import-ordering-grouping') {
602
+ return {
603
+ title: 'Group imports by type',
604
+ kind: 'quickfix',
605
+ edit: {
606
+ changes: {},
607
+ documentChanges: [],
608
+ },
609
+ isPreferred: true,
610
+ confidence: 0.7,
611
+ preview: 'Reorganize imports into groups (external, internal, relative)',
612
+ };
613
+ }
614
+ if (violation.patternId === 'structural/import-ordering-sorting') {
615
+ return {
616
+ title: 'Sort imports alphabetically',
617
+ kind: 'quickfix',
618
+ edit: {
619
+ changes: {},
620
+ documentChanges: [],
621
+ },
622
+ isPreferred: true,
623
+ confidence: 0.8,
624
+ preview: 'Sort imports alphabetically within each group',
625
+ };
626
+ }
627
+ if (violation.patternId === 'structural/import-ordering-separators') {
628
+ return {
629
+ title: 'Add blank lines between import groups',
630
+ kind: 'quickfix',
631
+ edit: {
632
+ changes: {},
633
+ documentChanges: [],
634
+ },
635
+ isPreferred: false,
636
+ confidence: 0.6,
637
+ preview: 'Add blank lines to separate import groups',
638
+ };
639
+ }
640
+ return null;
641
+ }
642
+ /**
643
+ * Create a pattern match for import grouping
644
+ */
645
+ createGroupingPattern(file, analysis) {
646
+ return {
647
+ patternId: `import-ordering-grouping-${analysis.groupingPattern}`,
648
+ location: { file, line: 1, column: 1 },
649
+ confidence: analysis.confidence,
650
+ isOutlier: false,
651
+ };
652
+ }
653
+ /**
654
+ * Create a pattern match for import sorting
655
+ */
656
+ createSortingPattern(file, analysis) {
657
+ return {
658
+ patternId: `import-ordering-sorting-${analysis.sortingPattern}`,
659
+ location: { file, line: 1, column: 1 },
660
+ confidence: analysis.confidence,
661
+ isOutlier: false,
662
+ };
663
+ }
664
+ /**
665
+ * Create a pattern match for group order
666
+ */
667
+ createGroupOrderPattern(file, analysis) {
668
+ const orderKey = analysis.dominantGroupOrder.join('-');
669
+ return {
670
+ patternId: `import-ordering-order-${orderKey}`,
671
+ location: { file, line: 1, column: 1 },
672
+ confidence: analysis.patternConsistency,
673
+ isOutlier: false,
674
+ };
675
+ }
676
+ /**
677
+ * Check if the file's import grouping follows the project pattern
678
+ */
679
+ checkGroupingConsistency(file, fileAnalysis, projectAnalysis) {
680
+ // Skip if project pattern is unknown or mixed
681
+ if (projectAnalysis.groupingPattern === 'unknown' || projectAnalysis.groupingPattern === 'mixed') {
682
+ return null;
683
+ }
684
+ // Check if file follows the pattern
685
+ const fileIsGrouped = fileAnalysis.isGrouped;
686
+ const projectExpectsGrouped = projectAnalysis.groupingPattern === 'grouped';
687
+ if (fileIsGrouped === projectExpectsGrouped) {
688
+ return null;
689
+ }
690
+ const range = {
691
+ start: { line: 1, character: 1 },
692
+ end: { line: 1, character: 1 },
693
+ };
694
+ let message;
695
+ let expected;
696
+ let actual;
697
+ if (projectExpectsGrouped) {
698
+ message = `Imports are not grouped by type. Project uses grouped imports (${getGroupOrderDescription(projectAnalysis.dominantGroupOrder)}).`;
699
+ expected = 'imports grouped by type';
700
+ actual = 'ungrouped imports';
701
+ }
702
+ else {
703
+ message = `Imports are grouped but project uses ungrouped imports.`;
704
+ expected = 'ungrouped imports';
705
+ actual = 'grouped imports';
706
+ }
707
+ return {
708
+ id: `import-ordering-grouping-${file.replace(/[^a-zA-Z0-9]/g, '-')}`,
709
+ patternId: 'structural/import-ordering-grouping',
710
+ severity: 'info',
711
+ file,
712
+ range,
713
+ message,
714
+ expected,
715
+ actual,
716
+ aiExplainAvailable: true,
717
+ aiFixAvailable: true,
718
+ firstSeen: new Date(),
719
+ occurrences: 1,
720
+ };
721
+ }
722
+ /**
723
+ * Check if the file's import sorting follows the project pattern
724
+ */
725
+ checkSortingConsistency(file, fileAnalysis, projectAnalysis) {
726
+ // Skip if project pattern is unknown or mixed
727
+ if (projectAnalysis.sortingPattern === 'unknown' || projectAnalysis.sortingPattern === 'mixed') {
728
+ return null;
729
+ }
730
+ // Check if file follows the pattern
731
+ const fileIsSorted = fileAnalysis.isSortedWithinGroups;
732
+ const projectExpectsSorted = projectAnalysis.sortingPattern === 'alphabetical';
733
+ if (fileIsSorted === projectExpectsSorted) {
734
+ return null;
735
+ }
736
+ // Find the first unsorted group for better error reporting
737
+ const unsortedGroup = fileAnalysis.groups.find(g => !g.isSorted);
738
+ const line = unsortedGroup?.startLine || 1;
739
+ const range = {
740
+ start: { line, character: 1 },
741
+ end: { line, character: 1 },
742
+ };
743
+ let message;
744
+ let expected;
745
+ let actual;
746
+ if (projectExpectsSorted) {
747
+ message = `Imports are not sorted alphabetically. Project uses alphabetically sorted imports.`;
748
+ expected = 'alphabetically sorted imports';
749
+ actual = 'unsorted imports';
750
+ }
751
+ else {
752
+ message = `Imports are sorted but project does not enforce alphabetical sorting.`;
753
+ expected = 'no specific sorting';
754
+ actual = 'alphabetically sorted imports';
755
+ }
756
+ return {
757
+ id: `import-ordering-sorting-${file.replace(/[^a-zA-Z0-9]/g, '-')}`,
758
+ patternId: 'structural/import-ordering-sorting',
759
+ severity: 'info',
760
+ file,
761
+ range,
762
+ message,
763
+ expected,
764
+ actual,
765
+ aiExplainAvailable: true,
766
+ aiFixAvailable: true,
767
+ firstSeen: new Date(),
768
+ occurrences: 1,
769
+ };
770
+ }
771
+ /**
772
+ * Check if the file uses blank line separators between import groups
773
+ */
774
+ checkBlankLineSeparators(file, fileAnalysis, projectAnalysis) {
775
+ // Skip if project doesn't use grouped imports
776
+ if (projectAnalysis.groupingPattern !== 'grouped') {
777
+ return null;
778
+ }
779
+ // Skip if file has only one group
780
+ if (fileAnalysis.groups.length <= 1) {
781
+ return null;
782
+ }
783
+ // Check if project uses blank line separators
784
+ const projectUsesSeparators = projectAnalysis.filesWithBlankLineSeparators > projectAnalysis.filesAnalyzed * 0.7;
785
+ if (!projectUsesSeparators) {
786
+ return null;
787
+ }
788
+ // Check if file has blank line separators
789
+ if (fileAnalysis.hasBlankLineSeparators) {
790
+ return null;
791
+ }
792
+ const range = {
793
+ start: { line: 1, character: 1 },
794
+ end: { line: 1, character: 1 },
795
+ };
796
+ return {
797
+ id: `import-ordering-separators-${file.replace(/[^a-zA-Z0-9]/g, '-')}`,
798
+ patternId: 'structural/import-ordering-separators',
799
+ severity: 'info',
800
+ file,
801
+ range,
802
+ message: `Import groups are not separated by blank lines. Project uses blank lines between import groups.`,
803
+ expected: 'blank lines between import groups',
804
+ actual: 'no blank lines between import groups',
805
+ aiExplainAvailable: true,
806
+ aiFixAvailable: true,
807
+ firstSeen: new Date(),
808
+ occurrences: 1,
809
+ };
810
+ }
811
+ }
812
+ // ============================================================================
813
+ // Factory Function
814
+ // ============================================================================
815
+ /**
816
+ * Create a new ImportOrderingDetector instance
817
+ */
818
+ export function createImportOrderingDetector() {
819
+ return new ImportOrderingDetector();
820
+ }
821
+ //# sourceMappingURL=import-ordering.js.map