@nielspeter/eess-ts 0.2.0 → 0.4.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 (433) hide show
  1. package/README.md +87 -34
  2. package/dist/builders/call-rule-builder.d.ts +66 -26
  3. package/dist/builders/call-rule-builder.d.ts.map +1 -1
  4. package/dist/builders/call-rule-builder.js +73 -31
  5. package/dist/builders/call-rule-builder.js.map +1 -1
  6. package/dist/builders/class-rule-builder.d.ts +125 -26
  7. package/dist/builders/class-rule-builder.d.ts.map +1 -1
  8. package/dist/builders/class-rule-builder.js +134 -30
  9. package/dist/builders/class-rule-builder.js.map +1 -1
  10. package/dist/builders/correspondence-builder.d.ts +287 -0
  11. package/dist/builders/correspondence-builder.d.ts.map +1 -0
  12. package/dist/builders/correspondence-builder.js +393 -0
  13. package/dist/builders/correspondence-builder.js.map +1 -0
  14. package/dist/builders/correspondence-findings.d.ts +104 -0
  15. package/dist/builders/correspondence-findings.d.ts.map +1 -0
  16. package/dist/builders/correspondence-findings.js +301 -0
  17. package/dist/builders/correspondence-findings.js.map +1 -0
  18. package/dist/builders/cross-layer-builder.d.ts +99 -16
  19. package/dist/builders/cross-layer-builder.d.ts.map +1 -1
  20. package/dist/builders/cross-layer-builder.js +181 -35
  21. package/dist/builders/cross-layer-builder.js.map +1 -1
  22. package/dist/builders/function-rule-builder.d.ts +144 -25
  23. package/dist/builders/function-rule-builder.d.ts.map +1 -1
  24. package/dist/builders/function-rule-builder.js +173 -26
  25. package/dist/builders/function-rule-builder.js.map +1 -1
  26. package/dist/builders/jsx-rule-builder.d.ts +70 -14
  27. package/dist/builders/jsx-rule-builder.d.ts.map +1 -1
  28. package/dist/builders/jsx-rule-builder.js +73 -14
  29. package/dist/builders/jsx-rule-builder.js.map +1 -1
  30. package/dist/builders/module-rule-builder.d.ts +2 -2
  31. package/dist/builders/module-rule-builder.d.ts.map +1 -1
  32. package/dist/builders/module-rule-builder.js +12 -3
  33. package/dist/builders/module-rule-builder.js.map +1 -1
  34. package/dist/builders/scoped-function-rule-builder.d.ts +11 -0
  35. package/dist/builders/scoped-function-rule-builder.d.ts.map +1 -1
  36. package/dist/builders/scoped-function-rule-builder.js +12 -0
  37. package/dist/builders/scoped-function-rule-builder.js.map +1 -1
  38. package/dist/builders/slice-discovery-message.d.ts +36 -0
  39. package/dist/builders/slice-discovery-message.d.ts.map +1 -0
  40. package/dist/builders/slice-discovery-message.js +181 -0
  41. package/dist/builders/slice-discovery-message.js.map +1 -0
  42. package/dist/builders/slice-rule-builder.d.ts +151 -12
  43. package/dist/builders/slice-rule-builder.d.ts.map +1 -1
  44. package/dist/builders/slice-rule-builder.js +242 -35
  45. package/dist/builders/slice-rule-builder.js.map +1 -1
  46. package/dist/builders/type-rule-builder.d.ts +95 -24
  47. package/dist/builders/type-rule-builder.d.ts.map +1 -1
  48. package/dist/builders/type-rule-builder.js +105 -29
  49. package/dist/builders/type-rule-builder.js.map +1 -1
  50. package/dist/{helpers → builders}/within.d.ts +2 -2
  51. package/dist/builders/within.d.ts.map +1 -0
  52. package/dist/{helpers → builders}/within.js +1 -1
  53. package/dist/builders/within.js.map +1 -0
  54. package/dist/cli/commands/baseline.d.ts +3 -2
  55. package/dist/cli/commands/baseline.d.ts.map +1 -1
  56. package/dist/cli/commands/baseline.js +68 -6
  57. package/dist/cli/commands/baseline.js.map +1 -1
  58. package/dist/cli/commands/check.d.ts +7 -2
  59. package/dist/cli/commands/check.d.ts.map +1 -1
  60. package/dist/cli/commands/check.js +241 -45
  61. package/dist/cli/commands/check.js.map +1 -1
  62. package/dist/cli/commands/doctor.d.ts +29 -0
  63. package/dist/cli/commands/doctor.d.ts.map +1 -0
  64. package/dist/cli/commands/doctor.js +224 -0
  65. package/dist/cli/commands/doctor.js.map +1 -0
  66. package/dist/cli/commands/explain.d.ts +2 -1
  67. package/dist/cli/commands/explain.d.ts.map +1 -1
  68. package/dist/cli/commands/explain.js +19 -10
  69. package/dist/cli/commands/explain.js.map +1 -1
  70. package/dist/cli/commands/init.d.ts +9 -3
  71. package/dist/cli/commands/init.d.ts.map +1 -1
  72. package/dist/cli/commands/init.js +162 -137
  73. package/dist/cli/commands/init.js.map +1 -1
  74. package/dist/cli/import-rule-module.d.ts +29 -0
  75. package/dist/cli/import-rule-module.d.ts.map +1 -0
  76. package/dist/cli/import-rule-module.js +60 -0
  77. package/dist/cli/import-rule-module.js.map +1 -0
  78. package/dist/cli/index.d.ts +2 -2
  79. package/dist/cli/index.d.ts.map +1 -1
  80. package/dist/cli/index.js +98 -33
  81. package/dist/cli/index.js.map +1 -1
  82. package/dist/cli/load-rules.d.ts +6 -11
  83. package/dist/cli/load-rules.d.ts.map +1 -1
  84. package/dist/cli/load-rules.js +21 -29
  85. package/dist/cli/load-rules.js.map +1 -1
  86. package/dist/cli/resolve-config.d.ts.map +1 -1
  87. package/dist/cli/resolve-config.js +24 -14
  88. package/dist/cli/resolve-config.js.map +1 -1
  89. package/dist/cli/rule-file-findings.d.ts +178 -0
  90. package/dist/cli/rule-file-findings.d.ts.map +1 -0
  91. package/dist/cli/rule-file-findings.js +293 -0
  92. package/dist/cli/rule-file-findings.js.map +1 -0
  93. package/dist/cli/watch.d.ts +20 -7
  94. package/dist/cli/watch.d.ts.map +1 -1
  95. package/dist/cli/watch.js +39 -14
  96. package/dist/cli/watch.js.map +1 -1
  97. package/dist/conditions/body-analysis-function.d.ts.map +1 -1
  98. package/dist/conditions/body-analysis-function.js +16 -7
  99. package/dist/conditions/body-analysis-function.js.map +1 -1
  100. package/dist/conditions/body-analysis-module.d.ts.map +1 -1
  101. package/dist/conditions/body-analysis-module.js +14 -9
  102. package/dist/conditions/body-analysis-module.js.map +1 -1
  103. package/dist/conditions/body-analysis.d.ts.map +1 -1
  104. package/dist/conditions/body-analysis.js +16 -7
  105. package/dist/conditions/body-analysis.js.map +1 -1
  106. package/dist/conditions/call.d.ts.map +1 -1
  107. package/dist/conditions/call.js +38 -17
  108. package/dist/conditions/call.js.map +1 -1
  109. package/dist/conditions/catch-analysis.d.ts +2 -1
  110. package/dist/conditions/catch-analysis.d.ts.map +1 -1
  111. package/dist/conditions/catch-analysis.js.map +1 -1
  112. package/dist/conditions/cross-layer.d.ts +2 -10
  113. package/dist/conditions/cross-layer.d.ts.map +1 -1
  114. package/dist/conditions/cross-layer.js +227 -23
  115. package/dist/conditions/cross-layer.js.map +1 -1
  116. package/dist/conditions/dependency.d.ts +35 -6
  117. package/dist/conditions/dependency.d.ts.map +1 -1
  118. package/dist/conditions/dependency.js +299 -45
  119. package/dist/conditions/dependency.js.map +1 -1
  120. package/dist/conditions/exports.d.ts.map +1 -1
  121. package/dist/conditions/exports.js +10 -0
  122. package/dist/conditions/exports.js.map +1 -1
  123. package/dist/conditions/function.d.ts.map +1 -1
  124. package/dist/conditions/function.js +19 -5
  125. package/dist/conditions/function.js.map +1 -1
  126. package/dist/conditions/helpers.d.ts +2 -1
  127. package/dist/conditions/helpers.d.ts.map +1 -1
  128. package/dist/conditions/helpers.js +4 -1
  129. package/dist/conditions/helpers.js.map +1 -1
  130. package/dist/conditions/jsx.d.ts.map +1 -1
  131. package/dist/conditions/jsx.js +7 -2
  132. package/dist/conditions/jsx.js.map +1 -1
  133. package/dist/conditions/match-identity.d.ts +43 -0
  134. package/dist/conditions/match-identity.d.ts.map +1 -0
  135. package/dist/conditions/match-identity.js +43 -0
  136. package/dist/conditions/match-identity.js.map +1 -0
  137. package/dist/conditions/members.d.ts.map +1 -1
  138. package/dist/conditions/members.js +17 -4
  139. package/dist/conditions/members.js.map +1 -1
  140. package/dist/conditions/reverse-dependency.d.ts +18 -5
  141. package/dist/conditions/reverse-dependency.d.ts.map +1 -1
  142. package/dist/conditions/reverse-dependency.js +109 -92
  143. package/dist/conditions/reverse-dependency.js.map +1 -1
  144. package/dist/conditions/slice.d.ts +86 -2
  145. package/dist/conditions/slice.d.ts.map +1 -1
  146. package/dist/conditions/slice.js +234 -53
  147. package/dist/conditions/slice.js.map +1 -1
  148. package/dist/conditions/structural.d.ts.map +1 -1
  149. package/dist/conditions/structural.js +16 -4
  150. package/dist/conditions/structural.js.map +1 -1
  151. package/dist/core/check-all.d.ts +19 -0
  152. package/dist/core/check-all.d.ts.map +1 -0
  153. package/dist/core/check-all.js +96 -0
  154. package/dist/core/check-all.js.map +1 -0
  155. package/dist/core/combinators.d.ts +48 -0
  156. package/dist/core/combinators.d.ts.map +1 -0
  157. package/dist/core/combinators.js +56 -0
  158. package/dist/core/combinators.js.map +1 -0
  159. package/dist/core/descendant-cache.d.ts +36 -0
  160. package/dist/core/descendant-cache.d.ts.map +1 -0
  161. package/dist/core/descendant-cache.js +119 -0
  162. package/dist/core/descendant-cache.js.map +1 -0
  163. package/dist/core/diagnose.d.ts +234 -0
  164. package/dist/core/diagnose.d.ts.map +1 -0
  165. package/dist/core/diagnose.js +382 -0
  166. package/dist/core/diagnose.js.map +1 -0
  167. package/dist/core/disk-set.d.ts +48 -0
  168. package/dist/core/disk-set.d.ts.map +1 -0
  169. package/dist/core/disk-set.js +218 -0
  170. package/dist/core/disk-set.js.map +1 -0
  171. package/dist/core/element-cache.d.ts +75 -0
  172. package/dist/core/element-cache.d.ts.map +1 -0
  173. package/dist/core/element-cache.js +32 -0
  174. package/dist/core/element-cache.js.map +1 -0
  175. package/dist/core/empty-project-advice.d.ts +75 -0
  176. package/dist/core/empty-project-advice.d.ts.map +1 -0
  177. package/dist/core/empty-project-advice.js +61 -0
  178. package/dist/core/empty-project-advice.js.map +1 -0
  179. package/dist/core/exclusion-comments.d.ts +54 -0
  180. package/dist/core/exclusion-comments.d.ts.map +1 -0
  181. package/dist/core/exclusion-comments.js +310 -0
  182. package/dist/core/exclusion-comments.js.map +1 -0
  183. package/dist/core/execute-rule.d.ts +150 -0
  184. package/dist/core/execute-rule.d.ts.map +1 -0
  185. package/dist/core/execute-rule.js +580 -0
  186. package/dist/core/execute-rule.js.map +1 -0
  187. package/dist/core/glob-diagnosis.d.ts +78 -0
  188. package/dist/core/glob-diagnosis.d.ts.map +1 -0
  189. package/dist/core/glob-diagnosis.js +134 -0
  190. package/dist/core/glob-diagnosis.js.map +1 -0
  191. package/dist/core/glob-evaluator.d.ts +48 -0
  192. package/dist/core/glob-evaluator.d.ts.map +1 -0
  193. package/dist/core/glob-evaluator.js +89 -0
  194. package/dist/core/glob-evaluator.js.map +1 -0
  195. package/dist/core/import-candidates.d.ts +60 -0
  196. package/dist/core/import-candidates.d.ts.map +1 -0
  197. package/dist/core/import-candidates.js +93 -0
  198. package/dist/core/import-candidates.js.map +1 -0
  199. package/dist/core/import-options.d.ts +55 -2
  200. package/dist/core/import-options.d.ts.map +1 -1
  201. package/dist/core/import-options.js +64 -0
  202. package/dist/core/import-options.js.map +1 -1
  203. package/dist/core/line-index.d.ts +3 -0
  204. package/dist/core/line-index.d.ts.map +1 -0
  205. package/dist/core/line-index.js +229 -0
  206. package/dist/core/line-index.js.map +1 -0
  207. package/dist/core/metric-violation.d.ts +86 -0
  208. package/dist/core/metric-violation.d.ts.map +1 -0
  209. package/dist/core/metric-violation.js +132 -0
  210. package/dist/core/metric-violation.js.map +1 -0
  211. package/dist/core/module-edges.d.ts +361 -0
  212. package/dist/core/module-edges.d.ts.map +1 -0
  213. package/dist/core/module-edges.js +592 -0
  214. package/dist/core/module-edges.js.map +1 -0
  215. package/dist/core/object-literal-functions.d.ts +42 -0
  216. package/dist/core/object-literal-functions.d.ts.map +1 -0
  217. package/dist/core/object-literal-functions.js +75 -0
  218. package/dist/core/object-literal-functions.js.map +1 -0
  219. package/dist/core/orphan-exclusions.d.ts +44 -0
  220. package/dist/core/orphan-exclusions.d.ts.map +1 -0
  221. package/dist/core/orphan-exclusions.js +214 -0
  222. package/dist/core/orphan-exclusions.js.map +1 -0
  223. package/dist/core/pair-condition.d.ts +32 -3
  224. package/dist/core/pair-condition.d.ts.map +1 -1
  225. package/dist/core/path-universe.d.ts +54 -0
  226. package/dist/core/path-universe.d.ts.map +1 -0
  227. package/dist/core/path-universe.js +65 -0
  228. package/dist/core/path-universe.js.map +1 -0
  229. package/dist/core/per-root-compiler-options.d.ts +20 -0
  230. package/dist/core/per-root-compiler-options.d.ts.map +1 -0
  231. package/dist/core/per-root-compiler-options.js +57 -0
  232. package/dist/core/per-root-compiler-options.js.map +1 -0
  233. package/dist/core/project-relative.d.ts +98 -0
  234. package/dist/core/project-relative.d.ts.map +1 -0
  235. package/dist/core/project-relative.js +185 -0
  236. package/dist/core/project-relative.js.map +1 -0
  237. package/dist/core/project.d.ts +7 -1
  238. package/dist/core/project.d.ts.map +1 -1
  239. package/dist/core/project.js +24 -0
  240. package/dist/core/project.js.map +1 -1
  241. package/dist/core/rule-builder.d.ts +282 -0
  242. package/dist/core/rule-builder.d.ts.map +1 -0
  243. package/dist/core/rule-builder.js +445 -0
  244. package/dist/core/rule-builder.js.map +1 -0
  245. package/dist/core/rule-declaration.d.ts +32 -0
  246. package/dist/core/rule-declaration.d.ts.map +1 -0
  247. package/dist/core/rule-declaration.js +126 -0
  248. package/dist/core/rule-declaration.js.map +1 -0
  249. package/dist/core/terminal-builder.d.ts +625 -0
  250. package/dist/core/terminal-builder.d.ts.map +1 -0
  251. package/dist/core/terminal-builder.js +787 -0
  252. package/dist/core/terminal-builder.js.map +1 -0
  253. package/dist/core/terminal-execution.d.ts +23 -0
  254. package/dist/core/terminal-execution.d.ts.map +1 -0
  255. package/dist/core/terminal-execution.js +71 -0
  256. package/dist/core/terminal-execution.js.map +1 -0
  257. package/dist/core/vacuity-diagnosis.d.ts +103 -0
  258. package/dist/core/vacuity-diagnosis.d.ts.map +1 -0
  259. package/dist/core/vacuity-diagnosis.js +415 -0
  260. package/dist/core/vacuity-diagnosis.js.map +1 -0
  261. package/dist/core/violation.d.ts +16 -11
  262. package/dist/core/violation.d.ts.map +1 -1
  263. package/dist/core/violation.js +33 -13
  264. package/dist/core/violation.js.map +1 -1
  265. package/dist/graphql/index.js +1 -1
  266. package/dist/graphql/index.js.map +1 -1
  267. package/dist/graphql/resolver-rule-builder.d.ts +98 -23
  268. package/dist/graphql/resolver-rule-builder.d.ts.map +1 -1
  269. package/dist/graphql/resolver-rule-builder.js +151 -21
  270. package/dist/graphql/resolver-rule-builder.js.map +1 -1
  271. package/dist/graphql/schema-loader.d.ts +21 -0
  272. package/dist/graphql/schema-loader.d.ts.map +1 -1
  273. package/dist/graphql/schema-loader.js +81 -12
  274. package/dist/graphql/schema-loader.js.map +1 -1
  275. package/dist/graphql/schema-rule-builder.d.ts +57 -20
  276. package/dist/graphql/schema-rule-builder.d.ts.map +1 -1
  277. package/dist/graphql/schema-rule-builder.js +101 -25
  278. package/dist/graphql/schema-rule-builder.js.map +1 -1
  279. package/dist/helpers/baseline-diagnostics.d.ts +45 -0
  280. package/dist/helpers/baseline-diagnostics.d.ts.map +1 -0
  281. package/dist/helpers/baseline-diagnostics.js +168 -0
  282. package/dist/helpers/baseline-diagnostics.js.map +1 -0
  283. package/dist/helpers/baseline-generator.d.ts +19 -0
  284. package/dist/helpers/baseline-generator.d.ts.map +1 -0
  285. package/dist/helpers/baseline-generator.js +18 -0
  286. package/dist/helpers/baseline-generator.js.map +1 -0
  287. package/dist/helpers/baseline.d.ts +336 -0
  288. package/dist/helpers/baseline.d.ts.map +1 -0
  289. package/dist/helpers/baseline.js +664 -0
  290. package/dist/helpers/baseline.js.map +1 -0
  291. package/dist/helpers/body-traversal.d.ts +27 -2
  292. package/dist/helpers/body-traversal.d.ts.map +1 -1
  293. package/dist/helpers/body-traversal.js +122 -16
  294. package/dist/helpers/body-traversal.js.map +1 -1
  295. package/dist/helpers/callback-extractor.d.ts.map +1 -1
  296. package/dist/helpers/callback-extractor.js +48 -47
  297. package/dist/helpers/callback-extractor.js.map +1 -1
  298. package/dist/helpers/complexity.d.ts +13 -5
  299. package/dist/helpers/complexity.d.ts.map +1 -1
  300. package/dist/helpers/complexity.js +15 -6
  301. package/dist/helpers/complexity.js.map +1 -1
  302. package/dist/helpers/diff-aware.d.ts +44 -0
  303. package/dist/helpers/diff-aware.d.ts.map +1 -0
  304. package/dist/helpers/diff-aware.js +84 -0
  305. package/dist/helpers/diff-aware.js.map +1 -0
  306. package/dist/helpers/matchers.d.ts +68 -7
  307. package/dist/helpers/matchers.d.ts.map +1 -1
  308. package/dist/helpers/matchers.js +114 -20
  309. package/dist/helpers/matchers.js.map +1 -1
  310. package/dist/helpers/slice-graph.d.ts +100 -8
  311. package/dist/helpers/slice-graph.d.ts.map +1 -1
  312. package/dist/helpers/slice-graph.js +126 -34
  313. package/dist/helpers/slice-graph.js.map +1 -1
  314. package/dist/helpers/tarjan.d.ts +0 -14
  315. package/dist/helpers/tarjan.d.ts.map +1 -1
  316. package/dist/helpers/tarjan.js +29 -16
  317. package/dist/helpers/tarjan.js.map +1 -1
  318. package/dist/index.d.ts +56 -17
  319. package/dist/index.d.ts.map +1 -1
  320. package/dist/index.js +57 -13
  321. package/dist/index.js.map +1 -1
  322. package/dist/models/arch-call.d.ts +3 -2
  323. package/dist/models/arch-call.d.ts.map +1 -1
  324. package/dist/models/arch-call.js.map +1 -1
  325. package/dist/models/arch-function.d.ts +28 -6
  326. package/dist/models/arch-function.d.ts.map +1 -1
  327. package/dist/models/arch-function.js +106 -3
  328. package/dist/models/arch-function.js.map +1 -1
  329. package/dist/models/arch-jsx-element.js +2 -2
  330. package/dist/models/arch-jsx-element.js.map +1 -1
  331. package/dist/models/slice.d.ts +33 -9
  332. package/dist/models/slice.d.ts.map +1 -1
  333. package/dist/models/slice.js +129 -19
  334. package/dist/models/slice.js.map +1 -1
  335. package/dist/predicates/call.d.ts.map +1 -1
  336. package/dist/predicates/call.js +5 -0
  337. package/dist/predicates/call.js.map +1 -1
  338. package/dist/predicates/identity.d.ts +21 -0
  339. package/dist/predicates/identity.d.ts.map +1 -1
  340. package/dist/predicates/identity.js +75 -3
  341. package/dist/predicates/identity.js.map +1 -1
  342. package/dist/predicates/index.d.ts +1 -1
  343. package/dist/predicates/index.d.ts.map +1 -1
  344. package/dist/predicates/index.js +1 -1
  345. package/dist/predicates/index.js.map +1 -1
  346. package/dist/predicates/metrics.d.ts +4 -2
  347. package/dist/predicates/metrics.d.ts.map +1 -1
  348. package/dist/predicates/metrics.js +4 -2
  349. package/dist/predicates/metrics.js.map +1 -1
  350. package/dist/predicates/module.d.ts +4 -12
  351. package/dist/predicates/module.d.ts.map +1 -1
  352. package/dist/predicates/module.js +57 -37
  353. package/dist/predicates/module.js.map +1 -1
  354. package/dist/presets/agent-guardrails.d.ts +22 -15
  355. package/dist/presets/agent-guardrails.d.ts.map +1 -1
  356. package/dist/presets/agent-guardrails.js +124 -19
  357. package/dist/presets/agent-guardrails.js.map +1 -1
  358. package/dist/presets/boundaries.d.ts +45 -2
  359. package/dist/presets/boundaries.d.ts.map +1 -1
  360. package/dist/presets/boundaries.js +132 -23
  361. package/dist/presets/boundaries.js.map +1 -1
  362. package/dist/presets/data-layer.d.ts +22 -2
  363. package/dist/presets/data-layer.d.ts.map +1 -1
  364. package/dist/presets/data-layer.js +58 -16
  365. package/dist/presets/data-layer.js.map +1 -1
  366. package/dist/presets/index.d.ts +7 -5
  367. package/dist/presets/index.d.ts.map +1 -1
  368. package/dist/presets/index.js +9 -3
  369. package/dist/presets/index.js.map +1 -1
  370. package/dist/presets/layered.d.ts +46 -2
  371. package/dist/presets/layered.d.ts.map +1 -1
  372. package/dist/presets/layered.js +66 -29
  373. package/dist/presets/layered.js.map +1 -1
  374. package/dist/presets/recommended.d.ts +80 -9
  375. package/dist/presets/recommended.d.ts.map +1 -1
  376. package/dist/presets/recommended.js +25 -23
  377. package/dist/presets/recommended.js.map +1 -1
  378. package/dist/presets/shared.d.ts +270 -2
  379. package/dist/presets/shared.d.ts.map +1 -1
  380. package/dist/presets/shared.js +338 -4
  381. package/dist/presets/shared.js.map +1 -1
  382. package/dist/rules/code-quality.d.ts.map +1 -1
  383. package/dist/rules/code-quality.js +15 -6
  384. package/dist/rules/code-quality.js.map +1 -1
  385. package/dist/rules/hygiene.d.ts +1 -1
  386. package/dist/rules/hygiene.js +1 -1
  387. package/dist/rules/metrics-function.d.ts +2 -1
  388. package/dist/rules/metrics-function.d.ts.map +1 -1
  389. package/dist/rules/metrics-function.js +33 -6
  390. package/dist/rules/metrics-function.js.map +1 -1
  391. package/dist/rules/metrics.d.ts +2 -1
  392. package/dist/rules/metrics.d.ts.map +1 -1
  393. package/dist/rules/metrics.js +39 -9
  394. package/dist/rules/metrics.js.map +1 -1
  395. package/dist/smells/duplicate-bodies.d.ts +58 -5
  396. package/dist/smells/duplicate-bodies.d.ts.map +1 -1
  397. package/dist/smells/duplicate-bodies.js +137 -56
  398. package/dist/smells/duplicate-bodies.js.map +1 -1
  399. package/dist/smells/fingerprint.d.ts +8 -1
  400. package/dist/smells/fingerprint.d.ts.map +1 -1
  401. package/dist/smells/fingerprint.js +21 -3
  402. package/dist/smells/fingerprint.js.map +1 -1
  403. package/dist/smells/inconsistent-siblings.d.ts +128 -7
  404. package/dist/smells/inconsistent-siblings.d.ts.map +1 -1
  405. package/dist/smells/inconsistent-siblings.js +288 -86
  406. package/dist/smells/inconsistent-siblings.js.map +1 -1
  407. package/dist/smells/sibling-files.d.ts +47 -0
  408. package/dist/smells/sibling-files.d.ts.map +1 -0
  409. package/dist/smells/sibling-files.js +104 -0
  410. package/dist/smells/sibling-files.js.map +1 -0
  411. package/dist/smells/similar-pairs.d.ts +27 -0
  412. package/dist/smells/similar-pairs.d.ts.map +1 -0
  413. package/dist/smells/similar-pairs.js +52 -0
  414. package/dist/smells/similar-pairs.js.map +1 -0
  415. package/dist/smells/smell-builder.d.ts +57 -12
  416. package/dist/smells/smell-builder.d.ts.map +1 -1
  417. package/dist/smells/smell-builder.js +111 -14
  418. package/dist/smells/smell-builder.js.map +1 -1
  419. package/dist/tsconfig/index.d.ts +19 -0
  420. package/dist/tsconfig/index.d.ts.map +1 -0
  421. package/dist/tsconfig/index.js +20 -0
  422. package/dist/tsconfig/index.js.map +1 -0
  423. package/dist/tsconfig/tsconfig-builder.d.ts +42 -9
  424. package/dist/tsconfig/tsconfig-builder.d.ts.map +1 -1
  425. package/dist/tsconfig/tsconfig-builder.js +64 -16
  426. package/dist/tsconfig/tsconfig-builder.js.map +1 -1
  427. package/package.json +3 -2
  428. package/dist/core/module-dependencies.d.ts +0 -28
  429. package/dist/core/module-dependencies.d.ts.map +0 -1
  430. package/dist/core/module-dependencies.js +0 -35
  431. package/dist/core/module-dependencies.js.map +0 -1
  432. package/dist/helpers/within.d.ts.map +0 -1
  433. package/dist/helpers/within.js.map +0 -1
@@ -0,0 +1,75 @@
1
+ /**
2
+ * Object-literal function traversal. **In `core/` because it was the wrong way up.**
3
+ *
4
+ * It lived in `helpers/` and was imported by `models/arch-function.ts` — a
5
+ * `models → helpers` edge, which is backwards: helpers may depend on models, not
6
+ * the reverse. That edge sat harmlessly until
7
+ * [ts-archunit plan 0082](https://github.com/nielspeter/ts-archunit/blob/main/plans/completed/0082-an-object-literal-callback-keeps-its-name.md)
8
+ * added `helpers/callback-extractor.ts → models/arch-function.ts` as a **value**
9
+ * import, closing a runtime cycle.
10
+ *
11
+ * Measured: at v0.45.6 no file in `helpers/` had a value import from `models/` —
12
+ * only `import type`. So the cycle was one day old when
13
+ * [ts-archunit plan 0084](https://github.com/nielspeter/ts-archunit/blob/main/plans/completed/0084-cycle-detection-that-ignores-type-only-imports.md)
14
+ * found it, and the rule that exists to catch exactly this was pinned at `.warn()`
15
+ * with a comment explaining why. A rule that cannot fail let a cycle in overnight.
16
+ *
17
+ * This module imports nothing but ts-morph, so `core/` costs it no dependency and
18
+ * both `models → core` and `helpers → core` are permitted directions.
19
+ */
20
+ import { Node } from 'ts-morph';
21
+ /** Default recursion depth into nested object literals (matches the callback path). */
22
+ const MAX_OBJECT_LITERAL_DEPTH = 3;
23
+ /**
24
+ * Walk an object literal and collect every function-valued property — arrow,
25
+ * function expression, or method shorthand — recursing into nested object
26
+ * literals up to `maxDepth`. Call-agnostic (F3): the single traversal shared by
27
+ * `functions()` object-literal collection (proposal 016) and the
28
+ * callback-extractor (`within()` / call path), so the two cannot drift.
29
+ *
30
+ * Only descends into nested object-literal property values, never into function
31
+ * bodies. Returns `[]` when `node` is not an object literal.
32
+ */
33
+ export function collectObjectLiteralFunctions(node, maxDepth = MAX_OBJECT_LITERAL_DEPTH) {
34
+ const out = [];
35
+ walk(node, [], 0, maxDepth, out);
36
+ return out;
37
+ }
38
+ function walk(node, keyPath, depth, maxDepth, out) {
39
+ if (!Node.isObjectLiteralExpression(node))
40
+ return;
41
+ if (depth >= maxDepth)
42
+ return;
43
+ for (const prop of node.getProperties()) {
44
+ // Method shorthand: { GET(req) { ... } }
45
+ if (Node.isMethodDeclaration(prop)) {
46
+ out.push({ node: prop, keyPath: [...keyPath, keyOf(prop)] });
47
+ continue;
48
+ }
49
+ if (!Node.isPropertyAssignment(prop))
50
+ continue;
51
+ const init = prop.getInitializer();
52
+ if (!init)
53
+ continue;
54
+ const key = keyOf(prop);
55
+ // Arrow / function-expression property value.
56
+ if (Node.isArrowFunction(init) || Node.isFunctionExpression(init)) {
57
+ out.push({ node: init, keyPath: [...keyPath, key] });
58
+ continue;
59
+ }
60
+ // Nested object literal — recurse (depth-limited).
61
+ if (Node.isObjectLiteralExpression(init)) {
62
+ walk(init, [...keyPath, key], depth + 1, maxDepth, out);
63
+ }
64
+ }
65
+ }
66
+ /** Property key as a string; computed keys degrade to a defined `<computed>` sentinel. */
67
+ function keyOf(prop) {
68
+ const nameNode = prop.getNameNode();
69
+ if (Node.isComputedPropertyName(nameNode))
70
+ return '<computed>';
71
+ if (Node.isStringLiteral(nameNode))
72
+ return nameNode.getLiteralValue();
73
+ return nameNode.getText();
74
+ }
75
+ //# sourceMappingURL=object-literal-functions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"object-literal-functions.js","sourceRoot":"","sources":["../../src/core/object-literal-functions.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,EAAE,IAAI,EAAE,MAAM,UAAU,CAAA;AAe/B,uFAAuF;AACvF,MAAM,wBAAwB,GAAG,CAAC,CAAA;AAElC;;;;;;;;;GASG;AACH,MAAM,UAAU,6BAA6B,CAC3C,IAAU,EACV,WAAmB,wBAAwB;IAE3C,MAAM,GAAG,GAA4B,EAAE,CAAA;IACvC,IAAI,CAAC,IAAI,EAAE,EAAE,EAAE,CAAC,EAAE,QAAQ,EAAE,GAAG,CAAC,CAAA;IAChC,OAAO,GAAG,CAAA;AACZ,CAAC;AAED,SAAS,IAAI,CACX,IAAU,EACV,OAA0B,EAC1B,KAAa,EACb,QAAgB,EAChB,GAA4B;IAE5B,IAAI,CAAC,IAAI,CAAC,yBAAyB,CAAC,IAAI,CAAC;QAAE,OAAM;IACjD,IAAI,KAAK,IAAI,QAAQ;QAAE,OAAM;IAE7B,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,aAAa,EAAE,EAAE,CAAC;QACxC,yCAAyC;QACzC,IAAI,IAAI,CAAC,mBAAmB,CAAC,IAAI,CAAC,EAAE,CAAC;YACnC,GAAG,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,GAAG,OAAO,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,CAAA;YAC5D,SAAQ;QACV,CAAC;QACD,IAAI,CAAC,IAAI,CAAC,oBAAoB,CAAC,IAAI,CAAC;YAAE,SAAQ;QAC9C,MAAM,IAAI,GAAG,IAAI,CAAC,cAAc,EAAE,CAAA;QAClC,IAAI,CAAC,IAAI;YAAE,SAAQ;QACnB,MAAM,GAAG,GAAG,KAAK,CAAC,IAAI,CAAC,CAAA;QACvB,8CAA8C;QAC9C,IAAI,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,oBAAoB,CAAC,IAAI,CAAC,EAAE,CAAC;YAClE,GAAG,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,GAAG,OAAO,EAAE,GAAG,CAAC,EAAE,CAAC,CAAA;YACpD,SAAQ;QACV,CAAC;QACD,mDAAmD;QACnD,IAAI,IAAI,CAAC,yBAAyB,CAAC,IAAI,CAAC,EAAE,CAAC;YACzC,IAAI,CAAC,IAAI,EAAE,CAAC,GAAG,OAAO,EAAE,GAAG,CAAC,EAAE,KAAK,GAAG,CAAC,EAAE,QAAQ,EAAE,GAAG,CAAC,CAAA;QACzD,CAAC;IACH,CAAC;AACH,CAAC;AAED,0FAA0F;AAC1F,SAAS,KAAK,CAAC,IAA4C;IACzD,MAAM,QAAQ,GAAG,IAAI,CAAC,WAAW,EAAE,CAAA;IACnC,IAAI,IAAI,CAAC,sBAAsB,CAAC,QAAQ,CAAC;QAAE,OAAO,YAAY,CAAA;IAC9D,IAAI,IAAI,CAAC,eAAe,CAAC,QAAQ,CAAC;QAAE,OAAO,QAAQ,CAAC,eAAe,EAAE,CAAA;IACrE,OAAO,QAAQ,CAAC,OAAO,EAAE,CAAA;AAC3B,CAAC"}
@@ -0,0 +1,44 @@
1
+ import type { DiagnosableRule } from './diagnose.js';
2
+ /**
3
+ * How much of the project the caller actually looked at.
4
+ *
5
+ * `orphanExclusions` compares directives against the ids of the rules it is
6
+ * handed. If that is a **subset** of the project's rules, a directive naming a
7
+ * rule declared elsewhere looks orphaned — so a caller that knows it saw only
8
+ * part of the project says so, and the advice carries the caveat.
9
+ */
10
+ interface OrphanExclusionOptions {
11
+ /** Rule files inspected, when the caller counted them. */
12
+ readonly ruleFilesChecked?: number;
13
+ /** Rule files the caller believes exist, when it knows. */
14
+ readonly ruleFilesTotal?: number;
15
+ /**
16
+ * Called once per source file, with whether that file was parsed.
17
+ *
18
+ * Exists so a test can assert the cheap reject still applies. Deleting that
19
+ * `continue` changes **cost and not behaviour**, so every functional test stays
20
+ * green — which is how a 3.0x regression could ship unnoticed, and how two
21
+ * separate attempts to measure it could both land on the wrong arm.
22
+ */
23
+ readonly onFileScanned?: (parsed: boolean) => void;
24
+ }
25
+ /** One exclusion comment naming a rule id nothing declares. */
26
+ export interface OrphanExclusion {
27
+ /** The rule id the comment names. */
28
+ readonly ruleId: string;
29
+ /** The source file holding the comment. */
30
+ readonly file: string;
31
+ /** The comment's line. */
32
+ readonly line: number;
33
+ /** The sanctioned fix. */
34
+ readonly advice: string;
35
+ }
36
+ /**
37
+ * Every exclusion comment in the project naming a rule id no rule declares.
38
+ *
39
+ * @param rules - **All** rules, across every rule file. A subset yields false
40
+ * orphans; see the module docstring.
41
+ */
42
+ export declare function orphanExclusions(rules: readonly DiagnosableRule[], options?: OrphanExclusionOptions): OrphanExclusion[];
43
+ export {};
44
+ //# sourceMappingURL=orphan-exclusions.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"orphan-exclusions.d.ts","sourceRoot":"","sources":["../../src/core/orphan-exclusions.ts"],"names":[],"mappings":"AA2CA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,eAAe,CAAA;AAEpD;;;;;;;GAOG;AACH,UAAU,sBAAsB;IAC9B,0DAA0D;IAC1D,QAAQ,CAAC,gBAAgB,CAAC,EAAE,MAAM,CAAA;IAClC,2DAA2D;IAC3D,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,CAAA;IAChC;;;;;;;OAOG;IACH,QAAQ,CAAC,aAAa,CAAC,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,IAAI,CAAA;CACnD;AAgBD,+DAA+D;AAC/D,MAAM,WAAW,eAAe;IAC9B,qCAAqC;IACrC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,2CAA2C;IAC3C,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,0BAA0B;IAC1B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,0BAA0B;IAC1B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CACxB;AAoCD;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAC9B,KAAK,EAAE,SAAS,eAAe,EAAE,EACjC,OAAO,CAAC,EAAE,sBAAsB,GAC/B,eAAe,EAAE,CAwHnB"}
@@ -0,0 +1,214 @@
1
+ /**
2
+ * Exclusion comments that name a rule nobody declares —
3
+ * [ts-archunit bug 0044](https://github.com/nielspeter/ts-archunit/blob/main/bugs/fixed/0044-an-inline-exclusion-comment-has-no-feedback-channel.md).
4
+ *
5
+ * `.excluding()` warns when a pattern matches zero violations. An inline
6
+ * `// eess-exclude` comment has no equivalent, and **cannot get one on the
7
+ * enforcement path**: comments are parsed only in files that already produced a
8
+ * violation (`execute-rule.ts`'s `result.length > 0` gate), so a directive naming
9
+ * a rule id that no longer exists is never even read. Rename a rule and every
10
+ * comment naming the old id goes inert — silently, permanently.
11
+ *
12
+ * That is the failure v0.37.0's suppression disclosure does **not** cover. That
13
+ * reports what a comment *did* silence; this reports a comment that silences
14
+ * nothing.
15
+ *
16
+ * ## Why a diagnostic and not a finding
17
+ *
18
+ * [ADR-009](../../../../adr/009-agent-first-failure-surfaces.md) rule 1's migration
19
+ * corollary: *"a warning is something you hope is read; a command is something
20
+ * someone ran."* This cannot be a check-time finding without parsing every file
21
+ * in scope on every run — the cost the `result.length > 0` gate exists to avoid —
22
+ * so it goes where `doctor` already looks.
23
+ *
24
+ * ## It must see EVERY rule, and that is a real footgun
25
+ *
26
+ * The declared-id set is the union across all rule files. `doctor` diagnoses one
27
+ * file at a time (`cli/commands/doctor.ts`), and a directive naming a rule
28
+ * declared in a *different* file would be reported as an orphan if this were
29
+ * called per file. So it is deliberately **not** part of `diagnose()`: it takes
30
+ * every rule at once, and calling it with a subset produces false orphans.
31
+ *
32
+ * Same shape as `checkAll` versus a per-rule `.check()`, which this project
33
+ * already documents: some facts are only true at the run boundary.
34
+ *
35
+ * ## What it does not catch
36
+ *
37
+ * A directive whose rule id is **correct** but whose placement is wrong — the
38
+ * other half of bug 0044. Catching that needs the enforcement path to know which
39
+ * violations a comment failed to cover, which is option 1 in that bug and costs a
40
+ * parse per file per rule. Stated here rather than left to be discovered.
41
+ */
42
+ import { parseExclusionComments } from './exclusion-comments.js';
43
+ /** The caveat, or `''` when the caller vouched for full coverage. */
44
+ function scopeNote(options) {
45
+ const checked = options?.ruleFilesChecked;
46
+ if (checked === undefined)
47
+ return '';
48
+ const total = options?.ruleFilesTotal;
49
+ if (total !== undefined && checked >= total)
50
+ return '';
51
+ const files = checked === 1 ? 'file' : 'files';
52
+ return (`Checked against ${String(checked)} rule ${files} only — if this id is declared in a rule ` +
53
+ `file that was not inspected, this report is a false positive and the comment is working. ` +
54
+ `Pass every rule file to be sure. `);
55
+ }
56
+ /**
57
+ * Could this text hold a directive at all?
58
+ *
59
+ * One predicate, two callers — and the deduplication is the point. This test
60
+ * existed as two identical inline `includes` checks, and that duplication caused
61
+ * a real measurement error: an attempt to time the cost of removing it patched
62
+ * the wrong occurrence, so both arms ran the same path and the saving looked
63
+ * imaginary. Two identical lines where only one is guarded is a trap for
64
+ * whoever sabotages next, so there is now one line to remove.
65
+ *
66
+ * Sound because `parseExclusionComments` only ever *removes* directives when
67
+ * blanking literals (bug 0043) — it cannot invent one in a file that does not
68
+ * contain the text.
69
+ */
70
+ function mayHoldDirective(text) {
71
+ return text.includes('eess-exclude');
72
+ }
73
+ /** The first directive found anywhere, so the aggregate finding has a location. */
74
+ function firstDirective(projects) {
75
+ for (const project of projects) {
76
+ for (const sourceFile of project.getSourceFiles()) {
77
+ const text = sourceFile.getFullText();
78
+ if (!mayHoldDirective(text))
79
+ continue;
80
+ const path = sourceFile.getFilePath();
81
+ const [first] = parseExclusionComments(text, path).exclusions;
82
+ if (first !== undefined)
83
+ return { file: path, line: first.line };
84
+ }
85
+ }
86
+ return undefined;
87
+ }
88
+ /**
89
+ * Every exclusion comment in the project naming a rule id no rule declares.
90
+ *
91
+ * @param rules - **All** rules, across every rule file. A subset yields false
92
+ * orphans; see the module docstring.
93
+ */
94
+ export function orphanExclusions(rules, options) {
95
+ const declared = new Set();
96
+ const projects = [];
97
+ for (const rule of rules) {
98
+ const id = rule.describeRule?.().id;
99
+ if (id !== undefined && id !== '')
100
+ declared.add(id);
101
+ const project = rule.getProject?.();
102
+ // By object, not by `tsConfigPath` — that path is not an identity, per
103
+ // `diagnose()`'s own reasoning (bug 0011's class).
104
+ //
105
+ // Note what this does NOT guard against, because the first comment here got
106
+ // it wrong: `workspace([a, b])` builds a **single** ts-morph project and
107
+ // returns one `ArchProject`, so it contributes one entry either way.
108
+ // Measured. The case that needs deduping is two separate `project()` calls
109
+ // whose globs overlap — and that is what `seen` below is for.
110
+ if (project !== undefined && !projects.includes(project))
111
+ projects.push(project);
112
+ }
113
+ // Nothing declares an id — so every inline exclusion in this project really IS
114
+ // inert (`isExcludedByComment` returns false without a `ruleId`, and the scan
115
+ // is gated on `ctx.metadata?.id`). Reporting nothing was the first behaviour
116
+ // and it was wrong in the ADR-009 rule 1 direction: those are all real
117
+ // orphans, and the diagnostic was silent about every one of them.
118
+ //
119
+ // Reporting each of them is the other failure — a wall of findings for one
120
+ // authored cause, which is what rule 4 calls a total standing in for an
121
+ // identity. So: **one** aggregate finding naming the cause, which is neither
122
+ // noise nor silence.
123
+ if (declared.size === 0) {
124
+ const anyDirective = firstDirective(projects);
125
+ if (anyDirective === undefined)
126
+ return [];
127
+ return [
128
+ {
129
+ ruleId: '(none declared)',
130
+ file: anyDirective.file,
131
+ line: anyDirective.line,
132
+ advice: `No rule declares an id, so **every** inline \`// eess-exclude\` comment in ` +
133
+ `this project is inert — a comment can only match a rule that carries ` +
134
+ `\`.rule({ id })\`. Add ids to the rules these comments name, or delete the ` +
135
+ `comments. Reported once rather than per comment: one cause, one finding.`,
136
+ },
137
+ ];
138
+ }
139
+ const found = [];
140
+ const seen = new Set();
141
+ for (const project of projects) {
142
+ for (const sourceFile of project.getSourceFiles()) {
143
+ const path = sourceFile.getFilePath();
144
+ // `getFullText()`, not `fs.readFileSync`. The text is already in memory, so
145
+ // the read was a second I/O that also **silently lost findings**: review
146
+ // measured an in-memory project's stale directive vanishing (ENOENT into
147
+ // the catch) and a `chmod 000` file doing the same with nothing on stderr.
148
+ // A diagnostic whose entire subject is "this silently does nothing" must
149
+ // not silently do nothing. The catch is gone because its cause is gone.
150
+ const text = sourceFile.getFullText();
151
+ // Cheap reject before the parse, load-bearing on soundness AND on cost.
152
+ //
153
+ // Sound because `parseExclusionComments` only ever *removes* directives
154
+ // when blanking literals (bug 0043), so a file with no occurrence of the
155
+ // literal text cannot hold one.
156
+ //
157
+ // The cost shape is the better argument: it scales with **directive-bearing
158
+ // files, not project size** — ~5.7ms per parsed file, against ~2.6ms times
159
+ // *every* file without it. This repository has 18 of 566 files mentioning
160
+ // the literal (mostly its own source discussing the feature), so the pass
161
+ // costs ~105ms instead of ~1.5s and `doctor` ~670ms instead of ~2.0s. A
162
+ // 5000-file consumer monorepo with **no** directives would have paid ~13s
163
+ // per run to report nothing.
164
+ //
165
+ // I measured this as ~1.0x and concluded the saving was imaginary. Wrong
166
+ // twice: the first attempt was vacuous (`findings=0`, equally consistent
167
+ // with scanning nothing), and the second patched the **other** occurrence
168
+ // of this line — `firstDirective` above carries the same reject — so both
169
+ // arms ran the same path. Removing a `continue` changes cost and not
170
+ // behaviour, so no output distinguished them, and 18 parses cost the same
171
+ // ~105ms either way. `onFileScanned` exists because counting is the only
172
+ // way to assert this reject still applies.
173
+ if (!mayHoldDirective(text)) {
174
+ options?.onFileScanned?.(false);
175
+ continue;
176
+ }
177
+ options?.onFileScanned?.(true);
178
+ for (const comment of parseExclusionComments(text, path).exclusions) {
179
+ if (declared.has(comment.ruleId))
180
+ continue;
181
+ // One report per (id, file, line): a block directive naming two rules
182
+ // yields two comments, and the same file can be reached through two
183
+ // projects in a workspace.
184
+ const key = `${comment.ruleId} ${path} ${String(comment.line)}`;
185
+ if (seen.has(key))
186
+ continue;
187
+ seen.add(key);
188
+ found.push({
189
+ ruleId: comment.ruleId,
190
+ file: path,
191
+ line: comment.line,
192
+ // The scope caveat is FIRST, and it is not decoration.
193
+ //
194
+ // Review measured the false positive this module's docstring claims to
195
+ // prevent, reachable through the documented CLI form: `doctor
196
+ // a.rules.ts` on a project whose comment names a rule declared in
197
+ // `b.rules.ts` reported that working comment as an orphan — and then
198
+ // told the reader to **delete it**, which un-waives a real violation.
199
+ // A remedy that is wrong on the path that produced it is worse than
200
+ // none (ADR-009 rule 2), so the caller states its scope and the reader
201
+ // is told what it means.
202
+ advice: `${scopeNote(options)}This exclusion names '${comment.ruleId}', which no rule ` +
203
+ `declares — so it suppresses nothing and the rule it was meant to waive is being ` +
204
+ `enforced here. Either correct the id to a rule that exists, or delete the ` +
205
+ `comment. The commonest cause is a rule that was renamed: nothing reports this at ` +
206
+ `check time, because a comment is only read in a file that already produced a ` +
207
+ `finding for that rule.`,
208
+ });
209
+ }
210
+ }
211
+ }
212
+ return found;
213
+ }
214
+ //# sourceMappingURL=orphan-exclusions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"orphan-exclusions.js","sourceRoot":"","sources":["../../src/core/orphan-exclusions.ts"],"names":[],"mappings":"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"}
@@ -1,10 +1,39 @@
1
1
  import type { SourceFile } from 'ts-morph';
2
- import type { ArchViolation } from './violation.js';
2
+ import type { ArchViolation } from '@nielspeter/eess';
3
3
  import type { ConditionContext } from '@nielspeter/eess';
4
- import type { LayerPair } from '../models/cross-layer.js';
4
+ import type { LayerPair, Layer } from '../models/cross-layer.js';
5
+ /**
6
+ * What a pair condition is given, beyond an ordinary condition's context.
7
+ *
8
+ * `layers` is the builder's **own resolved** layers —
9
+ * [ts-archunit bug 0040](https://github.com/nielspeter/ts-archunit/blob/main/bugs/fixed/0040-a-crosslayer-rule-reports-nothing-when-its-layer-resolves-nothing.md).
10
+ * Before this, `haveMatchingCounterpart` took a `Layer[]` argument that **no
11
+ * public API could produce**: `PairFinalBuilder.layers` is private at every
12
+ * stage and `resolveLayer` is unexported, so every caller hand-built the array
13
+ * and the condition judged that copy rather than the builder's resolution.
14
+ * Measured: builder glob dead, hand-built layers populated → two counterpart
15
+ * violations and no configuration finding, describing an array the library never
16
+ * resolved.
17
+ *
18
+ * ## Why a subtype rather than a field on `ConditionContext`
19
+ *
20
+ * A pair-only field on the base context leaks onto every class, function, module
21
+ * and type condition. `identifyByArgument` is the one precedent, and its own
22
+ * docstring justifies itself as "one optional primitive" — a second would make
23
+ * that comment false.
24
+ *
25
+ * This is still additive for an external implementer: TypeScript method
26
+ * parameters are bivariant, so a condition declaring `ConditionContext` still
27
+ * satisfies `PairCondition`. Verified — `haveConsistentExports` and
28
+ * `satisfyPairCondition` compile unchanged.
29
+ */
30
+ export interface PairConditionContext extends ConditionContext {
31
+ /** The layers the builder resolved, in declaration order. */
32
+ readonly layers: readonly Layer[];
33
+ }
5
34
  /** Condition that evaluates matched pairs from two layers. */
6
35
  export interface PairCondition<A = SourceFile, B = SourceFile> {
7
36
  readonly description: string;
8
- evaluate(pairs: LayerPair<A, B>[], context: ConditionContext): ArchViolation[];
37
+ evaluate(pairs: LayerPair<A, B>[], context: PairConditionContext): ArchViolation[];
9
38
  }
10
39
  //# sourceMappingURL=pair-condition.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"pair-condition.d.ts","sourceRoot":"","sources":["../../src/core/pair-condition.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,UAAU,CAAA;AAC1C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAA;AACnD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAA;AACxD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAA;AAEzD,8DAA8D;AAC9D,MAAM,WAAW,aAAa,CAAC,CAAC,GAAG,UAAU,EAAE,CAAC,GAAG,UAAU;IAC3D,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAA;IAC5B,QAAQ,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,OAAO,EAAE,gBAAgB,GAAG,aAAa,EAAE,CAAA;CAC/E"}
1
+ {"version":3,"file":"pair-condition.d.ts","sourceRoot":"","sources":["../../src/core/pair-condition.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,UAAU,CAAA;AAC1C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAA;AACrD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAA;AACxD,OAAO,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,0BAA0B,CAAA;AAEhE;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,MAAM,WAAW,oBAAqB,SAAQ,gBAAgB;IAC5D,6DAA6D;IAC7D,QAAQ,CAAC,MAAM,EAAE,SAAS,KAAK,EAAE,CAAA;CAClC;AAED,8DAA8D;AAC9D,MAAM,WAAW,aAAa,CAAC,CAAC,GAAG,UAAU,EAAE,CAAC,GAAG,UAAU;IAC3D,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAA;IAC5B,QAAQ,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,OAAO,EAAE,oBAAoB,GAAG,aAAa,EAAE,CAAA;CACnF"}
@@ -0,0 +1,54 @@
1
+ import type { ArchProject } from './project.js';
2
+ /**
3
+ * Every path a glob could legitimately match in a project, materialized once.
4
+ *
5
+ * A free function over `ArchProject` rather than a method on it: bare-object
6
+ * `ArchProject` literals are real test doubles across the suite, and adding a
7
+ * required method would break every one of them. Lives in `src/core/`, takes
8
+ * `ArchProject` in and hands plain strings out, and imports no ts-morph —
9
+ * ADR-007's batch-first shape by construction, one materialization instead of
10
+ * a traversal per glob.
11
+ */
12
+ export interface PathUniverse {
13
+ /** Absolute paths of every file in the project. */
14
+ readonly filePaths: readonly string[];
15
+ /**
16
+ * Immediate parent directories only.
17
+ *
18
+ * Not all ancestors. `resideInFolder` tests
19
+ * `filePath.substring(0, filePath.lastIndexOf('/'))` — the immediate parent
20
+ * and nothing else — so an all-ancestors set is not a harmless
21
+ * over-approximation, it is a **false green**: measured on this repo, 41 of
22
+ * the 122 ancestors are no file's parent, so `resideInFolder('**\/tests/fixtures')`
23
+ * can never select anything while an all-ancestors universe calls it
24
+ * satisfiable. Using the parent set removes the over-approximation rather
25
+ * than excusing it.
26
+ */
27
+ readonly parentDirs: readonly string[];
28
+ /** `filePaths` relative to the tsconfig directory, for message wording. */
29
+ readonly tsconfigRelativeFilePaths: readonly string[];
30
+ /** `parentDirs` relative to the tsconfig directory, for message wording. */
31
+ readonly tsconfigRelativeParentDirs: readonly string[];
32
+ }
33
+ /**
34
+ * The project's path universe, computed once per project.
35
+ *
36
+ * Memoized on the project identity, so a rule file with fifty rules pays for
37
+ * one traversal rather than fifty.
38
+ */
39
+ export declare function pathUniverse(project: ArchProject): PathUniverse;
40
+ /**
41
+ * The views a glob of this kind is matched against.
42
+ *
43
+ * Satisfiability is taken against the **union** — a glob is unsatisfiable only
44
+ * when nothing in any view matches it. That is deliberately generous, so that
45
+ * a wrong `base` cannot make a glob look unmatched. It does NOT make `base`
46
+ * message-only: the anchor check in `syntacticFault` consults it, and an
47
+ * unanchored `base: 'absolute'` glob is dead regardless of what any view
48
+ * holds. See `GlobBase`.
49
+ *
50
+ * `import-target`, `specifier` and `literal` are not path kinds and have no
51
+ * views, so they can never be found unsatisfiable here.
52
+ */
53
+ export declare function viewsFor(universe: PathUniverse, kind: 'file-path' | 'parent-dir' | 'import-target' | 'specifier' | 'literal'): readonly (readonly string[])[];
54
+ //# sourceMappingURL=path-universe.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"path-universe.d.ts","sourceRoot":"","sources":["../../src/core/path-universe.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAA;AAE/C;;;;;;;;;GASG;AACH,MAAM,WAAW,YAAY;IAC3B,mDAAmD;IACnD,QAAQ,CAAC,SAAS,EAAE,SAAS,MAAM,EAAE,CAAA;IACrC;;;;;;;;;;;OAWG;IACH,QAAQ,CAAC,UAAU,EAAE,SAAS,MAAM,EAAE,CAAA;IACtC,2EAA2E;IAC3E,QAAQ,CAAC,yBAAyB,EAAE,SAAS,MAAM,EAAE,CAAA;IACrD,4EAA4E;IAC5E,QAAQ,CAAC,0BAA0B,EAAE,SAAS,MAAM,EAAE,CAAA;CACvD;AAID;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,WAAW,GAAG,YAAY,CAiB/D;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,QAAQ,CACtB,QAAQ,EAAE,YAAY,EACtB,IAAI,EAAE,WAAW,GAAG,YAAY,GAAG,eAAe,GAAG,WAAW,GAAG,SAAS,GAC3E,SAAS,CAAC,SAAS,MAAM,EAAE,CAAC,EAAE,CAIhC"}
@@ -0,0 +1,65 @@
1
+ const cache = new WeakMap();
2
+ /**
3
+ * The project's path universe, computed once per project.
4
+ *
5
+ * Memoized on the project identity, so a rule file with fifty rules pays for
6
+ * one traversal rather than fifty.
7
+ */
8
+ export function pathUniverse(project) {
9
+ const cached = cache.get(project);
10
+ if (cached)
11
+ return cached;
12
+ const filePaths = project.getSourceFiles().map((sourceFile) => sourceFile.getFilePath());
13
+ const parentDirs = [
14
+ ...new Set(filePaths.map((filePath) => filePath.substring(0, filePath.lastIndexOf('/')))),
15
+ ];
16
+ const root = tsconfigDir(project.tsConfigPath);
17
+ const universe = {
18
+ filePaths,
19
+ parentDirs,
20
+ tsconfigRelativeFilePaths: filePaths.map((filePath) => relativeTo(root, filePath)),
21
+ tsconfigRelativeParentDirs: parentDirs.map((dir) => relativeTo(root, dir)),
22
+ };
23
+ cache.set(project, universe);
24
+ return universe;
25
+ }
26
+ /**
27
+ * The views a glob of this kind is matched against.
28
+ *
29
+ * Satisfiability is taken against the **union** — a glob is unsatisfiable only
30
+ * when nothing in any view matches it. That is deliberately generous, so that
31
+ * a wrong `base` cannot make a glob look unmatched. It does NOT make `base`
32
+ * message-only: the anchor check in `syntacticFault` consults it, and an
33
+ * unanchored `base: 'absolute'` glob is dead regardless of what any view
34
+ * holds. See `GlobBase`.
35
+ *
36
+ * `import-target`, `specifier` and `literal` are not path kinds and have no
37
+ * views, so they can never be found unsatisfiable here.
38
+ */
39
+ export function viewsFor(universe, kind) {
40
+ if (kind === 'file-path')
41
+ return [universe.filePaths, universe.tsconfigRelativeFilePaths];
42
+ if (kind === 'parent-dir')
43
+ return [universe.parentDirs, universe.tsconfigRelativeParentDirs];
44
+ return [];
45
+ }
46
+ /** The directory containing the tsconfig, with forward slashes and no trailing separator. */
47
+ function tsconfigDir(tsConfigPath) {
48
+ const normalized = tsConfigPath.replaceAll('\\', '/');
49
+ const lastSlash = normalized.lastIndexOf('/');
50
+ return lastSlash === -1 ? '' : normalized.slice(0, lastSlash);
51
+ }
52
+ /**
53
+ * `filePath` relative to `root`, or unchanged when it sits outside.
54
+ *
55
+ * Deliberately not `path.relative`: that would emit `../../..` for a path
56
+ * above the root, which encodes the root's depth — machine-dependent, and the
57
+ * same mistake `toPortablePath` exists to avoid.
58
+ */
59
+ function relativeTo(root, filePath) {
60
+ if (root === '')
61
+ return filePath;
62
+ const prefix = root.endsWith('/') ? root : root + '/';
63
+ return filePath.startsWith(prefix) ? filePath.slice(prefix.length) : filePath;
64
+ }
65
+ //# sourceMappingURL=path-universe.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"path-universe.js","sourceRoot":"","sources":["../../src/core/path-universe.ts"],"names":[],"mappings":"AAkCA,MAAM,KAAK,GAAG,IAAI,OAAO,EAA6B,CAAA;AAEtD;;;;;GAKG;AACH,MAAM,UAAU,YAAY,CAAC,OAAoB;IAC/C,MAAM,MAAM,GAAG,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,CAAA;IACjC,IAAI,MAAM;QAAE,OAAO,MAAM,CAAA;IAEzB,MAAM,SAAS,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC,GAAG,CAAC,CAAC,UAAU,EAAE,EAAE,CAAC,UAAU,CAAC,WAAW,EAAE,CAAC,CAAA;IACxF,MAAM,UAAU,GAAG;QACjB,GAAG,IAAI,GAAG,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,EAAE,QAAQ,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;KAC1F,CAAA;IACD,MAAM,IAAI,GAAG,WAAW,CAAC,OAAO,CAAC,YAAY,CAAC,CAAA;IAC9C,MAAM,QAAQ,GAAiB;QAC7B,SAAS;QACT,UAAU;QACV,yBAAyB,EAAE,SAAS,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,UAAU,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;QAClF,0BAA0B,EAAE,UAAU,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,UAAU,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;KAC3E,CAAA;IACD,KAAK,CAAC,GAAG,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAA;IAC5B,OAAO,QAAQ,CAAA;AACjB,CAAC;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,QAAQ,CACtB,QAAsB,EACtB,IAA4E;IAE5E,IAAI,IAAI,KAAK,WAAW;QAAE,OAAO,CAAC,QAAQ,CAAC,SAAS,EAAE,QAAQ,CAAC,yBAAyB,CAAC,CAAA;IACzF,IAAI,IAAI,KAAK,YAAY;QAAE,OAAO,CAAC,QAAQ,CAAC,UAAU,EAAE,QAAQ,CAAC,0BAA0B,CAAC,CAAA;IAC5F,OAAO,EAAE,CAAA;AACX,CAAC;AAED,6FAA6F;AAC7F,SAAS,WAAW,CAAC,YAAoB;IACvC,MAAM,UAAU,GAAG,YAAY,CAAC,UAAU,CAAC,IAAI,EAAE,GAAG,CAAC,CAAA;IACrD,MAAM,SAAS,GAAG,UAAU,CAAC,WAAW,CAAC,GAAG,CAAC,CAAA;IAC7C,OAAO,SAAS,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,EAAE,SAAS,CAAC,CAAA;AAC/D,CAAC;AAED;;;;;;GAMG;AACH,SAAS,UAAU,CAAC,IAAY,EAAE,QAAgB;IAChD,IAAI,IAAI,KAAK,EAAE;QAAE,OAAO,QAAQ,CAAA;IAChC,MAAM,MAAM,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,GAAG,GAAG,CAAA;IACrD,OAAO,QAAQ,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAA;AAC/E,CAAC"}
@@ -0,0 +1,20 @@
1
+ import { Project as TsMorphProject } from 'ts-morph';
2
+ import type { SourceFile } from 'ts-morph';
3
+ /**
4
+ * Record each config's options against the root directory it governs.
5
+ *
6
+ * Called by `workspace()` with every resolved tsconfig path — **every** one, not just the
7
+ * primary, which is the whole point. `project()` does not need it: one config governs one
8
+ * project, so the project-wide lookup is already correct there.
9
+ */
10
+ export declare function registerRootCompilerOptions(tsMorphProject: TsMorphProject, tsConfigPaths: readonly string[]): void;
11
+ /**
12
+ * `verbatimModuleSyntax` for the package that owns this file.
13
+ *
14
+ * Falls back to the project-wide value, which is correct for `project()` and for any
15
+ * project built without going through `workspace()` — an in-memory test double, for
16
+ * instance. The fallback is the OLD behaviour, so a file the registry does not cover
17
+ * answers exactly as it did before bug 0058.
18
+ */
19
+ export declare function verbatimModuleSyntaxFor(sourceFile: SourceFile): boolean;
20
+ //# sourceMappingURL=per-root-compiler-options.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"per-root-compiler-options.d.ts","sourceRoot":"","sources":["../../src/core/per-root-compiler-options.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,IAAI,cAAc,EAAE,MAAM,UAAU,CAAA;AACpD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,UAAU,CAAA;AAiD1C;;;;;;GAMG;AACH,wBAAgB,2BAA2B,CACzC,cAAc,EAAE,cAAc,EAC9B,aAAa,EAAE,SAAS,MAAM,EAAE,GAC/B,IAAI,CAQN;AAED;;;;;;;GAOG;AACH,wBAAgB,uBAAuB,CAAC,UAAU,EAAE,UAAU,GAAG,OAAO,CAUvE"}
@@ -0,0 +1,57 @@
1
+ import { Project as TsMorphProject } from 'ts-morph';
2
+ import { rootOf } from './project-relative.js';
3
+ const optionsByProject = new WeakMap();
4
+ /**
5
+ * Read one tsconfig's options **without loading its files**.
6
+ *
7
+ * `skipAddingFilesFromTsConfig` is the load-bearing part: a `workspace()` of ten packages
8
+ * would otherwise parse every package's sources ten times over to answer one boolean.
9
+ * Going through ts-morph rather than reading the JSON is also deliberate — `extends` has
10
+ * to resolve, and hand-rolling that is how a monorepo whose packages inherit a base
11
+ * config gets the wrong answer (ADR-002: ts-morph owns this).
12
+ */
13
+ function readRootOptions(tsConfigPath) {
14
+ const parsed = new TsMorphProject({
15
+ tsConfigFilePath: tsConfigPath,
16
+ skipAddingFilesFromTsConfig: true,
17
+ });
18
+ return { verbatimModuleSyntax: parsed.getCompilerOptions().verbatimModuleSyntax === true };
19
+ }
20
+ /**
21
+ * Record each config's options against the root directory it governs.
22
+ *
23
+ * Called by `workspace()` with every resolved tsconfig path — **every** one, not just the
24
+ * primary, which is the whole point. `project()` does not need it: one config governs one
25
+ * project, so the project-wide lookup is already correct there.
26
+ */
27
+ export function registerRootCompilerOptions(tsMorphProject, tsConfigPaths) {
28
+ const byRoot = new Map();
29
+ for (const configPath of tsConfigPaths) {
30
+ const normalized = configPath.replaceAll('\\', '/');
31
+ const root = normalized.replace(/\/[^/]*$/, '') || '/';
32
+ byRoot.set(root, readRootOptions(configPath));
33
+ }
34
+ if (byRoot.size > 0)
35
+ optionsByProject.set(tsMorphProject, byRoot);
36
+ }
37
+ /**
38
+ * `verbatimModuleSyntax` for the package that owns this file.
39
+ *
40
+ * Falls back to the project-wide value, which is correct for `project()` and for any
41
+ * project built without going through `workspace()` — an in-memory test double, for
42
+ * instance. The fallback is the OLD behaviour, so a file the registry does not cover
43
+ * answers exactly as it did before bug 0058.
44
+ */
45
+ export function verbatimModuleSyntaxFor(sourceFile) {
46
+ const byRoot = optionsByProject.get(sourceFile.getProject());
47
+ if (byRoot !== undefined) {
48
+ const root = rootOf(sourceFile);
49
+ if (root !== undefined) {
50
+ const owned = byRoot.get(root);
51
+ if (owned !== undefined)
52
+ return owned.verbatimModuleSyntax;
53
+ }
54
+ }
55
+ return sourceFile.getProject().getCompilerOptions().verbatimModuleSyntax === true;
56
+ }
57
+ //# sourceMappingURL=per-root-compiler-options.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"per-root-compiler-options.js","sourceRoot":"","sources":["../../src/core/per-root-compiler-options.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,IAAI,cAAc,EAAE,MAAM,UAAU,CAAA;AAEpD,OAAO,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAA;AA6B9C,MAAM,gBAAgB,GAAG,IAAI,OAAO,EAAoD,CAAA;AAExF;;;;;;;;GAQG;AACH,SAAS,eAAe,CAAC,YAAoB;IAC3C,MAAM,MAAM,GAAG,IAAI,cAAc,CAAC;QAChC,gBAAgB,EAAE,YAAY;QAC9B,2BAA2B,EAAE,IAAI;KAClC,CAAC,CAAA;IACF,OAAO,EAAE,oBAAoB,EAAE,MAAM,CAAC,kBAAkB,EAAE,CAAC,oBAAoB,KAAK,IAAI,EAAE,CAAA;AAC5F,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,2BAA2B,CACzC,cAA8B,EAC9B,aAAgC;IAEhC,MAAM,MAAM,GAAG,IAAI,GAAG,EAAuB,CAAA;IAC7C,KAAK,MAAM,UAAU,IAAI,aAAa,EAAE,CAAC;QACvC,MAAM,UAAU,GAAG,UAAU,CAAC,UAAU,CAAC,IAAI,EAAE,GAAG,CAAC,CAAA;QACnD,MAAM,IAAI,GAAG,UAAU,CAAC,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC,IAAI,GAAG,CAAA;QACtD,MAAM,CAAC,GAAG,CAAC,IAAI,EAAE,eAAe,CAAC,UAAU,CAAC,CAAC,CAAA;IAC/C,CAAC;IACD,IAAI,MAAM,CAAC,IAAI,GAAG,CAAC;QAAE,gBAAgB,CAAC,GAAG,CAAC,cAAc,EAAE,MAAM,CAAC,CAAA;AACnE,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,uBAAuB,CAAC,UAAsB;IAC5D,MAAM,MAAM,GAAG,gBAAgB,CAAC,GAAG,CAAC,UAAU,CAAC,UAAU,EAAE,CAAC,CAAA;IAC5D,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;QACzB,MAAM,IAAI,GAAG,MAAM,CAAC,UAAU,CAAC,CAAA;QAC/B,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;YACvB,MAAM,KAAK,GAAG,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,CAAA;YAC9B,IAAI,KAAK,KAAK,SAAS;gBAAE,OAAO,KAAK,CAAC,oBAAoB,CAAA;QAC5D,CAAC;IACH,CAAC;IACD,OAAO,UAAU,CAAC,UAAU,EAAE,CAAC,kBAAkB,EAAE,CAAC,oBAAoB,KAAK,IAAI,CAAA;AACnF,CAAC"}