@nielspeter/eess-ts 0.2.1 → 0.5.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 (467) hide show
  1. package/README.md +61 -35
  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 +75 -32
  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 +141 -55
  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 +385 -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 +182 -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 +177 -39
  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 +16 -19
  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 +243 -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 +109 -42
  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 +8 -3
  55. package/dist/cli/commands/baseline.d.ts.map +1 -1
  56. package/dist/cli/commands/baseline.js +111 -7
  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 +385 -47
  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 +47 -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 +101 -43
  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 +25 -32
  85. package/dist/cli/load-rules.js.map +1 -1
  86. package/dist/cli/resolve-config.d.ts +0 -8
  87. package/dist/cli/resolve-config.d.ts.map +1 -1
  88. package/dist/cli/resolve-config.js +25 -55
  89. package/dist/cli/resolve-config.js.map +1 -1
  90. package/dist/cli/rule-file-findings.d.ts +178 -0
  91. package/dist/cli/rule-file-findings.d.ts.map +1 -0
  92. package/dist/cli/rule-file-findings.js +351 -0
  93. package/dist/cli/rule-file-findings.js.map +1 -0
  94. package/dist/cli/watch.d.ts +17 -34
  95. package/dist/cli/watch.d.ts.map +1 -1
  96. package/dist/cli/watch.js +14 -129
  97. package/dist/cli/watch.js.map +1 -1
  98. package/dist/conditions/body-analysis-function.d.ts.map +1 -1
  99. package/dist/conditions/body-analysis-function.js +16 -7
  100. package/dist/conditions/body-analysis-function.js.map +1 -1
  101. package/dist/conditions/body-analysis-module.d.ts.map +1 -1
  102. package/dist/conditions/body-analysis-module.js +14 -9
  103. package/dist/conditions/body-analysis-module.js.map +1 -1
  104. package/dist/conditions/body-analysis.d.ts.map +1 -1
  105. package/dist/conditions/body-analysis.js +16 -7
  106. package/dist/conditions/body-analysis.js.map +1 -1
  107. package/dist/conditions/call.d.ts.map +1 -1
  108. package/dist/conditions/call.js +41 -19
  109. package/dist/conditions/call.js.map +1 -1
  110. package/dist/conditions/catch-analysis.d.ts +2 -1
  111. package/dist/conditions/catch-analysis.d.ts.map +1 -1
  112. package/dist/conditions/catch-analysis.js.map +1 -1
  113. package/dist/conditions/cross-layer.d.ts +2 -10
  114. package/dist/conditions/cross-layer.d.ts.map +1 -1
  115. package/dist/conditions/cross-layer.js +227 -23
  116. package/dist/conditions/cross-layer.js.map +1 -1
  117. package/dist/conditions/dependency.d.ts +35 -6
  118. package/dist/conditions/dependency.d.ts.map +1 -1
  119. package/dist/conditions/dependency.js +299 -45
  120. package/dist/conditions/dependency.js.map +1 -1
  121. package/dist/conditions/exports.d.ts.map +1 -1
  122. package/dist/conditions/exports.js +41 -37
  123. package/dist/conditions/exports.js.map +1 -1
  124. package/dist/conditions/function.d.ts.map +1 -1
  125. package/dist/conditions/function.js +19 -5
  126. package/dist/conditions/function.js.map +1 -1
  127. package/dist/conditions/helpers.d.ts +2 -1
  128. package/dist/conditions/helpers.d.ts.map +1 -1
  129. package/dist/conditions/helpers.js +4 -1
  130. package/dist/conditions/helpers.js.map +1 -1
  131. package/dist/conditions/jsx.d.ts.map +1 -1
  132. package/dist/conditions/jsx.js +7 -2
  133. package/dist/conditions/jsx.js.map +1 -1
  134. package/dist/conditions/match-identity.d.ts +43 -0
  135. package/dist/conditions/match-identity.d.ts.map +1 -0
  136. package/dist/conditions/match-identity.js +43 -0
  137. package/dist/conditions/match-identity.js.map +1 -0
  138. package/dist/conditions/members.d.ts.map +1 -1
  139. package/dist/conditions/members.js +20 -6
  140. package/dist/conditions/members.js.map +1 -1
  141. package/dist/conditions/reverse-dependency.d.ts +18 -5
  142. package/dist/conditions/reverse-dependency.d.ts.map +1 -1
  143. package/dist/conditions/reverse-dependency.js +155 -93
  144. package/dist/conditions/reverse-dependency.js.map +1 -1
  145. package/dist/conditions/slice.d.ts +86 -2
  146. package/dist/conditions/slice.d.ts.map +1 -1
  147. package/dist/conditions/slice.js +234 -53
  148. package/dist/conditions/slice.js.map +1 -1
  149. package/dist/conditions/structural.d.ts.map +1 -1
  150. package/dist/conditions/structural.js +16 -4
  151. package/dist/conditions/structural.js.map +1 -1
  152. package/dist/core/check-all.d.ts +19 -0
  153. package/dist/core/check-all.d.ts.map +1 -0
  154. package/dist/core/check-all.js +150 -0
  155. package/dist/core/check-all.js.map +1 -0
  156. package/dist/core/combinators.d.ts +48 -0
  157. package/dist/core/combinators.d.ts.map +1 -0
  158. package/dist/core/combinators.js +49 -0
  159. package/dist/core/combinators.js.map +1 -0
  160. package/dist/core/descendant-cache.d.ts +36 -0
  161. package/dist/core/descendant-cache.d.ts.map +1 -0
  162. package/dist/core/descendant-cache.js +117 -0
  163. package/dist/core/descendant-cache.js.map +1 -0
  164. package/dist/core/diagnose.d.ts +234 -0
  165. package/dist/core/diagnose.d.ts.map +1 -0
  166. package/dist/core/diagnose.js +390 -0
  167. package/dist/core/diagnose.js.map +1 -0
  168. package/dist/core/disk-set.d.ts +48 -0
  169. package/dist/core/disk-set.d.ts.map +1 -0
  170. package/dist/core/disk-set.js +218 -0
  171. package/dist/core/disk-set.js.map +1 -0
  172. package/dist/core/element-cache.d.ts +75 -0
  173. package/dist/core/element-cache.d.ts.map +1 -0
  174. package/dist/core/element-cache.js +32 -0
  175. package/dist/core/element-cache.js.map +1 -0
  176. package/dist/core/empty-project-advice.d.ts +75 -0
  177. package/dist/core/empty-project-advice.d.ts.map +1 -0
  178. package/dist/core/empty-project-advice.js +61 -0
  179. package/dist/core/empty-project-advice.js.map +1 -0
  180. package/dist/core/exclusion-comments.d.ts +19 -0
  181. package/dist/core/exclusion-comments.d.ts.map +1 -0
  182. package/dist/core/exclusion-comments.js +7 -0
  183. package/dist/core/exclusion-comments.js.map +1 -0
  184. package/dist/core/execute-rule.d.ts +158 -0
  185. package/dist/core/execute-rule.d.ts.map +1 -0
  186. package/dist/core/execute-rule.js +666 -0
  187. package/dist/core/execute-rule.js.map +1 -0
  188. package/dist/core/glob-diagnosis.d.ts +78 -0
  189. package/dist/core/glob-diagnosis.d.ts.map +1 -0
  190. package/dist/core/glob-diagnosis.js +134 -0
  191. package/dist/core/glob-diagnosis.js.map +1 -0
  192. package/dist/core/glob-evaluator.d.ts +48 -0
  193. package/dist/core/glob-evaluator.d.ts.map +1 -0
  194. package/dist/core/glob-evaluator.js +89 -0
  195. package/dist/core/glob-evaluator.js.map +1 -0
  196. package/dist/core/import-candidates.d.ts +60 -0
  197. package/dist/core/import-candidates.d.ts.map +1 -0
  198. package/dist/core/import-candidates.js +93 -0
  199. package/dist/core/import-candidates.js.map +1 -0
  200. package/dist/core/import-options.d.ts +55 -2
  201. package/dist/core/import-options.d.ts.map +1 -1
  202. package/dist/core/import-options.js +64 -0
  203. package/dist/core/import-options.js.map +1 -1
  204. package/dist/core/invalidate-on-modify.d.ts +20 -0
  205. package/dist/core/invalidate-on-modify.d.ts.map +1 -0
  206. package/dist/core/invalidate-on-modify.js +26 -0
  207. package/dist/core/invalidate-on-modify.js.map +1 -0
  208. package/dist/core/line-index.d.ts +3 -0
  209. package/dist/core/line-index.d.ts.map +1 -0
  210. package/dist/core/line-index.js +227 -0
  211. package/dist/core/line-index.js.map +1 -0
  212. package/dist/core/metric-violation.d.ts +86 -0
  213. package/dist/core/metric-violation.d.ts.map +1 -0
  214. package/dist/core/metric-violation.js +132 -0
  215. package/dist/core/metric-violation.js.map +1 -0
  216. package/dist/core/module-edges.d.ts +361 -0
  217. package/dist/core/module-edges.d.ts.map +1 -0
  218. package/dist/core/module-edges.js +593 -0
  219. package/dist/core/module-edges.js.map +1 -0
  220. package/dist/core/object-literal-functions.d.ts +42 -0
  221. package/dist/core/object-literal-functions.d.ts.map +1 -0
  222. package/dist/core/object-literal-functions.js +75 -0
  223. package/dist/core/object-literal-functions.js.map +1 -0
  224. package/dist/core/orphan-exclusions.d.ts +44 -0
  225. package/dist/core/orphan-exclusions.d.ts.map +1 -0
  226. package/dist/core/orphan-exclusions.js +224 -0
  227. package/dist/core/orphan-exclusions.js.map +1 -0
  228. package/dist/core/pair-condition.d.ts +32 -3
  229. package/dist/core/pair-condition.d.ts.map +1 -1
  230. package/dist/core/path-universe.d.ts +22 -0
  231. package/dist/core/path-universe.d.ts.map +1 -0
  232. package/dist/core/path-universe.js +45 -0
  233. package/dist/core/path-universe.js.map +1 -0
  234. package/dist/core/per-root-compiler-options.d.ts +20 -0
  235. package/dist/core/per-root-compiler-options.d.ts.map +1 -0
  236. package/dist/core/per-root-compiler-options.js +57 -0
  237. package/dist/core/per-root-compiler-options.js.map +1 -0
  238. package/dist/core/project-relative.d.ts +98 -0
  239. package/dist/core/project-relative.d.ts.map +1 -0
  240. package/dist/core/project-relative.js +185 -0
  241. package/dist/core/project-relative.js.map +1 -0
  242. package/dist/core/project.d.ts +7 -1
  243. package/dist/core/project.d.ts.map +1 -1
  244. package/dist/core/project.js +29 -4
  245. package/dist/core/project.js.map +1 -1
  246. package/dist/core/rule-builder.d.ts +303 -0
  247. package/dist/core/rule-builder.d.ts.map +1 -0
  248. package/dist/core/rule-builder.js +463 -0
  249. package/dist/core/rule-builder.js.map +1 -0
  250. package/dist/core/rule-declaration.d.ts +32 -0
  251. package/dist/core/rule-declaration.d.ts.map +1 -0
  252. package/dist/core/rule-declaration.js +88 -0
  253. package/dist/core/rule-declaration.js.map +1 -0
  254. package/dist/core/terminal-builder.d.ts +629 -0
  255. package/dist/core/terminal-builder.d.ts.map +1 -0
  256. package/dist/core/terminal-builder.js +807 -0
  257. package/dist/core/terminal-builder.js.map +1 -0
  258. package/dist/core/terminal-execution.d.ts +39 -0
  259. package/dist/core/terminal-execution.d.ts.map +1 -0
  260. package/dist/core/terminal-execution.js +103 -0
  261. package/dist/core/terminal-execution.js.map +1 -0
  262. package/dist/core/ts-comment-mask.d.ts +2 -0
  263. package/dist/core/ts-comment-mask.d.ts.map +1 -0
  264. package/dist/core/ts-comment-mask.js +102 -0
  265. package/dist/core/ts-comment-mask.js.map +1 -0
  266. package/dist/core/vacuity-diagnosis.d.ts +103 -0
  267. package/dist/core/vacuity-diagnosis.d.ts.map +1 -0
  268. package/dist/core/vacuity-diagnosis.js +415 -0
  269. package/dist/core/vacuity-diagnosis.js.map +1 -0
  270. package/dist/core/violation.d.ts +16 -11
  271. package/dist/core/violation.d.ts.map +1 -1
  272. package/dist/core/violation.js +33 -13
  273. package/dist/core/violation.js.map +1 -1
  274. package/dist/graphql/graphql-rule-builder.d.ts +95 -0
  275. package/dist/graphql/graphql-rule-builder.d.ts.map +1 -0
  276. package/dist/graphql/graphql-rule-builder.js +127 -0
  277. package/dist/graphql/graphql-rule-builder.js.map +1 -0
  278. package/dist/graphql/index.d.ts +1 -0
  279. package/dist/graphql/index.d.ts.map +1 -1
  280. package/dist/graphql/index.js +2 -1
  281. package/dist/graphql/index.js.map +1 -1
  282. package/dist/graphql/resolver-rule-builder.d.ts +44 -23
  283. package/dist/graphql/resolver-rule-builder.d.ts.map +1 -1
  284. package/dist/graphql/resolver-rule-builder.js +80 -72
  285. package/dist/graphql/resolver-rule-builder.js.map +1 -1
  286. package/dist/graphql/schema-loader.d.ts +21 -0
  287. package/dist/graphql/schema-loader.d.ts.map +1 -1
  288. package/dist/graphql/schema-loader.js +82 -12
  289. package/dist/graphql/schema-loader.js.map +1 -1
  290. package/dist/graphql/schema-predicates.d.ts.map +1 -1
  291. package/dist/graphql/schema-predicates.js +17 -12
  292. package/dist/graphql/schema-predicates.js.map +1 -1
  293. package/dist/graphql/schema-rule-builder.d.ts +15 -24
  294. package/dist/graphql/schema-rule-builder.d.ts.map +1 -1
  295. package/dist/graphql/schema-rule-builder.js +39 -77
  296. package/dist/graphql/schema-rule-builder.js.map +1 -1
  297. package/dist/helpers/baseline-diagnostics.d.ts +45 -0
  298. package/dist/helpers/baseline-diagnostics.d.ts.map +1 -0
  299. package/dist/helpers/baseline-diagnostics.js +168 -0
  300. package/dist/helpers/baseline-diagnostics.js.map +1 -0
  301. package/dist/helpers/baseline-generator.d.ts +28 -0
  302. package/dist/helpers/baseline-generator.d.ts.map +1 -0
  303. package/dist/helpers/baseline-generator.js +27 -0
  304. package/dist/helpers/baseline-generator.js.map +1 -0
  305. package/dist/helpers/baseline.d.ts +336 -0
  306. package/dist/helpers/baseline.d.ts.map +1 -0
  307. package/dist/helpers/baseline.js +664 -0
  308. package/dist/helpers/baseline.js.map +1 -0
  309. package/dist/helpers/body-traversal.d.ts +27 -2
  310. package/dist/helpers/body-traversal.d.ts.map +1 -1
  311. package/dist/helpers/body-traversal.js +135 -16
  312. package/dist/helpers/body-traversal.js.map +1 -1
  313. package/dist/helpers/callback-extractor.d.ts.map +1 -1
  314. package/dist/helpers/callback-extractor.js +53 -84
  315. package/dist/helpers/callback-extractor.js.map +1 -1
  316. package/dist/helpers/complexity.d.ts +13 -5
  317. package/dist/helpers/complexity.d.ts.map +1 -1
  318. package/dist/helpers/complexity.js +15 -6
  319. package/dist/helpers/complexity.js.map +1 -1
  320. package/dist/helpers/diff-aware.d.ts +16 -0
  321. package/dist/helpers/diff-aware.d.ts.map +1 -0
  322. package/dist/helpers/diff-aware.js +16 -0
  323. package/dist/helpers/diff-aware.js.map +1 -0
  324. package/dist/helpers/matchers.d.ts +68 -7
  325. package/dist/helpers/matchers.d.ts.map +1 -1
  326. package/dist/helpers/matchers.js +164 -86
  327. package/dist/helpers/matchers.js.map +1 -1
  328. package/dist/helpers/slice-graph.d.ts +100 -8
  329. package/dist/helpers/slice-graph.d.ts.map +1 -1
  330. package/dist/helpers/slice-graph.js +126 -34
  331. package/dist/helpers/slice-graph.js.map +1 -1
  332. package/dist/helpers/tarjan.d.ts +0 -14
  333. package/dist/helpers/tarjan.d.ts.map +1 -1
  334. package/dist/helpers/tarjan.js +29 -16
  335. package/dist/helpers/tarjan.js.map +1 -1
  336. package/dist/index.d.ts +55 -19
  337. package/dist/index.d.ts.map +1 -1
  338. package/dist/index.js +67 -15
  339. package/dist/index.js.map +1 -1
  340. package/dist/models/arch-call.d.ts +3 -2
  341. package/dist/models/arch-call.d.ts.map +1 -1
  342. package/dist/models/arch-call.js.map +1 -1
  343. package/dist/models/arch-function.d.ts +54 -8
  344. package/dist/models/arch-function.d.ts.map +1 -1
  345. package/dist/models/arch-function.js +145 -8
  346. package/dist/models/arch-function.js.map +1 -1
  347. package/dist/models/arch-jsx-element.d.ts.map +1 -1
  348. package/dist/models/arch-jsx-element.js +18 -19
  349. package/dist/models/arch-jsx-element.js.map +1 -1
  350. package/dist/models/slice.d.ts +33 -9
  351. package/dist/models/slice.d.ts.map +1 -1
  352. package/dist/models/slice.js +129 -19
  353. package/dist/models/slice.js.map +1 -1
  354. package/dist/predicates/call.d.ts.map +1 -1
  355. package/dist/predicates/call.js +5 -0
  356. package/dist/predicates/call.js.map +1 -1
  357. package/dist/predicates/identity.d.ts +21 -0
  358. package/dist/predicates/identity.d.ts.map +1 -1
  359. package/dist/predicates/identity.js +75 -3
  360. package/dist/predicates/identity.js.map +1 -1
  361. package/dist/predicates/index.d.ts +1 -1
  362. package/dist/predicates/index.d.ts.map +1 -1
  363. package/dist/predicates/index.js +1 -1
  364. package/dist/predicates/index.js.map +1 -1
  365. package/dist/predicates/jsx.d.ts.map +1 -1
  366. package/dist/predicates/jsx.js +2 -1
  367. package/dist/predicates/jsx.js.map +1 -1
  368. package/dist/predicates/metrics.d.ts +4 -2
  369. package/dist/predicates/metrics.d.ts.map +1 -1
  370. package/dist/predicates/metrics.js +4 -2
  371. package/dist/predicates/metrics.js.map +1 -1
  372. package/dist/predicates/module.d.ts +4 -12
  373. package/dist/predicates/module.d.ts.map +1 -1
  374. package/dist/predicates/module.js +57 -37
  375. package/dist/predicates/module.js.map +1 -1
  376. package/dist/presets/agent-guardrails.d.ts +49 -16
  377. package/dist/presets/agent-guardrails.d.ts.map +1 -1
  378. package/dist/presets/agent-guardrails.js +308 -19
  379. package/dist/presets/agent-guardrails.js.map +1 -1
  380. package/dist/presets/boundaries.d.ts +46 -3
  381. package/dist/presets/boundaries.d.ts.map +1 -1
  382. package/dist/presets/boundaries.js +132 -23
  383. package/dist/presets/boundaries.js.map +1 -1
  384. package/dist/presets/data-layer.d.ts +23 -3
  385. package/dist/presets/data-layer.d.ts.map +1 -1
  386. package/dist/presets/data-layer.js +58 -16
  387. package/dist/presets/data-layer.js.map +1 -1
  388. package/dist/presets/index.d.ts +10 -5
  389. package/dist/presets/index.d.ts.map +1 -1
  390. package/dist/presets/index.js +19 -3
  391. package/dist/presets/index.js.map +1 -1
  392. package/dist/presets/layered.d.ts +47 -3
  393. package/dist/presets/layered.d.ts.map +1 -1
  394. package/dist/presets/layered.js +66 -29
  395. package/dist/presets/layered.js.map +1 -1
  396. package/dist/presets/recommended.d.ts +81 -10
  397. package/dist/presets/recommended.d.ts.map +1 -1
  398. package/dist/presets/recommended.js +25 -23
  399. package/dist/presets/recommended.js.map +1 -1
  400. package/dist/presets/shared.d.ts +267 -2
  401. package/dist/presets/shared.d.ts.map +1 -1
  402. package/dist/presets/shared.js +367 -4
  403. package/dist/presets/shared.js.map +1 -1
  404. package/dist/rules/code-quality.d.ts.map +1 -1
  405. package/dist/rules/code-quality.js +15 -6
  406. package/dist/rules/code-quality.js.map +1 -1
  407. package/dist/rules/hygiene.d.ts +1 -1
  408. package/dist/rules/hygiene.js +1 -1
  409. package/dist/rules/metrics-function.d.ts +2 -1
  410. package/dist/rules/metrics-function.d.ts.map +1 -1
  411. package/dist/rules/metrics-function.js +63 -39
  412. package/dist/rules/metrics-function.js.map +1 -1
  413. package/dist/rules/metrics.d.ts +2 -1
  414. package/dist/rules/metrics.d.ts.map +1 -1
  415. package/dist/rules/metrics.js +80 -47
  416. package/dist/rules/metrics.js.map +1 -1
  417. package/dist/smells/clusters.d.ts +78 -0
  418. package/dist/smells/clusters.d.ts.map +1 -0
  419. package/dist/smells/clusters.js +124 -0
  420. package/dist/smells/clusters.js.map +1 -0
  421. package/dist/smells/duplicate-bodies.d.ts +92 -5
  422. package/dist/smells/duplicate-bodies.d.ts.map +1 -1
  423. package/dist/smells/duplicate-bodies.js +203 -73
  424. package/dist/smells/duplicate-bodies.js.map +1 -1
  425. package/dist/smells/duplicate-report.d.ts +90 -0
  426. package/dist/smells/duplicate-report.d.ts.map +1 -0
  427. package/dist/smells/duplicate-report.js +344 -0
  428. package/dist/smells/duplicate-report.js.map +1 -0
  429. package/dist/smells/fingerprint.d.ts +20 -1
  430. package/dist/smells/fingerprint.d.ts.map +1 -1
  431. package/dist/smells/fingerprint.js +27 -3
  432. package/dist/smells/fingerprint.js.map +1 -1
  433. package/dist/smells/inconsistent-siblings.d.ts +128 -7
  434. package/dist/smells/inconsistent-siblings.d.ts.map +1 -1
  435. package/dist/smells/inconsistent-siblings.js +288 -86
  436. package/dist/smells/inconsistent-siblings.js.map +1 -1
  437. package/dist/smells/sibling-files.d.ts +47 -0
  438. package/dist/smells/sibling-files.d.ts.map +1 -0
  439. package/dist/smells/sibling-files.js +104 -0
  440. package/dist/smells/sibling-files.js.map +1 -0
  441. package/dist/smells/similar-pairs.d.ts +28 -0
  442. package/dist/smells/similar-pairs.d.ts.map +1 -0
  443. package/dist/smells/similar-pairs.js +134 -0
  444. package/dist/smells/similar-pairs.js.map +1 -0
  445. package/dist/smells/smell-builder.d.ts +57 -12
  446. package/dist/smells/smell-builder.d.ts.map +1 -1
  447. package/dist/smells/smell-builder.js +112 -14
  448. package/dist/smells/smell-builder.js.map +1 -1
  449. package/dist/smells/variation.d.ts +47 -0
  450. package/dist/smells/variation.d.ts.map +1 -0
  451. package/dist/smells/variation.js +90 -0
  452. package/dist/smells/variation.js.map +1 -0
  453. package/dist/tsconfig/index.d.ts +19 -0
  454. package/dist/tsconfig/index.d.ts.map +1 -0
  455. package/dist/tsconfig/index.js +20 -0
  456. package/dist/tsconfig/index.js.map +1 -0
  457. package/dist/tsconfig/tsconfig-builder.d.ts +42 -9
  458. package/dist/tsconfig/tsconfig-builder.d.ts.map +1 -1
  459. package/dist/tsconfig/tsconfig-builder.js +65 -16
  460. package/dist/tsconfig/tsconfig-builder.js.map +1 -1
  461. package/package.json +4 -2
  462. package/dist/core/module-dependencies.d.ts +0 -28
  463. package/dist/core/module-dependencies.d.ts.map +0 -1
  464. package/dist/core/module-dependencies.js +0 -35
  465. package/dist/core/module-dependencies.js.map +0 -1
  466. package/dist/helpers/within.d.ts.map +0 -1
  467. package/dist/helpers/within.js.map +0 -1
@@ -0,0 +1,593 @@
1
+ import { Node, SyntaxKind } from 'ts-morph';
2
+ import { isTypeOnlyImport, isTypeOnlyReExport } from './import-options.js';
3
+ import { registerCacheReset } from '@nielspeter/eess/internal';
4
+ import { verbatimModuleSyntaxFor } from './per-root-compiler-options.js';
5
+ /**
6
+ * Every module edge leaving each file, in one call (ADR-007 rule 2).
7
+ *
8
+ * **Cached since plan 0076**, per file, invalidated by `onModified`. The
9
+ * sentence this paragraph used to carry — *"No cache … if a consumer reports a
10
+ * multiple-slowdown, the fix is a cache of resolution, not of the walk"* — was
11
+ * half right: a consumer did report one, and the walk is indeed not the cost
12
+ * (1ms across five passes over 520 files). But resolution is not the cost
13
+ * either. Building the `ModuleEdge` is: 15ms resolution against ~32ms
14
+ * construction, of 48ms total. So the cache is of the built edges, and the
15
+ * forward commitment this docstring made — *"what it forecloses is batching a
16
+ * resolution cache later"* — is discharged rather than left standing.
17
+ *
18
+ */
19
+ export function moduleEdges(files) {
20
+ const byFile = new Map();
21
+ for (const sf of files) {
22
+ byFile.set(sf.getFilePath(), edgesOf(sf));
23
+ }
24
+ return byFile;
25
+ }
26
+ /**
27
+ * Every module edge leaving one file, in source order.
28
+ *
29
+ * Exported for the predicate sites, which are per-element by construction and
30
+ * would otherwise build a one-entry `Map` per file just to read it back out.
31
+ */
32
+ export function edgesOf(sourceFile) {
33
+ const hit = cache.get(sourceFile);
34
+ if (hit !== undefined)
35
+ return hit;
36
+ const edges = buildEdges(sourceFile);
37
+ if (!watched.has(sourceFile)) {
38
+ // Once per file, not once per miss: a watch session that re-evaluates
39
+ // rules would otherwise accumulate one listener per rule execution.
40
+ watched.add(sourceFile);
41
+ sourceFile.onModified(() => cache.delete(sourceFile));
42
+ }
43
+ cache.set(sourceFile, edges);
44
+ return edges;
45
+ }
46
+ /**
47
+ * One built edge list per file, invalidated when the file is modified.
48
+ *
49
+ * Plan 0076. Measured on this repository (520 files): five whole-project
50
+ * `notImportFrom` rules made **10,525 `getSymbol()` calls in 47ms** where 2,105
51
+ * would do — exactly 5x, because rules that share subjects re-resolve the same
52
+ * literals. Five *disjoint* folder rules cost 388, so the win tracks subject
53
+ * overlap rather than rule count.
54
+ *
55
+ * **Why not `resolve()` alone**, which this file's own docstring above
56
+ * recommends: measured across five passes, the walk is 1ms, resolution 15ms and
57
+ * building the `ModuleEdge` ~32ms. The advice predates anyone splitting the
58
+ * three, and resolution is the middle third rather than the cost.
59
+ *
60
+ * **Why a listener rather than object identity.** A `SourceFile`'s identity
61
+ * SURVIVES an edit — measured, `addImportDeclaration` and `replaceWithText`
62
+ * both keep the same object while the edges change — so the argument that makes
63
+ * `WeakMap<ArchProject, …>` safe in `element-cache.ts` does **not** transfer. A
64
+ * `SourceFile`-keyed cache without invalidation serves pre-edit edges after an
65
+ * edit, and a `notImportFrom` rule then passes on the import the edit just
66
+ * added: ADR-008's false green, manufactured by a cache. `onModified` is a
67
+ * ts-morph API (no raw compiler access, ADR-002 intact) and fires on every
68
+ * mutation path — `addImportDeclaration`, `replaceWithText`, `remove` and
69
+ * `insertText` — and never on a read.
70
+ */
71
+ let cache = new WeakMap();
72
+ const watched = new WeakSet();
73
+ /**
74
+ * Drop every cached edge list. Called by `resetProjectCache()`.
75
+ *
76
+ * `onModified` covers a change to the file that OWNS the edge. It does not cover
77
+ * a change to the edge's **target** — `resolvedPath` is a function of the whole
78
+ * program, so creating the file a specifier could not resolve to, or deleting
79
+ * the one it did, leaves the importer's cached edge stale. Measured, both
80
+ * directions. This is the escape hatch for that; `watched` is deliberately not
81
+ * cleared, since those listeners stay correct.
82
+ */
83
+ function clearModuleEdgeCache() {
84
+ cache = new WeakMap();
85
+ }
86
+ registerCacheReset(clearModuleEdgeCache);
87
+ function buildEdges(sourceFile) {
88
+ // Once per file, not once per literal. Measured: 0.1ms across this repo's 574
89
+ // files, so hoisting is for clarity rather than cost.
90
+ const verbatim = usesVerbatimModuleSyntax(sourceFile);
91
+ const edges = [];
92
+ for (const literal of sourceFile.getImportStringLiterals()) {
93
+ const parent = literal.getParent();
94
+ if (parent === undefined)
95
+ continue;
96
+ const kind = kindOf(parent);
97
+ if (kind === undefined)
98
+ continue;
99
+ edges.push({
100
+ // The literal's absolute position, so the sort below is genuine source
101
+ // order. It is dropped from the public shape by the `map` at the end.
102
+ pos: literal.getPos(),
103
+ ...makeEdge(literal, parent, kind, verbatim),
104
+ // Sorted by the literal's absolute position so the result is source-ordered
105
+ // and deterministic. The binder's `imports` array puts declaration forms
106
+ // first and expression forms after, regardless of where they appear — so
107
+ // without this, `kind === 'import'` filtered out of an interleaved file
108
+ // would still be source-ordered but `relpath:line` multisets across kinds
109
+ // would not be, and item 8's fixture is exactly such a file.
110
+ });
111
+ }
112
+ // Source order, by the literal's absolute position.
113
+ //
114
+ // This used to be `(line, specifier.localeCompare(...))`, which was two defects
115
+ // in one line. The comment claimed "the literal's absolute position" and the
116
+ // code did not use it — measured, `import { Z } from './z.js'; import { A } from
117
+ // './a.js'` on ONE line came back `./a.js, ./z.js` against declaration order
118
+ // `./z.js, ./a.js`, which is one same-line double import away from a false red
119
+ // in the corpus sequence-equality test. And `localeCompare` is ICU/locale
120
+ // sensitive — exactly the machine-dependent ordering `conditions/slice.ts` goes
121
+ // out of its way to eliminate, because a value that differs per machine gives
122
+ // one finding two identities.
123
+ const counters = new Map();
124
+ return (edges.length > 1 ? [...edges].sort((a, b) => a.pos - b.pos) : edges).map(({ pos: _pos, ...edge }) => ({ ...edge, ordinal: nextOrdinal(counters, edge) }));
125
+ }
126
+ /**
127
+ * What tells two edges of the same kind, from the same file, to the same module apart.
128
+ *
129
+ * `names` when there are any; the source-order ordinal when there are not — and **`names` is
130
+ * empty for a SPELLING, not for a kind**, which is the distinction the whole of this comment
131
+ * turns on. `dynamic`, `require` and `type-expression` never carry names, and neither do four
132
+ * ordinary `import`/`reexport` spellings (`import D from`, `import * as NS from`, a bare
133
+ * `import './x.js'`, `export * from`). Any of them, twice to one module from one file,
134
+ * measured **2 findings, 1 hash** against a control of 2/2 for two named imports — so one
135
+ * accepted baseline entry silently pre-accepts the next one someone adds. Bug 0028's shape,
136
+ * in every spelling that reached this function without a discriminator; the lazy kinds are
137
+ * merely the ones
138
+ * [ts-archunit bug 0059](https://github.com/nielspeter/ts-archunit/blob/main/bugs/fixed/0059-slice-conditions-and-module-conditions-disagree-about-a-dependency.md)
139
+ * made reportable, which is how the narrower reading got written here in the first place.
140
+ *
141
+ * The sort and the `,` are load-bearing and cheap to lose: `getNamedImports()` returns source
142
+ * order, so without the sort a cosmetic reorder of a named import list moves every multi-name
143
+ * entry in an adopter's baseline — an import-sorting lint autofix would do it. Without the
144
+ * separator, `['a','b']` and `['ab']` collide. Both are pinned by the multi-name row in
145
+ * `tests/conditions/identity-does-not-move.test.ts`, and by nothing else in the suite.
146
+ *
147
+ * **No existing baseline entry moves**, and that is what the `ordinal === 0` branch buys.
148
+ * The naive form — `#${ordinal}` whenever `names` is empty — moves far more than the three
149
+ * kinds it was written for, because `names` is empty for four ordinary `import`/`reexport`
150
+ * spellings too: `import D from`, `import * as NS from`, a bare `import './x.js'`, and
151
+ * `export * from` (the barrel). `export * as NS from` is **not** among them — it carries one
152
+ * statically-known name. That form shipped briefly in v0.56.0's development and was caught by
153
+ * review, measured against `main` through the public conditions: 4 of 7 spellings moved, in
154
+ * both families, while the CHANGELOG and ts-archunit's `docs/upgrading.md` promised none did.
155
+ *
156
+ * Emitting `''` for the first edge of each group reproduces exactly what the pre-ordinal
157
+ * formula produced (`[...names].sort().join(',')` over an empty list), so every
158
+ * single-occurrence finding keeps a byte-identical identity — measured across all seven
159
+ * spellings plus `dynamic` and `type-expression`, zero diff. The `#n` suffix appears only on
160
+ * the **second and later** edge of one kind to one module from one file, which is precisely
161
+ * the group that had two findings and one hash before, i.e. a baseline entry that was already
162
+ * wrong. So the fail-open closes and the migration is empty — the surviving entry still
163
+ * matches, and only the genuinely-new sibling is reported.
164
+ *
165
+ * Uniqueness still holds: within a group the sequence `''`, `#1`, `#2`, … is injective, and
166
+ * `''` is unreachable from the named branch because no import specifier is an empty
167
+ * identifier.
168
+ *
169
+ * The cost, stated so it is a decision rather than a discovery: the discriminator is no longer
170
+ * uniform, so `…::` no longer distinguishes "names-less, first" from "not computed". That is
171
+ * a readability loss traded for a migration nobody has to perform.
172
+ */
173
+ export function edgeDiscriminator(edge) {
174
+ // Unicode codepoint order, NOT `localeCompare` — a baseline identity may not depend on the
175
+ // machine that computed it. `localeCompare` reads the host locale, and this file already said
176
+ // so 60 lines above (`indexEdges`: "exactly the machine-dependent ordering `conditions/slice.ts`
177
+ // goes out of its way to eliminate, because a value that differs per machine gives one finding
178
+ // two identities") — and then used it here anyway. Measured on plain ASCII: `zebra, aardvark`
179
+ // sorts to `aardvark,zebra` under `en-US` and to `zebra,aardvark` under `da-DK`, because Danish
180
+ // collates `aa` as `å`, after `z`. Same import, two baseline hashes, diverging only between a
181
+ // developer's machine and CI. `src/core/project.ts` uses this comparator for the same reason.
182
+ if (edge.names.length > 0)
183
+ return [...edge.names].sort((a, b) => (a < b ? -1 : a > b ? 1 : 0)).join(',');
184
+ return edge.ordinal === 0 ? '' : `#${String(edge.ordinal)}`;
185
+ }
186
+ /** Which of the five forms this literal belongs to, or `undefined` if none. */
187
+ function kindOf(parent) {
188
+ if (Node.isImportDeclaration(parent))
189
+ return 'import';
190
+ if (Node.isExportDeclaration(parent))
191
+ return 'reexport';
192
+ if (Node.isLiteralTypeNode(parent))
193
+ return 'type-expression';
194
+ if (Node.isExternalModuleReference(parent))
195
+ return 'require';
196
+ if (Node.isCallExpression(parent)) {
197
+ // The one place `import()` and `require()` are indistinguishable by parent
198
+ // kind. `reverse-dependency.ts` already discriminates this way.
199
+ return parent.getExpression().getKind() === SyntaxKind.ImportKeyword ? 'dynamic' : 'require';
200
+ }
201
+ return undefined;
202
+ }
203
+ /**
204
+ * The resolved file, via the **specifier's** symbol.
205
+ *
206
+ * One mechanism for all five parent kinds, and it returns the **named** module:
207
+ * `type A = import('./barrel.js').Deep` resolves to `barrel.ts`, where following
208
+ * the *type* symbol instead lands on `impl.ts` and would make
209
+ * `notImportFrom('**\/impl.ts')` fire on a file that never names `impl`.
210
+ *
211
+ * **`getDeclarations()[0]` is not the answer.** With a module augmentation
212
+ * elsewhere in the project, the symbol has two declarations — the `SourceFile`
213
+ * and a `ModuleDeclaration` in the augmenting file — and `[0]` is whichever the
214
+ * compiler merged first. ts-morph's own `ModuleUtils.getReferencedSourceFileFromSymbol`
215
+ * takes `[0]` and bails to `undefined` when it is not a SourceFile, so the other
216
+ * ordering is live in the reference implementation.
217
+ *
218
+ * **How live, measured:** across four shapes — the augmenting file sorting first
219
+ * alphabetically, two augmentations of one module, a `.d.ts` target, and the
220
+ * augmentation written inside the importing file itself — the `SourceFile` came
221
+ * first **every time**. So this is defence against an ordering that is documented
222
+ * in ts-morph's own code and that no arrangement here reproduces, not a fix for an
223
+ * observable defect. A review flagged it as a certain field false positive; that
224
+ * claim did not survive measurement, and saying so is cheaper than a future reader
225
+ * re-deriving it. `find` costs nothing and cannot be wrong, so it stays — but the
226
+ * `[0]` variant passes this repo's suite, which is recorded in
227
+ * `tests/core/module-edges-forms.test.ts` rather than hidden.
228
+ */
229
+ function resolve(literal) {
230
+ for (const declaration of literal.getSymbol()?.getDeclarations() ?? []) {
231
+ if (Node.isSourceFile(declaration))
232
+ return declaration.getFilePath();
233
+ }
234
+ return undefined;
235
+ }
236
+ /**
237
+ * The line of the statement carrying the edge, not of the literal.
238
+ *
239
+ * The nearest **edge-carrying node** — the declaration, call or import-type that
240
+ * names the module — not the nearest enclosing `Statement`.
241
+ *
242
+ * For the declaration forms the two are the same node, so `import` still equals
243
+ * `decl.getStartLineNumber()` and the corpus equality test holds. They diverge
244
+ * for an expression form nested inside a larger statement, and there the
245
+ * statement is the wrong answer: measured, `register({ handlers: { a: () =>
246
+ * import('./banned.js') } })` spanning lines 3–7 reported **line 3**, pointing the
247
+ * code frame at `register(` rather than at the import, and a class property
248
+ * `loader = import('./x.js')` reported the `ClassDeclaration`'s line because a
249
+ * `PropertyDeclaration` is not a `Statement`. A lazily-loaded route inside an
250
+ * object literal is the commonest real dynamic import, so that was the common
251
+ * case rather than a corner.
252
+ *
253
+ * Falls back to the literal's own line if no carrier is found, which the 20-form
254
+ * corpus does not produce — a guard, not a path.
255
+ */
256
+ function statementLine(literal) {
257
+ const carrier = literal.getFirstAncestor((a) => Node.isImportDeclaration(a) ||
258
+ Node.isExportDeclaration(a) ||
259
+ Node.isImportEqualsDeclaration(a) ||
260
+ Node.isCallExpression(a) ||
261
+ Node.isImportTypeNode(a));
262
+ return (carrier ?? literal).getStartLineNumber();
263
+ }
264
+ /**
265
+ * Whether the edge is erased at compile time.
266
+ *
267
+ * Per kind, and the two constants are the classification traps: `require` is
268
+ * **runtime** (an `else → type-expression` branch is what made it look erased)
269
+ * and `dynamic` is always runtime.
270
+ */
271
+ function isErased(kind, parent) {
272
+ switch (kind) {
273
+ case 'import':
274
+ // Reused unchanged. Its `getDefaultImport()`/`getNamespaceImport()` guards
275
+ // are load-bearing: `import React, { type FC } from 'react'` is a RUNTIME
276
+ // edge, and a formula without them classifies it type-only and skips it
277
+ // under `ignoreTypeImports` — a lost existing finding.
278
+ return Node.isImportDeclaration(parent) ? isTypeOnlyImport(parent) : false;
279
+ case 'reexport':
280
+ return Node.isExportDeclaration(parent) ? isTypeOnlyReExport(parent) : false;
281
+ case 'type-expression':
282
+ return true;
283
+ case 'dynamic':
284
+ case 'require':
285
+ return false;
286
+ }
287
+ }
288
+ /**
289
+ * Whether the statement vanishes entirely, emitting no module request.
290
+ *
291
+ * `typeOnly` is passed in rather than recomputed: the two answers must agree on the
292
+ * same node, and `isErased` is not free (it walks specifiers).
293
+ *
294
+ * Under `verbatimModuleSyntax` TypeScript preserves the statement unless the `type`
295
+ * modifier is on the **declaration** — `import type { X }` goes, `import { type X }`
296
+ * stays as `import {} from 's'`. Without the flag, elision is by binding usage and
297
+ * every type-only form disappears.
298
+ */
299
+ function erasesRequest(kind, parent, typeOnly, verbatimModuleSyntax) {
300
+ // A statement that binds a runtime value is always emitted.
301
+ if (!typeOnly)
302
+ return false;
303
+ if (!verbatimModuleSyntax)
304
+ return true;
305
+ switch (kind) {
306
+ case 'import':
307
+ return Node.isImportDeclaration(parent) ? parent.isTypeOnly() : true;
308
+ case 'reexport':
309
+ return Node.isExportDeclaration(parent) ? parent.isTypeOnly() : true;
310
+ case 'type-expression':
311
+ // `type X = import('s').Y` is a type position: never emitted under any flag.
312
+ return true;
313
+ case 'dynamic':
314
+ case 'require':
315
+ // Unreachable — neither is ever `typeOnly` — but stated rather than defaulted,
316
+ // for the same reason the sibling switches in this file are exhaustive.
317
+ return false;
318
+ }
319
+ }
320
+ /**
321
+ * One edge, built in one place.
322
+ *
323
+ * `buildEdges` and `edgeStream` each used to spell out the same field list, which is
324
+ * a shape that drifts silently: `edgeStream`'s only consumer reads `typeOnly`, so a
325
+ * field missing there would never surface until something else looked.
326
+ */
327
+ function makeEdge(literal, parent, kind, verbatimModuleSyntax) {
328
+ const typeOnly = isErased(kind, parent);
329
+ return {
330
+ kind,
331
+ // `getLiteralText()`, NOT `getText().slice(1, -1)` and NOT a narrowing — see the
332
+ // module docstring. The declared element type of `getImportStringLiterals()` is
333
+ // what this parameter takes, so the accessor is available without narrowing a
334
+ // node that may really be a NoSubstitutionTemplateLiteral.
335
+ specifier: literal.getLiteralText(),
336
+ resolvedPath: resolve(literal),
337
+ line: statementLine(literal),
338
+ typeOnly,
339
+ erasesModuleRequest: erasesRequest(kind, parent, typeOnly, verbatimModuleSyntax),
340
+ names: namesOf(kind, parent),
341
+ // Filled by the collectors, which are the only callers that can see the file's
342
+ // other edges. `makeEdge` is per-literal and has no way to count siblings.
343
+ ordinal: 0,
344
+ };
345
+ }
346
+ /**
347
+ * The next ordinal for `kind::specifier`, mutating `counters`.
348
+ *
349
+ * Shared by both collectors so they cannot drift: an identity that depended on which
350
+ * code path built the edge would be worse than the collision it fixes.
351
+ */
352
+ function nextOrdinal(counters, edge) {
353
+ const key = `${edge.kind}::${edge.specifier}`;
354
+ const n = counters.get(key) ?? 0;
355
+ counters.set(key, n + 1);
356
+ return n;
357
+ }
358
+ /**
359
+ * `verbatimModuleSyntax` for the package that owns this file, off when absent.
360
+ *
361
+ * Delegated rather than read from the project, because inside a `workspace()` the project
362
+ * carries the alphabetically-first tsconfig's options and every other package would be
363
+ * judged by them — wrong in both directions, measured
364
+ * ([ts-archunit bug 0058](https://github.com/nielspeter/ts-archunit/blob/main/bugs/fixed/0058-workspace-applies-one-packages-compiler-flag-to-all.md)).
365
+ */
366
+ function usesVerbatimModuleSyntax(sourceFile) {
367
+ return verbatimModuleSyntaxFor(sourceFile);
368
+ }
369
+ /** The names crossing the edge. See {@link ModuleEdge.names} for which name. */
370
+ function namesOf(kind, parent) {
371
+ if (kind === 'import' && Node.isImportDeclaration(parent)) {
372
+ // Inward names. A default or namespace binding contributes none — it crosses
373
+ // under a name the specifier list does not carry.
374
+ return parent.getNamedImports().map((specifier) => specifier.getName());
375
+ }
376
+ if (kind === 'reexport' && Node.isExportDeclaration(parent)) {
377
+ // `export * as NS` is not a star here: one statically-known name.
378
+ const namespaceExport = parent.getNamespaceExport();
379
+ if (namespaceExport !== undefined)
380
+ return [namespaceExport.getName()];
381
+ // Outward names, so `export { INNER as OUTER }` reports `OUTER`.
382
+ return parent
383
+ .getNamedExports()
384
+ .map((specifier) => specifier.getAliasNode()?.getText() ?? specifier.getName());
385
+ }
386
+ return [];
387
+ }
388
+ /**
389
+ * How a finding refers to this kind of edge.
390
+ *
391
+ * **An exhaustive `switch`, not a `Record` lookup or a 4-way branch** (plan 0071
392
+ * §4). Measured on a build with `require` unfiltered and no `require` verb: a
393
+ * `Record` lookup emitted the literal string `undefined` into a message —
394
+ * `cjs-consumer.js undefined "…/target.ts" which matches forbidden […]` — and
395
+ * that text is hashed into a baseline. A missing verb must be a compile error;
396
+ * with an explicit `string` return and no fallthrough, adding a sixth
397
+ * `ModuleEdgeKind` breaks the build here.
398
+ *
399
+ * `require` gets a real verb even though no condition reports it (§3). The
400
+ * alternative — throwing, or returning a placeholder — makes a forgotten kind
401
+ * filter produce nonsense instead of a correct sentence, and a correct sentence
402
+ * costs one line.
403
+ *
404
+ * **`import` must stay byte-identical.** Every existing baselined dependency
405
+ * finding hashes its message, so changing this string for `import` silently
406
+ * invalidates them all; the new kinds get distinct verbs precisely so their
407
+ * findings are NOT absorbed by an existing `import` entry for the same module.
408
+ */
409
+ export function edgeVerb(kind) {
410
+ return EDGE_WORDS[kind].verb;
411
+ }
412
+ /**
413
+ * Both words for every edge kind, in one table.
414
+ *
415
+ * They were two exhaustive switches over the same union — `no-copy-paste`
416
+ * reported them at 100% — and keeping them apart is what lets a new kind be
417
+ * added with a verb and no noun phrase, which compiles: the `Record` makes
418
+ * that a type error instead, so a kind cannot be half-described.
419
+ *
420
+ * `import`'s verb must stay byte-identical. Every existing baselined
421
+ * dependency finding hashes its message, so changing that one string silently
422
+ * invalidates them all; the other kinds get distinct verbs precisely so their
423
+ * findings are NOT absorbed by an existing `import` entry for the same module.
424
+ */
425
+ const EDGE_WORDS = {
426
+ import: { verb: 'imports', valuePhrase: 'a value import from' },
427
+ reexport: { verb: 're-exports', valuePhrase: 'a runtime re-export of' },
428
+ dynamic: { verb: 'dynamically imports', valuePhrase: 'a dynamic import of' },
429
+ 'type-expression': {
430
+ verb: 'references the type from',
431
+ valuePhrase: 'a type reference to',
432
+ },
433
+ require: { verb: 'requires', valuePhrase: 'a require call for' },
434
+ };
435
+ /**
436
+ * How a finding describes a **runtime** edge of this kind, for
437
+ * `onlyHaveTypeImportsFrom`.
438
+ *
439
+ * Separate from {@link edgeVerb} because that condition's sentence needs a noun
440
+ * phrase ("has a value import from") rather than a verb, and because its remedy
441
+ * differs per kind in a way the verb does not capture — see
442
+ * {@link edgeTypeOnlyRemedy}.
443
+ */
444
+ export function edgeValuePhrase(kind) {
445
+ return EDGE_WORDS[kind].valuePhrase;
446
+ }
447
+ /**
448
+ * The remedy for a runtime edge that should be type-only — **per kind, because
449
+ * the remedy differs and one of them has a consequence** (ADR-009 rule 2).
450
+ *
451
+ * `onlyHaveTypeImportsFrom`'s shipped preset says *"Use `import type { X }` so
452
+ * the dependency is erased"*. For an `import` that is complete and local. For a
453
+ * re-export it is not: `export type { X } from` erases the edge **and removes a
454
+ * runtime export consumers may be importing as a value**. The finding still
455
+ * stands — the runtime dependency is real — but a remedy that silently changes
456
+ * what the module publishes is a remedy the reader must be told about.
457
+ *
458
+ * `dynamic` is excluded from that condition entirely for the stronger version of
459
+ * the same reason: there is no remedy at all. You cannot erase an
460
+ * `await import(…)`.
461
+ */
462
+ export function edgeTypeOnlyRemedy(edge) {
463
+ switch (edge.kind) {
464
+ case 'import':
465
+ return 'Change it to `import type { … }` so the dependency is erased at compile time.';
466
+ case 'reexport':
467
+ // A STAR re-export has no names to put in the braces, and telling the reader
468
+ // to write `export type { … } from` there asks them to enumerate the target's
469
+ // entire export list — which an agent will invent rather than look up.
470
+ // `export type * from` is the one-token fix, and `isTypeOnlyReExport`
471
+ // already recognises it.
472
+ if (edge.names.length === 0) {
473
+ return ('Change it to `export type * from …`, which erases the dependency. Note this removes the ' +
474
+ 'runtime re-exports too — check no consumer imports any of them as a value.');
475
+ }
476
+ return ('Change it to `export type { … } from …`, which erases the dependency but also removes a ' +
477
+ 'runtime export — check no consumer imports it as a value. If one does, re-export it from ' +
478
+ 'a module this rule permits, or stop re-exporting it here.');
479
+ case 'dynamic':
480
+ return 'A dynamic import cannot be erased. Move the dependency behind an interface this rule permits.';
481
+ case 'type-expression':
482
+ return 'This edge is already erased; no change is needed.';
483
+ case 'require':
484
+ return 'Convert the `require` to an `import type { … }`, or move the dependency.';
485
+ }
486
+ }
487
+ /**
488
+ * The noun for this kind of edge, for `onlyHaveTypeImportsFrom`'s sentence tail.
489
+ *
490
+ * `edgeValuePhrase` was made per-kind and the tail was not, so a re-export read
491
+ * "has a runtime re-export of … which should be a type-only **import**". The two
492
+ * halves have to agree or the sentence contradicts itself.
493
+ */
494
+ /**
495
+ * The kinds a **forward** dependency site reports on.
496
+ *
497
+ * One constant, because there were two: `DEPENDENCY_KINDS` in
498
+ * `conditions/dependency.ts` and `PREDICATE_KINDS` in `predicates/module.ts`, whose
499
+ * docstring said "the same set as the conditions … and it has to be" with prose as
500
+ * the only enforcement. `notImportFrom` is one identifier with two definitions
501
+ * chosen by chain position, so a predicate that disagreed with its own condition
502
+ * about what an import is would be this release's Problem statement in miniature.
503
+ *
504
+ * **Exhaustive, not an allowlist filter.** A sixth `ModuleEdgeKind` is a compile
505
+ * error here rather than a kind silently excluded everywhere — that fail-open is the
506
+ * same false green this release closes.
507
+ *
508
+ * `require` is `false`: the kind exists so a 4-way branch cannot mark a CJS runtime
509
+ * dependency as erased, not to enforce CJS. The **reverse** graph counts it, which
510
+ * is the opposite disposition and deliberately so — see `indexEdges`'s reasoning.
511
+ * `onlyHaveTypeImportsFrom` diverges further still (`TYPE_IMPORT_KINDS`), and that
512
+ * one divergence is intentional and documented at its own site.
513
+ */
514
+ export const FORWARD_EDGE_KINDS = {
515
+ import: true,
516
+ reexport: true,
517
+ dynamic: true,
518
+ 'type-expression': true,
519
+ require: false,
520
+ };
521
+ /**
522
+ * Every module edge leaving one file, **lazily and unsorted**.
523
+ *
524
+ * For a caller that only asks "is there any edge matching X". `edgesOf` builds and
525
+ * resolves the whole array before returning, so `edgesOf(sf).some(...)` pays a
526
+ * `getSymbol()` for every literal in the file even when the first one answers the
527
+ * question — on a 100-import file whose first import matches, 100 checker calls
528
+ * where the pre-0.28.0 code made 1.
529
+ *
530
+ * **Order is unspecified, and since plan 0076 it differs between a cold and a
531
+ * warm call.** Cold, edges arrive in walk order — the declaration forms first,
532
+ * because that is how ts-morph enumerates them. Warm, they arrive in the source
533
+ * order {@link edgesOf} sorted them into. Measured, on a file whose dynamic
534
+ * import precedes its declaration import:
535
+ *
536
+ * cold ./a.js, ./b.js
537
+ * warm ./b.js, ./a.js
538
+ *
539
+ * No verdict depends on it today: the only consumer is `dependOn`
540
+ * (`conditions/dependency.ts`), which is a `.some()` and stops at the first
541
+ * match. But "sometimes sorted" is a worse contract than "never sorted", so it
542
+ * is stated rather than left to be discovered. **Anything that reports a
543
+ * finding must use {@link edgesOf}**, whose source ordering is part of its
544
+ * contract — a reporting site fed from here would name a different edge
545
+ * depending on whether an unrelated rule warmed the file first, which is one
546
+ * finding with two identities.
547
+ */
548
+ export function* edgeStream(sourceFile) {
549
+ // Warm: yield the already-built edges. The caller still breaks early, and
550
+ // iterating a materialized array costs nothing — the resolution it was
551
+ // avoiding has already happened.
552
+ const hit = cache.get(sourceFile);
553
+ if (hit !== undefined) {
554
+ yield* hit;
555
+ return;
556
+ }
557
+ const verbatim = usesVerbatimModuleSyntax(sourceFile);
558
+ // Cold: stream, and deliberately do NOT populate the cache. Filling it here
559
+ // would resolve every literal in the file to answer a question the first one
560
+ // may settle, which is the cost this generator exists to avoid
561
+ // (`dependency.ts:327-334`).
562
+ // Sorted by position, so `ordinal` matches what `buildEdges` assigns. The binder's
563
+ // array puts declaration forms before expression forms regardless of where they
564
+ // appear, so without this a file mixing `import` and `import()` of the same module
565
+ // gets different ordinals depending on which collector ran — and the identity would
566
+ // depend on whether the cache was warm. Sorting costs a comparison per literal and
567
+ // resolves nothing, so the early exit this generator exists for is untouched.
568
+ const literals = [...sourceFile.getImportStringLiterals()].sort((a, b) => a.getPos() - b.getPos());
569
+ const counters = new Map();
570
+ for (const literal of literals) {
571
+ const parent = literal.getParent();
572
+ if (parent === undefined)
573
+ continue;
574
+ const kind = kindOf(parent);
575
+ if (kind === undefined)
576
+ continue;
577
+ const edge = makeEdge(literal, parent, kind, verbatim);
578
+ yield { ...edge, ordinal: nextOrdinal(counters, edge) };
579
+ }
580
+ }
581
+ export function edgeTypeOnlyNoun(kind) {
582
+ switch (kind) {
583
+ case 'import':
584
+ case 'dynamic':
585
+ case 'require':
586
+ return 'import';
587
+ case 'reexport':
588
+ return 're-export';
589
+ case 'type-expression':
590
+ return 'reference';
591
+ }
592
+ }
593
+ //# sourceMappingURL=module-edges.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"module-edges.js","sourceRoot":"","sources":["../../src/core/module-edges.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,42 @@
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
+ /**
22
+ * A function found as a value in an object literal, with the property-key path
23
+ * that reached it.
24
+ */
25
+ export interface ObjectLiteralFunction {
26
+ /** The function node: `ArrowFunction | FunctionExpression | MethodDeclaration`. */
27
+ readonly node: Node;
28
+ /** Property-key path from the root object literal, e.g. `['routes', '/x', 'GET']`. */
29
+ readonly keyPath: readonly string[];
30
+ }
31
+ /**
32
+ * Walk an object literal and collect every function-valued property — arrow,
33
+ * function expression, or method shorthand — recursing into nested object
34
+ * literals up to `maxDepth`. Call-agnostic (F3): the single traversal shared by
35
+ * `functions()` object-literal collection (proposal 016) and the
36
+ * callback-extractor (`within()` / call path), so the two cannot drift.
37
+ *
38
+ * Only descends into nested object-literal property values, never into function
39
+ * bodies. Returns `[]` when `node` is not an object literal.
40
+ */
41
+ export declare function collectObjectLiteralFunctions(node: Node, maxDepth?: number): ObjectLiteralFunction[];
42
+ //# sourceMappingURL=object-literal-functions.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"object-literal-functions.d.ts","sourceRoot":"","sources":["../../src/core/object-literal-functions.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,EAAE,IAAI,EAAE,MAAM,UAAU,CAAA;AAG/B;;;GAGG;AAEH,MAAM,WAAW,qBAAqB;IACpC,mFAAmF;IACnF,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAA;IACnB,sFAAsF;IACtF,QAAQ,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,CAAA;CACpC;AAKD;;;;;;;;;GASG;AACH,wBAAgB,6BAA6B,CAC3C,IAAI,EAAE,IAAI,EACV,QAAQ,GAAE,MAAiC,GAC1C,qBAAqB,EAAE,CAIzB"}