@nielspeter/eess-ts 0.2.1 → 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.
- package/README.md +61 -35
- package/dist/builders/call-rule-builder.d.ts +66 -26
- package/dist/builders/call-rule-builder.d.ts.map +1 -1
- package/dist/builders/call-rule-builder.js +73 -31
- package/dist/builders/call-rule-builder.js.map +1 -1
- package/dist/builders/class-rule-builder.d.ts +125 -26
- package/dist/builders/class-rule-builder.d.ts.map +1 -1
- package/dist/builders/class-rule-builder.js +134 -30
- package/dist/builders/class-rule-builder.js.map +1 -1
- package/dist/builders/correspondence-builder.d.ts +287 -0
- package/dist/builders/correspondence-builder.d.ts.map +1 -0
- package/dist/builders/correspondence-builder.js +393 -0
- package/dist/builders/correspondence-builder.js.map +1 -0
- package/dist/builders/correspondence-findings.d.ts +104 -0
- package/dist/builders/correspondence-findings.d.ts.map +1 -0
- package/dist/builders/correspondence-findings.js +301 -0
- package/dist/builders/correspondence-findings.js.map +1 -0
- package/dist/builders/cross-layer-builder.d.ts +99 -16
- package/dist/builders/cross-layer-builder.d.ts.map +1 -1
- package/dist/builders/cross-layer-builder.js +181 -35
- package/dist/builders/cross-layer-builder.js.map +1 -1
- package/dist/builders/function-rule-builder.d.ts +144 -25
- package/dist/builders/function-rule-builder.d.ts.map +1 -1
- package/dist/builders/function-rule-builder.js +173 -26
- package/dist/builders/function-rule-builder.js.map +1 -1
- package/dist/builders/jsx-rule-builder.d.ts +70 -14
- package/dist/builders/jsx-rule-builder.d.ts.map +1 -1
- package/dist/builders/jsx-rule-builder.js +73 -14
- package/dist/builders/jsx-rule-builder.js.map +1 -1
- package/dist/builders/module-rule-builder.d.ts +2 -2
- package/dist/builders/module-rule-builder.d.ts.map +1 -1
- package/dist/builders/module-rule-builder.js +12 -3
- package/dist/builders/module-rule-builder.js.map +1 -1
- package/dist/builders/scoped-function-rule-builder.d.ts +11 -0
- package/dist/builders/scoped-function-rule-builder.d.ts.map +1 -1
- package/dist/builders/scoped-function-rule-builder.js +12 -0
- package/dist/builders/scoped-function-rule-builder.js.map +1 -1
- package/dist/builders/slice-discovery-message.d.ts +36 -0
- package/dist/builders/slice-discovery-message.d.ts.map +1 -0
- package/dist/builders/slice-discovery-message.js +181 -0
- package/dist/builders/slice-discovery-message.js.map +1 -0
- package/dist/builders/slice-rule-builder.d.ts +151 -12
- package/dist/builders/slice-rule-builder.d.ts.map +1 -1
- package/dist/builders/slice-rule-builder.js +242 -35
- package/dist/builders/slice-rule-builder.js.map +1 -1
- package/dist/builders/type-rule-builder.d.ts +95 -24
- package/dist/builders/type-rule-builder.d.ts.map +1 -1
- package/dist/builders/type-rule-builder.js +105 -29
- package/dist/builders/type-rule-builder.js.map +1 -1
- package/dist/{helpers → builders}/within.d.ts +2 -2
- package/dist/builders/within.d.ts.map +1 -0
- package/dist/{helpers → builders}/within.js +1 -1
- package/dist/builders/within.js.map +1 -0
- package/dist/cli/commands/baseline.d.ts +3 -2
- package/dist/cli/commands/baseline.d.ts.map +1 -1
- package/dist/cli/commands/baseline.js +68 -6
- package/dist/cli/commands/baseline.js.map +1 -1
- package/dist/cli/commands/check.d.ts +7 -2
- package/dist/cli/commands/check.d.ts.map +1 -1
- package/dist/cli/commands/check.js +241 -45
- package/dist/cli/commands/check.js.map +1 -1
- package/dist/cli/commands/doctor.d.ts +29 -0
- package/dist/cli/commands/doctor.d.ts.map +1 -0
- package/dist/cli/commands/doctor.js +224 -0
- package/dist/cli/commands/doctor.js.map +1 -0
- package/dist/cli/commands/explain.d.ts +2 -1
- package/dist/cli/commands/explain.d.ts.map +1 -1
- package/dist/cli/commands/explain.js +19 -10
- package/dist/cli/commands/explain.js.map +1 -1
- package/dist/cli/commands/init.d.ts +9 -3
- package/dist/cli/commands/init.d.ts.map +1 -1
- package/dist/cli/commands/init.js +162 -137
- package/dist/cli/commands/init.js.map +1 -1
- package/dist/cli/import-rule-module.d.ts +29 -0
- package/dist/cli/import-rule-module.d.ts.map +1 -0
- package/dist/cli/import-rule-module.js +60 -0
- package/dist/cli/import-rule-module.js.map +1 -0
- package/dist/cli/index.d.ts +2 -2
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +98 -33
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/load-rules.d.ts +6 -11
- package/dist/cli/load-rules.d.ts.map +1 -1
- package/dist/cli/load-rules.js +21 -29
- package/dist/cli/load-rules.js.map +1 -1
- package/dist/cli/resolve-config.d.ts.map +1 -1
- package/dist/cli/resolve-config.js +24 -24
- package/dist/cli/resolve-config.js.map +1 -1
- package/dist/cli/rule-file-findings.d.ts +178 -0
- package/dist/cli/rule-file-findings.d.ts.map +1 -0
- package/dist/cli/rule-file-findings.js +293 -0
- package/dist/cli/rule-file-findings.js.map +1 -0
- package/dist/cli/watch.d.ts +20 -7
- package/dist/cli/watch.d.ts.map +1 -1
- package/dist/cli/watch.js +39 -14
- package/dist/cli/watch.js.map +1 -1
- package/dist/conditions/body-analysis-function.d.ts.map +1 -1
- package/dist/conditions/body-analysis-function.js +16 -7
- package/dist/conditions/body-analysis-function.js.map +1 -1
- package/dist/conditions/body-analysis-module.d.ts.map +1 -1
- package/dist/conditions/body-analysis-module.js +14 -9
- package/dist/conditions/body-analysis-module.js.map +1 -1
- package/dist/conditions/body-analysis.d.ts.map +1 -1
- package/dist/conditions/body-analysis.js +16 -7
- package/dist/conditions/body-analysis.js.map +1 -1
- package/dist/conditions/call.d.ts.map +1 -1
- package/dist/conditions/call.js +38 -17
- package/dist/conditions/call.js.map +1 -1
- package/dist/conditions/catch-analysis.d.ts +2 -1
- package/dist/conditions/catch-analysis.d.ts.map +1 -1
- package/dist/conditions/catch-analysis.js.map +1 -1
- package/dist/conditions/cross-layer.d.ts +2 -10
- package/dist/conditions/cross-layer.d.ts.map +1 -1
- package/dist/conditions/cross-layer.js +227 -23
- package/dist/conditions/cross-layer.js.map +1 -1
- package/dist/conditions/dependency.d.ts +35 -6
- package/dist/conditions/dependency.d.ts.map +1 -1
- package/dist/conditions/dependency.js +299 -45
- package/dist/conditions/dependency.js.map +1 -1
- package/dist/conditions/exports.d.ts.map +1 -1
- package/dist/conditions/exports.js +10 -0
- package/dist/conditions/exports.js.map +1 -1
- package/dist/conditions/function.d.ts.map +1 -1
- package/dist/conditions/function.js +19 -5
- package/dist/conditions/function.js.map +1 -1
- package/dist/conditions/helpers.d.ts +2 -1
- package/dist/conditions/helpers.d.ts.map +1 -1
- package/dist/conditions/helpers.js +4 -1
- package/dist/conditions/helpers.js.map +1 -1
- package/dist/conditions/jsx.d.ts.map +1 -1
- package/dist/conditions/jsx.js +7 -2
- package/dist/conditions/jsx.js.map +1 -1
- package/dist/conditions/match-identity.d.ts +43 -0
- package/dist/conditions/match-identity.d.ts.map +1 -0
- package/dist/conditions/match-identity.js +43 -0
- package/dist/conditions/match-identity.js.map +1 -0
- package/dist/conditions/members.d.ts.map +1 -1
- package/dist/conditions/members.js +17 -4
- package/dist/conditions/members.js.map +1 -1
- package/dist/conditions/reverse-dependency.d.ts +18 -5
- package/dist/conditions/reverse-dependency.d.ts.map +1 -1
- package/dist/conditions/reverse-dependency.js +109 -92
- package/dist/conditions/reverse-dependency.js.map +1 -1
- package/dist/conditions/slice.d.ts +86 -2
- package/dist/conditions/slice.d.ts.map +1 -1
- package/dist/conditions/slice.js +234 -53
- package/dist/conditions/slice.js.map +1 -1
- package/dist/conditions/structural.d.ts.map +1 -1
- package/dist/conditions/structural.js +16 -4
- package/dist/conditions/structural.js.map +1 -1
- package/dist/core/check-all.d.ts +19 -0
- package/dist/core/check-all.d.ts.map +1 -0
- package/dist/core/check-all.js +96 -0
- package/dist/core/check-all.js.map +1 -0
- package/dist/core/combinators.d.ts +48 -0
- package/dist/core/combinators.d.ts.map +1 -0
- package/dist/core/combinators.js +56 -0
- package/dist/core/combinators.js.map +1 -0
- package/dist/core/descendant-cache.d.ts +36 -0
- package/dist/core/descendant-cache.d.ts.map +1 -0
- package/dist/core/descendant-cache.js +119 -0
- package/dist/core/descendant-cache.js.map +1 -0
- package/dist/core/diagnose.d.ts +234 -0
- package/dist/core/diagnose.d.ts.map +1 -0
- package/dist/core/diagnose.js +382 -0
- package/dist/core/diagnose.js.map +1 -0
- package/dist/core/disk-set.d.ts +48 -0
- package/dist/core/disk-set.d.ts.map +1 -0
- package/dist/core/disk-set.js +218 -0
- package/dist/core/disk-set.js.map +1 -0
- package/dist/core/element-cache.d.ts +75 -0
- package/dist/core/element-cache.d.ts.map +1 -0
- package/dist/core/element-cache.js +32 -0
- package/dist/core/element-cache.js.map +1 -0
- package/dist/core/empty-project-advice.d.ts +75 -0
- package/dist/core/empty-project-advice.d.ts.map +1 -0
- package/dist/core/empty-project-advice.js +61 -0
- package/dist/core/empty-project-advice.js.map +1 -0
- package/dist/core/exclusion-comments.d.ts +54 -0
- package/dist/core/exclusion-comments.d.ts.map +1 -0
- package/dist/core/exclusion-comments.js +310 -0
- package/dist/core/exclusion-comments.js.map +1 -0
- package/dist/core/execute-rule.d.ts +150 -0
- package/dist/core/execute-rule.d.ts.map +1 -0
- package/dist/core/execute-rule.js +580 -0
- package/dist/core/execute-rule.js.map +1 -0
- package/dist/core/glob-diagnosis.d.ts +78 -0
- package/dist/core/glob-diagnosis.d.ts.map +1 -0
- package/dist/core/glob-diagnosis.js +134 -0
- package/dist/core/glob-diagnosis.js.map +1 -0
- package/dist/core/glob-evaluator.d.ts +48 -0
- package/dist/core/glob-evaluator.d.ts.map +1 -0
- package/dist/core/glob-evaluator.js +89 -0
- package/dist/core/glob-evaluator.js.map +1 -0
- package/dist/core/import-candidates.d.ts +60 -0
- package/dist/core/import-candidates.d.ts.map +1 -0
- package/dist/core/import-candidates.js +93 -0
- package/dist/core/import-candidates.js.map +1 -0
- package/dist/core/import-options.d.ts +55 -2
- package/dist/core/import-options.d.ts.map +1 -1
- package/dist/core/import-options.js +64 -0
- package/dist/core/import-options.js.map +1 -1
- package/dist/core/line-index.d.ts +3 -0
- package/dist/core/line-index.d.ts.map +1 -0
- package/dist/core/line-index.js +229 -0
- package/dist/core/line-index.js.map +1 -0
- package/dist/core/metric-violation.d.ts +86 -0
- package/dist/core/metric-violation.d.ts.map +1 -0
- package/dist/core/metric-violation.js +132 -0
- package/dist/core/metric-violation.js.map +1 -0
- package/dist/core/module-edges.d.ts +361 -0
- package/dist/core/module-edges.d.ts.map +1 -0
- package/dist/core/module-edges.js +592 -0
- package/dist/core/module-edges.js.map +1 -0
- package/dist/core/object-literal-functions.d.ts +42 -0
- package/dist/core/object-literal-functions.d.ts.map +1 -0
- package/dist/core/object-literal-functions.js +75 -0
- package/dist/core/object-literal-functions.js.map +1 -0
- package/dist/core/orphan-exclusions.d.ts +44 -0
- package/dist/core/orphan-exclusions.d.ts.map +1 -0
- package/dist/core/orphan-exclusions.js +214 -0
- package/dist/core/orphan-exclusions.js.map +1 -0
- package/dist/core/pair-condition.d.ts +32 -3
- package/dist/core/pair-condition.d.ts.map +1 -1
- package/dist/core/path-universe.d.ts +54 -0
- package/dist/core/path-universe.d.ts.map +1 -0
- package/dist/core/path-universe.js +65 -0
- package/dist/core/path-universe.js.map +1 -0
- package/dist/core/per-root-compiler-options.d.ts +20 -0
- package/dist/core/per-root-compiler-options.d.ts.map +1 -0
- package/dist/core/per-root-compiler-options.js +57 -0
- package/dist/core/per-root-compiler-options.js.map +1 -0
- package/dist/core/project-relative.d.ts +98 -0
- package/dist/core/project-relative.d.ts.map +1 -0
- package/dist/core/project-relative.js +185 -0
- package/dist/core/project-relative.js.map +1 -0
- package/dist/core/project.d.ts +7 -1
- package/dist/core/project.d.ts.map +1 -1
- package/dist/core/project.js +24 -0
- package/dist/core/project.js.map +1 -1
- package/dist/core/rule-builder.d.ts +282 -0
- package/dist/core/rule-builder.d.ts.map +1 -0
- package/dist/core/rule-builder.js +445 -0
- package/dist/core/rule-builder.js.map +1 -0
- package/dist/core/rule-declaration.d.ts +32 -0
- package/dist/core/rule-declaration.d.ts.map +1 -0
- package/dist/core/rule-declaration.js +126 -0
- package/dist/core/rule-declaration.js.map +1 -0
- package/dist/core/terminal-builder.d.ts +625 -0
- package/dist/core/terminal-builder.d.ts.map +1 -0
- package/dist/core/terminal-builder.js +787 -0
- package/dist/core/terminal-builder.js.map +1 -0
- package/dist/core/terminal-execution.d.ts +23 -0
- package/dist/core/terminal-execution.d.ts.map +1 -0
- package/dist/core/terminal-execution.js +71 -0
- package/dist/core/terminal-execution.js.map +1 -0
- package/dist/core/vacuity-diagnosis.d.ts +103 -0
- package/dist/core/vacuity-diagnosis.d.ts.map +1 -0
- package/dist/core/vacuity-diagnosis.js +415 -0
- package/dist/core/vacuity-diagnosis.js.map +1 -0
- package/dist/core/violation.d.ts +16 -11
- package/dist/core/violation.d.ts.map +1 -1
- package/dist/core/violation.js +33 -13
- package/dist/core/violation.js.map +1 -1
- package/dist/graphql/index.js +1 -1
- package/dist/graphql/index.js.map +1 -1
- package/dist/graphql/resolver-rule-builder.d.ts +98 -23
- package/dist/graphql/resolver-rule-builder.d.ts.map +1 -1
- package/dist/graphql/resolver-rule-builder.js +151 -21
- package/dist/graphql/resolver-rule-builder.js.map +1 -1
- package/dist/graphql/schema-loader.d.ts +21 -0
- package/dist/graphql/schema-loader.d.ts.map +1 -1
- package/dist/graphql/schema-loader.js +81 -12
- package/dist/graphql/schema-loader.js.map +1 -1
- package/dist/graphql/schema-rule-builder.d.ts +57 -20
- package/dist/graphql/schema-rule-builder.d.ts.map +1 -1
- package/dist/graphql/schema-rule-builder.js +101 -25
- package/dist/graphql/schema-rule-builder.js.map +1 -1
- package/dist/helpers/baseline-diagnostics.d.ts +45 -0
- package/dist/helpers/baseline-diagnostics.d.ts.map +1 -0
- package/dist/helpers/baseline-diagnostics.js +168 -0
- package/dist/helpers/baseline-diagnostics.js.map +1 -0
- package/dist/helpers/baseline-generator.d.ts +19 -0
- package/dist/helpers/baseline-generator.d.ts.map +1 -0
- package/dist/helpers/baseline-generator.js +18 -0
- package/dist/helpers/baseline-generator.js.map +1 -0
- package/dist/helpers/baseline.d.ts +336 -0
- package/dist/helpers/baseline.d.ts.map +1 -0
- package/dist/helpers/baseline.js +664 -0
- package/dist/helpers/baseline.js.map +1 -0
- package/dist/helpers/body-traversal.d.ts +27 -2
- package/dist/helpers/body-traversal.d.ts.map +1 -1
- package/dist/helpers/body-traversal.js +122 -16
- package/dist/helpers/body-traversal.js.map +1 -1
- package/dist/helpers/callback-extractor.d.ts.map +1 -1
- package/dist/helpers/callback-extractor.js +48 -47
- package/dist/helpers/callback-extractor.js.map +1 -1
- package/dist/helpers/complexity.d.ts +13 -5
- package/dist/helpers/complexity.d.ts.map +1 -1
- package/dist/helpers/complexity.js +15 -6
- package/dist/helpers/complexity.js.map +1 -1
- package/dist/helpers/diff-aware.d.ts +44 -0
- package/dist/helpers/diff-aware.d.ts.map +1 -0
- package/dist/helpers/diff-aware.js +84 -0
- package/dist/helpers/diff-aware.js.map +1 -0
- package/dist/helpers/matchers.d.ts +68 -7
- package/dist/helpers/matchers.d.ts.map +1 -1
- package/dist/helpers/matchers.js +114 -20
- package/dist/helpers/matchers.js.map +1 -1
- package/dist/helpers/slice-graph.d.ts +100 -8
- package/dist/helpers/slice-graph.d.ts.map +1 -1
- package/dist/helpers/slice-graph.js +126 -34
- package/dist/helpers/slice-graph.js.map +1 -1
- package/dist/helpers/tarjan.d.ts +0 -14
- package/dist/helpers/tarjan.d.ts.map +1 -1
- package/dist/helpers/tarjan.js +29 -16
- package/dist/helpers/tarjan.js.map +1 -1
- package/dist/index.d.ts +56 -17
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +57 -13
- package/dist/index.js.map +1 -1
- package/dist/models/arch-call.d.ts +3 -2
- package/dist/models/arch-call.d.ts.map +1 -1
- package/dist/models/arch-call.js.map +1 -1
- package/dist/models/arch-function.d.ts +28 -6
- package/dist/models/arch-function.d.ts.map +1 -1
- package/dist/models/arch-function.js +106 -3
- package/dist/models/arch-function.js.map +1 -1
- package/dist/models/arch-jsx-element.js +2 -2
- package/dist/models/arch-jsx-element.js.map +1 -1
- package/dist/models/slice.d.ts +33 -9
- package/dist/models/slice.d.ts.map +1 -1
- package/dist/models/slice.js +129 -19
- package/dist/models/slice.js.map +1 -1
- package/dist/predicates/call.d.ts.map +1 -1
- package/dist/predicates/call.js +5 -0
- package/dist/predicates/call.js.map +1 -1
- package/dist/predicates/identity.d.ts +21 -0
- package/dist/predicates/identity.d.ts.map +1 -1
- package/dist/predicates/identity.js +75 -3
- package/dist/predicates/identity.js.map +1 -1
- package/dist/predicates/index.d.ts +1 -1
- package/dist/predicates/index.d.ts.map +1 -1
- package/dist/predicates/index.js +1 -1
- package/dist/predicates/index.js.map +1 -1
- package/dist/predicates/metrics.d.ts +4 -2
- package/dist/predicates/metrics.d.ts.map +1 -1
- package/dist/predicates/metrics.js +4 -2
- package/dist/predicates/metrics.js.map +1 -1
- package/dist/predicates/module.d.ts +4 -12
- package/dist/predicates/module.d.ts.map +1 -1
- package/dist/predicates/module.js +57 -37
- package/dist/predicates/module.js.map +1 -1
- package/dist/presets/agent-guardrails.d.ts +22 -15
- package/dist/presets/agent-guardrails.d.ts.map +1 -1
- package/dist/presets/agent-guardrails.js +124 -19
- package/dist/presets/agent-guardrails.js.map +1 -1
- package/dist/presets/boundaries.d.ts +45 -2
- package/dist/presets/boundaries.d.ts.map +1 -1
- package/dist/presets/boundaries.js +132 -23
- package/dist/presets/boundaries.js.map +1 -1
- package/dist/presets/data-layer.d.ts +22 -2
- package/dist/presets/data-layer.d.ts.map +1 -1
- package/dist/presets/data-layer.js +58 -16
- package/dist/presets/data-layer.js.map +1 -1
- package/dist/presets/index.d.ts +7 -5
- package/dist/presets/index.d.ts.map +1 -1
- package/dist/presets/index.js +9 -3
- package/dist/presets/index.js.map +1 -1
- package/dist/presets/layered.d.ts +46 -2
- package/dist/presets/layered.d.ts.map +1 -1
- package/dist/presets/layered.js +66 -29
- package/dist/presets/layered.js.map +1 -1
- package/dist/presets/recommended.d.ts +80 -9
- package/dist/presets/recommended.d.ts.map +1 -1
- package/dist/presets/recommended.js +25 -23
- package/dist/presets/recommended.js.map +1 -1
- package/dist/presets/shared.d.ts +270 -2
- package/dist/presets/shared.d.ts.map +1 -1
- package/dist/presets/shared.js +338 -4
- package/dist/presets/shared.js.map +1 -1
- package/dist/rules/code-quality.d.ts.map +1 -1
- package/dist/rules/code-quality.js +15 -6
- package/dist/rules/code-quality.js.map +1 -1
- package/dist/rules/hygiene.d.ts +1 -1
- package/dist/rules/hygiene.js +1 -1
- package/dist/rules/metrics-function.d.ts +2 -1
- package/dist/rules/metrics-function.d.ts.map +1 -1
- package/dist/rules/metrics-function.js +33 -6
- package/dist/rules/metrics-function.js.map +1 -1
- package/dist/rules/metrics.d.ts +2 -1
- package/dist/rules/metrics.d.ts.map +1 -1
- package/dist/rules/metrics.js +39 -9
- package/dist/rules/metrics.js.map +1 -1
- package/dist/smells/duplicate-bodies.d.ts +58 -5
- package/dist/smells/duplicate-bodies.d.ts.map +1 -1
- package/dist/smells/duplicate-bodies.js +137 -56
- package/dist/smells/duplicate-bodies.js.map +1 -1
- package/dist/smells/fingerprint.d.ts +8 -1
- package/dist/smells/fingerprint.d.ts.map +1 -1
- package/dist/smells/fingerprint.js +21 -3
- package/dist/smells/fingerprint.js.map +1 -1
- package/dist/smells/inconsistent-siblings.d.ts +128 -7
- package/dist/smells/inconsistent-siblings.d.ts.map +1 -1
- package/dist/smells/inconsistent-siblings.js +288 -86
- package/dist/smells/inconsistent-siblings.js.map +1 -1
- package/dist/smells/sibling-files.d.ts +47 -0
- package/dist/smells/sibling-files.d.ts.map +1 -0
- package/dist/smells/sibling-files.js +104 -0
- package/dist/smells/sibling-files.js.map +1 -0
- package/dist/smells/similar-pairs.d.ts +27 -0
- package/dist/smells/similar-pairs.d.ts.map +1 -0
- package/dist/smells/similar-pairs.js +52 -0
- package/dist/smells/similar-pairs.js.map +1 -0
- package/dist/smells/smell-builder.d.ts +57 -12
- package/dist/smells/smell-builder.d.ts.map +1 -1
- package/dist/smells/smell-builder.js +111 -14
- package/dist/smells/smell-builder.js.map +1 -1
- package/dist/tsconfig/index.d.ts +19 -0
- package/dist/tsconfig/index.d.ts.map +1 -0
- package/dist/tsconfig/index.js +20 -0
- package/dist/tsconfig/index.js.map +1 -0
- package/dist/tsconfig/tsconfig-builder.d.ts +42 -9
- package/dist/tsconfig/tsconfig-builder.d.ts.map +1 -1
- package/dist/tsconfig/tsconfig-builder.js +64 -16
- package/dist/tsconfig/tsconfig-builder.js.map +1 -1
- package/package.json +3 -2
- package/dist/core/module-dependencies.d.ts +0 -28
- package/dist/core/module-dependencies.d.ts.map +0 -1
- package/dist/core/module-dependencies.js +0 -35
- package/dist/core/module-dependencies.js.map +0 -1
- package/dist/helpers/within.d.ts.map +0 -1
- package/dist/helpers/within.js.map +0 -1
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import type { Condition } from '@nielspeter/eess';
|
|
2
2
|
import type { Slice } from '../models/slice.js';
|
|
3
|
+
import type { ImportOptions } from '../core/import-options.js';
|
|
3
4
|
/**
|
|
4
5
|
* Assert that no circular dependencies exist between slices.
|
|
5
6
|
*
|
|
6
|
-
* Builds a directed dependency graph from
|
|
7
|
+
* Builds a directed dependency graph from imports and re-exports,
|
|
7
8
|
* then runs Tarjan's SCC algorithm to detect cycles.
|
|
8
9
|
* Each cycle produces a violation listing the cycle path.
|
|
9
10
|
*
|
|
@@ -13,10 +14,82 @@ import type { Slice } from '../models/slice.js';
|
|
|
13
14
|
* .should().beFreeOfCycles()
|
|
14
15
|
* .check()
|
|
15
16
|
*/
|
|
16
|
-
|
|
17
|
+
/**
|
|
18
|
+
* `canonicalizeCycle` lived here, and sorting replaced it — bug 0056.
|
|
19
|
+
*
|
|
20
|
+
* It rotated an SCC to start at its lexicographically smallest member, for a real reason:
|
|
21
|
+
* Tarjan emits membership in traversal order, traversal follows the file walk, and the same
|
|
22
|
+
* cycle therefore had two identities on two machines. That is the concern
|
|
23
|
+
* [ts-archunit bug 0010](https://github.com/nielspeter/ts-archunit/blob/main/bugs/fixed/0010-violation-identity-embeds-absolute-paths.md) introduced
|
|
24
|
+
* the `identity` field for — the original docstring cited it here, a little loosely, since
|
|
25
|
+
* 0010 itself is about absolute paths rather than about cycles.
|
|
26
|
+
*
|
|
27
|
+
* Rotation was necessary and **not sufficient**, and the reason is in its own docstring's
|
|
28
|
+
* final claim — *"Direction is NOT normalized, because `a -> b -> c -> a` and
|
|
29
|
+
* `a -> c -> b -> a` traverse different edges and are genuinely different cycles"*. That
|
|
30
|
+
* premise requires the array to be an edge-ordered PATH. It is not, for any component of
|
|
31
|
+
* three or more: measured, a real ring `a→b→c→d→a` came out as `a -> d -> c -> b -> a`,
|
|
32
|
+
* every arrow reversed. So the preserved "direction" was information about the traversal,
|
|
33
|
+
* not about the graph — and reordering two imports moved the element from `[a, c, b]` to
|
|
34
|
+
* `[a, b, c]`, reddening CI on a cosmetic edit.
|
|
35
|
+
*
|
|
36
|
+
* Sorting subsumes rotation for a set and adds the missing half. If a future change
|
|
37
|
+
* recovers a REAL path (bug 0055's fuller fix), direction becomes genuine information
|
|
38
|
+
* again — and then the right shape is a sorted member set for the identity with the path
|
|
39
|
+
* carried in the message, not a return to rotation.
|
|
40
|
+
*
|
|
41
|
+
* **`identity`/`element` moved off the member set entirely — plan 0104.** One violation
|
|
42
|
+
* per SCC (keyed by the sorted member set above) let `.excluding()` waive a whole tangled
|
|
43
|
+
* component with one pattern, so a brand-new edge between two already-waived members was
|
|
44
|
+
* silently absorbed — a second, doubly fail-open bug in the same family. Each internal
|
|
45
|
+
* edge of the component now gets its own violation, `identity`, and `element`
|
|
46
|
+
* (`cycle-edge::${from}->${to}`, `${from} -> ${to}`) — every such edge provably lies on
|
|
47
|
+
* some cycle, because the component's own connectivity supplies a return path. The sorted
|
|
48
|
+
* `members` set computed above still exists and is still load-bearing: it now serves the
|
|
49
|
+
* MESSAGE's "part of a cycle with: ..." context only, not identity or element.
|
|
50
|
+
*/
|
|
51
|
+
/**
|
|
52
|
+
* Every slice must be free of dependency cycles.
|
|
53
|
+
*
|
|
54
|
+
* **The graph counts eager static dependencies: `import` declarations AND
|
|
55
|
+
* re-exports.** Since v0.48.0 `export { x } from './b.js'` and `export * from
|
|
56
|
+
* './b.js'` are edges — they emit an import of the module, so it is evaluated — which
|
|
57
|
+
* means a **barrel cycle** (`a → barrel → a`) is detected. It was not before v0.48.0,
|
|
58
|
+
* and that was the commonest cycle shape there is.
|
|
59
|
+
*
|
|
60
|
+
* Not counted, each for a reason: **dynamic `import()`** (lazy, so it cannot deadlock
|
|
61
|
+
* initialization, and it is usually the deliberate *fix* for a cycle), **`require()`**
|
|
62
|
+
* (CJS; this is an ESM-only package), and **type positions** like
|
|
63
|
+
* `type X = import('./b.js').Y` (erased).
|
|
64
|
+
*
|
|
65
|
+
* Type-only imports and re-exports are dropped by default — see `ignoreTypeImports`
|
|
66
|
+
* below, and note the default differs from `notDependOn`/`respectLayerOrder` on
|
|
67
|
+
* purpose: a cycle asks whether the module is *evaluated*, those ask whether the code
|
|
68
|
+
* is *coupled*.
|
|
69
|
+
*
|
|
70
|
+
* **This docstring said the opposite until v0.49.1.** It described the re-export
|
|
71
|
+
* blindness as permanent, and it argued for its own importance on the ground that "this
|
|
72
|
+
* docstring is read when the rule fails, and a changelog is read once" — then v0.48.0
|
|
73
|
+
* updated the changelog and left this text standing, along with the same claim in two
|
|
74
|
+
* shipped preset `because` strings that are **printed inside every finding**. Found by
|
|
75
|
+
* review, not by the suite; nothing pins prose against behaviour.
|
|
76
|
+
*/
|
|
77
|
+
export declare function beFreeOfCycles(options?: ImportOptions): Condition<Slice>;
|
|
17
78
|
/**
|
|
18
79
|
* Assert that slices respect a layered dependency order.
|
|
19
80
|
*
|
|
81
|
+
* **Which edges count:** every kind `notImportFrom()` and `onlyImportFrom()` count — plain
|
|
82
|
+
* imports, re-exports, `import('…')` and `type X = import('…').Y` — because this is a
|
|
83
|
+
* **coupling** question and a lazy import of a forbidden slice is still a forbidden
|
|
84
|
+
* dependency. `require()` is not counted (ESM-only package, ADR-004). Contrast
|
|
85
|
+
* `beFreeOfCycles`, which counts only the eager kinds because a cycle is a deadlock in
|
|
86
|
+
* initialization order.
|
|
87
|
+
*
|
|
88
|
+
* Stated here rather than only in `docs/slices.md` because this docstring is what an IDE
|
|
89
|
+
* and an agent read. The same omission stood from v0.48.0 to v0.49.1 and nothing pinned
|
|
90
|
+
* prose against behaviour then either
|
|
91
|
+
* ([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)).
|
|
92
|
+
*
|
|
20
93
|
* Given layers ['presentation', 'application', 'persistence', 'domain'],
|
|
21
94
|
* layer N may depend on layers N+1, N+2, ... but NOT on layers N-1, N-2, ...
|
|
22
95
|
* That is, dependencies must flow downward (toward higher indices) only.
|
|
@@ -31,10 +104,20 @@ export declare function beFreeOfCycles(): Condition<Slice>;
|
|
|
31
104
|
* .should().respectLayerOrder('presentation', 'application', 'persistence', 'domain')
|
|
32
105
|
* .check()
|
|
33
106
|
*/
|
|
107
|
+
export declare function respectLayerOrder(layers: string[], options: ImportOptions): Condition<Slice>;
|
|
34
108
|
export declare function respectLayerOrder(...layers: string[]): Condition<Slice>;
|
|
35
109
|
/**
|
|
36
110
|
* Assert that no slice depends on any of the listed slices.
|
|
37
111
|
*
|
|
112
|
+
* **Which edges count:** every kind `notImportFrom()` and `onlyImportFrom()` count — plain
|
|
113
|
+
* imports, re-exports, `import('…')` and `type X = import('…').Y` — because this is a
|
|
114
|
+
* **coupling** question: a lazy import of a forbidden slice is still a forbidden dependency.
|
|
115
|
+
* `require()` is not counted (ESM-only, ADR-004). Contrast `beFreeOfCycles`, which counts
|
|
116
|
+
* only the eager kinds because a cycle is a deadlock in initialization order. Dynamic and
|
|
117
|
+
* type-expression edges were invisible here until
|
|
118
|
+
* [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);
|
|
119
|
+
* this note exists because that docstring said nothing either way.
|
|
120
|
+
*
|
|
38
121
|
* Use for explicit isolation rules, e.g., "no slice may depend on legacy".
|
|
39
122
|
*
|
|
40
123
|
* @param forbiddenSlices - Names of slices that must not be depended upon
|
|
@@ -45,5 +128,6 @@ export declare function respectLayerOrder(...layers: string[]): Condition<Slice>
|
|
|
45
128
|
* .should().notDependOn('legacy', 'deprecated')
|
|
46
129
|
* .check()
|
|
47
130
|
*/
|
|
131
|
+
export declare function notDependOn(forbiddenSlices: string[], options: ImportOptions): Condition<Slice>;
|
|
48
132
|
export declare function notDependOn(...forbiddenSlices: string[]): Condition<Slice>;
|
|
49
133
|
//# sourceMappingURL=slice.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"slice.d.ts","sourceRoot":"","sources":["../../src/conditions/slice.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAoB,MAAM,kBAAkB,CAAA;AAEnE,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAA;
|
|
1
|
+
{"version":3,"file":"slice.d.ts","sourceRoot":"","sources":["../../src/conditions/slice.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAoB,MAAM,kBAAkB,CAAA;AAEnE,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAA;AAC/C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAA;AAQ9D;;;;;;;;;;;;GAYG;AACH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AAEH;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAgB,cAAc,CAAC,OAAO,CAAC,EAAE,aAAa,GAAG,SAAS,CAAC,KAAK,CAAC,CAwIxE;AAoDD;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,EAAE,EAAE,OAAO,EAAE,aAAa,GAAG,SAAS,CAAC,KAAK,CAAC,CAAA;AAC7F,wBAAgB,iBAAiB,CAAC,GAAG,MAAM,EAAE,MAAM,EAAE,GAAG,SAAS,CAAC,KAAK,CAAC,CAAA;AAmDxE;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,WAAW,CAAC,eAAe,EAAE,MAAM,EAAE,EAAE,OAAO,EAAE,aAAa,GAAG,SAAS,CAAC,KAAK,CAAC,CAAA;AAChG,wBAAgB,WAAW,CAAC,GAAG,eAAe,EAAE,MAAM,EAAE,GAAG,SAAS,CAAC,KAAK,CAAC,CAAA"}
|
package/dist/conditions/slice.js
CHANGED
|
@@ -1,9 +1,12 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { splitGlobArgs } from '../core/import-options.js';
|
|
2
|
+
import { edgeDiscriminator, edgeVerb } from '../core/module-edges.js';
|
|
3
|
+
import { sliceGraph, buildFileToSliceMap } from '../helpers/slice-graph.js';
|
|
2
4
|
import { tarjanSCC } from '../helpers/tarjan.js';
|
|
5
|
+
import { byCodepoint } from '@nielspeter/eess';
|
|
3
6
|
/**
|
|
4
7
|
* Assert that no circular dependencies exist between slices.
|
|
5
8
|
*
|
|
6
|
-
* Builds a directed dependency graph from
|
|
9
|
+
* Builds a directed dependency graph from imports and re-exports,
|
|
7
10
|
* then runs Tarjan's SCC algorithm to detect cycles.
|
|
8
11
|
* Each cycle produces a violation listing the cycle path.
|
|
9
12
|
*
|
|
@@ -13,12 +16,89 @@ import { tarjanSCC } from '../helpers/tarjan.js';
|
|
|
13
16
|
* .should().beFreeOfCycles()
|
|
14
17
|
* .check()
|
|
15
18
|
*/
|
|
16
|
-
|
|
19
|
+
/**
|
|
20
|
+
* `canonicalizeCycle` lived here, and sorting replaced it — bug 0056.
|
|
21
|
+
*
|
|
22
|
+
* It rotated an SCC to start at its lexicographically smallest member, for a real reason:
|
|
23
|
+
* Tarjan emits membership in traversal order, traversal follows the file walk, and the same
|
|
24
|
+
* cycle therefore had two identities on two machines. That is the concern
|
|
25
|
+
* [ts-archunit bug 0010](https://github.com/nielspeter/ts-archunit/blob/main/bugs/fixed/0010-violation-identity-embeds-absolute-paths.md) introduced
|
|
26
|
+
* the `identity` field for — the original docstring cited it here, a little loosely, since
|
|
27
|
+
* 0010 itself is about absolute paths rather than about cycles.
|
|
28
|
+
*
|
|
29
|
+
* Rotation was necessary and **not sufficient**, and the reason is in its own docstring's
|
|
30
|
+
* final claim — *"Direction is NOT normalized, because `a -> b -> c -> a` and
|
|
31
|
+
* `a -> c -> b -> a` traverse different edges and are genuinely different cycles"*. That
|
|
32
|
+
* premise requires the array to be an edge-ordered PATH. It is not, for any component of
|
|
33
|
+
* three or more: measured, a real ring `a→b→c→d→a` came out as `a -> d -> c -> b -> a`,
|
|
34
|
+
* every arrow reversed. So the preserved "direction" was information about the traversal,
|
|
35
|
+
* not about the graph — and reordering two imports moved the element from `[a, c, b]` to
|
|
36
|
+
* `[a, b, c]`, reddening CI on a cosmetic edit.
|
|
37
|
+
*
|
|
38
|
+
* Sorting subsumes rotation for a set and adds the missing half. If a future change
|
|
39
|
+
* recovers a REAL path (bug 0055's fuller fix), direction becomes genuine information
|
|
40
|
+
* again — and then the right shape is a sorted member set for the identity with the path
|
|
41
|
+
* carried in the message, not a return to rotation.
|
|
42
|
+
*
|
|
43
|
+
* **`identity`/`element` moved off the member set entirely — plan 0104.** One violation
|
|
44
|
+
* per SCC (keyed by the sorted member set above) let `.excluding()` waive a whole tangled
|
|
45
|
+
* component with one pattern, so a brand-new edge between two already-waived members was
|
|
46
|
+
* silently absorbed — a second, doubly fail-open bug in the same family. Each internal
|
|
47
|
+
* edge of the component now gets its own violation, `identity`, and `element`
|
|
48
|
+
* (`cycle-edge::${from}->${to}`, `${from} -> ${to}`) — every such edge provably lies on
|
|
49
|
+
* some cycle, because the component's own connectivity supplies a return path. The sorted
|
|
50
|
+
* `members` set computed above still exists and is still load-bearing: it now serves the
|
|
51
|
+
* MESSAGE's "part of a cycle with: ..." context only, not identity or element.
|
|
52
|
+
*/
|
|
53
|
+
/**
|
|
54
|
+
* Every slice must be free of dependency cycles.
|
|
55
|
+
*
|
|
56
|
+
* **The graph counts eager static dependencies: `import` declarations AND
|
|
57
|
+
* re-exports.** Since v0.48.0 `export { x } from './b.js'` and `export * from
|
|
58
|
+
* './b.js'` are edges — they emit an import of the module, so it is evaluated — which
|
|
59
|
+
* means a **barrel cycle** (`a → barrel → a`) is detected. It was not before v0.48.0,
|
|
60
|
+
* and that was the commonest cycle shape there is.
|
|
61
|
+
*
|
|
62
|
+
* Not counted, each for a reason: **dynamic `import()`** (lazy, so it cannot deadlock
|
|
63
|
+
* initialization, and it is usually the deliberate *fix* for a cycle), **`require()`**
|
|
64
|
+
* (CJS; this is an ESM-only package), and **type positions** like
|
|
65
|
+
* `type X = import('./b.js').Y` (erased).
|
|
66
|
+
*
|
|
67
|
+
* Type-only imports and re-exports are dropped by default — see `ignoreTypeImports`
|
|
68
|
+
* below, and note the default differs from `notDependOn`/`respectLayerOrder` on
|
|
69
|
+
* purpose: a cycle asks whether the module is *evaluated*, those ask whether the code
|
|
70
|
+
* is *coupled*.
|
|
71
|
+
*
|
|
72
|
+
* **This docstring said the opposite until v0.49.1.** It described the re-export
|
|
73
|
+
* blindness as permanent, and it argued for its own importance on the ground that "this
|
|
74
|
+
* docstring is read when the rule fails, and a changelog is read once" — then v0.48.0
|
|
75
|
+
* updated the changelog and left this text standing, along with the same claim in two
|
|
76
|
+
* shipped preset `because` strings that are **printed inside every finding**. Found by
|
|
77
|
+
* review, not by the suite; nothing pins prose against behaviour.
|
|
78
|
+
*/
|
|
79
|
+
export function beFreeOfCycles(options) {
|
|
80
|
+
// Resolved PER FIELD, once, and passed down as a complete object.
|
|
81
|
+
//
|
|
82
|
+
// This was a whole-object default — `options: ImportOptions = { ignoreTypeImports: true }`
|
|
83
|
+
// — while the read downstream was `options?.ignoreTypeImports === true`. So ANY object
|
|
84
|
+
// defeated it: `beFreeOfCycles({})` typechecks, because the field is optional, and
|
|
85
|
+
// silently gave the pre-0.47 graph. Measured: `()` reported no cycle and `({})`
|
|
86
|
+
// reported one, on a project whose only cross-slice edge was an `import type`.
|
|
87
|
+
//
|
|
88
|
+
// It gets worse with a second field, which is the point of a shared options bag:
|
|
89
|
+
// `beFreeOfCycles({ someOtherOption: true })` would revert a documented default while
|
|
90
|
+
// the caller's intent was unrelated. Bug 0057.
|
|
91
|
+
const resolved = { ignoreTypeImports: options?.ignoreTypeImports ?? true };
|
|
17
92
|
return {
|
|
18
93
|
description: 'be free of cycles',
|
|
19
94
|
evaluate(slices, context) {
|
|
20
95
|
const fileToSlice = buildFileToSliceMap(slices);
|
|
21
|
-
|
|
96
|
+
// 'module-request': a cycle is a deadlock in module-initialization order, so
|
|
97
|
+
// what matters is whether the target is EVALUATED, not whether the bindings are
|
|
98
|
+
// type-level. Under `verbatimModuleSyntax`, `import { type X } from 's'` emits
|
|
99
|
+
// `import {} from 's'` and can close a cycle (plan 0087).
|
|
100
|
+
const graph = sliceGraph(slices, fileToSlice, resolved, 'module-request');
|
|
101
|
+
const edges = graph.edges;
|
|
22
102
|
// Map slice names to indices for Tarjan's
|
|
23
103
|
const sliceNames = slices.map((s) => s.name);
|
|
24
104
|
const nameToIndex = new Map(sliceNames.map((name, i) => [name, i]));
|
|
@@ -39,49 +119,154 @@ export function beFreeOfCycles() {
|
|
|
39
119
|
const sccs = tarjanSCC(slices.length, adjacency);
|
|
40
120
|
const violations = [];
|
|
41
121
|
for (const scc of sccs) {
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
//
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
122
|
+
// **SORTED, not rotated** — bug 0056. `tarjanSCC` returns MEMBERSHIP in DFS-pop
|
|
123
|
+
// order, so the sequence is an artefact of traversal: reordering two imports moved
|
|
124
|
+
// the element from `[a, c, b]` to `[a, b, c]`, which reddened CI on a cosmetic edit
|
|
125
|
+
// and printed "it may be stale after a rename" about a rename that never happened.
|
|
126
|
+
// Unchanged by plan 0104: `members`/sorting now serves the MESSAGE only — identity
|
|
127
|
+
// and element moved to the edge, below — but the order-independence this sort buys
|
|
128
|
+
// still matters there too (`internalEdges` is itself sorted the same way).
|
|
129
|
+
const members = [...new Set(scc.map((i) => sliceNames[i] ?? ''))].sort(byCodepoint);
|
|
130
|
+
const inCycle = new Set(members);
|
|
131
|
+
// **Every internal edge, not just one** — plan 0104. Provably meaningful, not a
|
|
132
|
+
// heuristic: for a strongly connected component, any edge `u -> v` where both `u`
|
|
133
|
+
// and `v` are members lies on SOME cycle, because the component's own connectivity
|
|
134
|
+
// supplies a return path `v -> ... -> u`. So every edge this filter finds is a real,
|
|
135
|
+
// substantiated cycle-membership fact — bug 0055 already established there is no
|
|
136
|
+
// single, order-independent answer to "the" closing edge, so this reports the
|
|
137
|
+
// provable superset instead of guessing at one. SORTED for the same portability
|
|
138
|
+
// reason the old single-`realEdge` selection needed (bug 0010): `edges` is built by
|
|
139
|
+
// walking the file list, so an unsorted iteration order would make which edge is
|
|
140
|
+
// "first" — and therefore, before this plan, the only reported one — depend on
|
|
141
|
+
// filesystem order.
|
|
142
|
+
// INVARIANT (review: architect): every `scc` reaching this point has 2+
|
|
143
|
+
// members (`tarjanSCC` only returns components of size > 1) and `adjacency`
|
|
144
|
+
// is built from the same `edges` array this filter reads, so `internalEdges`
|
|
145
|
+
// is never empty here — a size-2+ strongly connected component always has at
|
|
146
|
+
// least one internal edge by construction. Not asserted at runtime: an empty
|
|
147
|
+
// result would silently emit zero violations for a real cycle, so if this
|
|
148
|
+
// invariant is ever wrong it fails open rather than throwing.
|
|
149
|
+
const internalEdges = edges
|
|
150
|
+
.filter((e) => inCycle.has(e.from) && inCycle.has(e.to))
|
|
151
|
+
.sort((a, b) => byCodepoint(a.from, b.from) || byCodepoint(a.to, b.to));
|
|
152
|
+
for (const edge of internalEdges) {
|
|
153
|
+
// Through the graph, so the question and the options cannot diverge from the
|
|
154
|
+
// ones it was built with. Passing 'type-bindings' here used to be writable, and
|
|
155
|
+
// it turned this finding into "dynamically imports ... at line 1" — pointing the
|
|
156
|
+
// reader at the construct that FIXES cycles. Called once per edge rather than
|
|
157
|
+
// once per SCC: each call walks `fromSlice.files`, which is cheap — the AST work
|
|
158
|
+
// underneath is cached per file by `edgesOf` (module-edges.ts) regardless of call
|
|
159
|
+
// count (Out of scope: performance, reasoned not benchmarked).
|
|
160
|
+
const details = graph.detailsFor(edge.from, edge.to);
|
|
161
|
+
// Same reason as the old single-edge lookup, one level down: `details` follows
|
|
162
|
+
// the slice's file order, and each edge computes its OWN site — never a hoisted
|
|
163
|
+
// one shared across edges in the same SCC, which would silently reintroduce a
|
|
164
|
+
// shared-location regression this plan's own test inventory guards against.
|
|
165
|
+
const site = [...details].sort((a, b) => byCodepoint(a.sourceFile.getFilePath(), b.sourceFile.getFilePath()) ||
|
|
166
|
+
a.importLine - b.importLine)[0];
|
|
167
|
+
violations.push({
|
|
168
|
+
rule: context.rule,
|
|
169
|
+
// The edge ITSELF, not the component — plan 0104. `.excluding('helpers -> builders')`
|
|
170
|
+
// now names exactly this fact and nothing else in the component. Deliberately
|
|
171
|
+
// NOT decorated with the member list: folding membership in here would move
|
|
172
|
+
// every edge's element whenever the component's shape changes, even for edges
|
|
173
|
+
// that did not themselves change — see plan 0104's "Why per-edge" for the case
|
|
174
|
+
// analysis this avoids.
|
|
175
|
+
element: `${edge.from} -> ${edge.to}`,
|
|
176
|
+
file: site ? site.sourceFile.getFilePath() : 'unknown',
|
|
177
|
+
line: site ? site.importLine : 0,
|
|
178
|
+
// A pure function of the two slice names — no path, no line, no message text.
|
|
179
|
+
// Distinct prefix from the old `cycle::` scheme (bug 0056) so an old-format
|
|
180
|
+
// baseline entry cannot accidentally collide with a new-format one — see
|
|
181
|
+
// `HASH_VERSION`'s bump in `src/helpers/baseline.ts`.
|
|
182
|
+
identity: `cycle-edge::${edge.from}->${edge.to}`,
|
|
183
|
+
// "Cycle detected" stays the leading words —
|
|
184
|
+
// tests/presets/cycle-claims-match-behaviour.test.ts filters on
|
|
185
|
+
// `message.startsWith('Cycle detected')` and must keep matching. The named
|
|
186
|
+
// edge is a real, substantiated fact for THIS finding (not an "e.g." example of
|
|
187
|
+
// the component, as the pre-plan-0104 message had it) — every edge pushed here
|
|
188
|
+
// provably closes some cycle, per the proof above.
|
|
189
|
+
message: site
|
|
190
|
+
? `Cycle detected: "${edge.from}" ${edgeVerb(site.edge.kind)} "${edge.to}" at ` +
|
|
191
|
+
`${site.sourceFile.getBaseName()}:${String(site.importLine)}, part of a cycle with: ` +
|
|
192
|
+
`${members.join(', ')}`
|
|
193
|
+
: // Unreachable given `graph`'s options/question binding — kept for the same
|
|
194
|
+
// defensive reason the pre-plan-0104 code kept its own `'unknown'`/`0`
|
|
195
|
+
// fallback.
|
|
196
|
+
`Cycle detected: "${edge.from}" depends on "${edge.to}", part of a cycle with: ` +
|
|
197
|
+
`${members.join(', ')} (location unknown)`,
|
|
198
|
+
because: context.because,
|
|
199
|
+
});
|
|
200
|
+
}
|
|
57
201
|
}
|
|
58
202
|
return violations;
|
|
59
203
|
},
|
|
60
204
|
};
|
|
61
205
|
}
|
|
62
206
|
/**
|
|
63
|
-
*
|
|
64
|
-
*
|
|
65
|
-
* Given layers ['presentation', 'application', 'persistence', 'domain'],
|
|
66
|
-
* layer N may depend on layers N+1, N+2, ... but NOT on layers N-1, N-2, ...
|
|
67
|
-
* That is, dependencies must flow downward (toward higher indices) only.
|
|
207
|
+
* A dependency site's identity, following the scheme the dependency conditions already use.
|
|
68
208
|
*
|
|
69
|
-
*
|
|
209
|
+
* `basename::kind::specifier::sorted-names`, prefixed with the slice pair — and
|
|
210
|
+
* **deliberately no line number**, which is the correction plan 0088's own sketch needed.
|
|
211
|
+
* `ArchViolation.identity` exists precisely to survive "a coordinate — `at line 12` moves
|
|
212
|
+
* when anything above it is edited", and `src/conditions/dependency.ts` omits the line for
|
|
213
|
+
* that reason. Copying the scheme rather than inventing a second one is the point: these
|
|
214
|
+
* two families report the same underlying edges.
|
|
70
215
|
*
|
|
71
|
-
*
|
|
72
|
-
*
|
|
73
|
-
*
|
|
74
|
-
*
|
|
75
|
-
*
|
|
76
|
-
* .should().respectLayerOrder('presentation', 'application', 'persistence', 'domain')
|
|
77
|
-
* .check()
|
|
216
|
+
* Why this distinguishes what a count could not: a barrel with thirty re-exports into one
|
|
217
|
+
* forbidden slice previously produced thirty findings sharing ONE hash, because `element`
|
|
218
|
+
* was the basename and the message named only the slice pair — so one baseline entry
|
|
219
|
+
* accepted all thirty. Each edge carries different `names`, so each site is now its own
|
|
220
|
+
* finding. (Measured before the fix: 3 sites, 3 lines, 1 hash.)
|
|
78
221
|
*/
|
|
79
|
-
|
|
222
|
+
function siteIdentity(from, to, site) {
|
|
223
|
+
return [
|
|
224
|
+
`${from}->${to}`,
|
|
225
|
+
// The FULL PATH, not the basename — and this is a deliberate divergence from the
|
|
226
|
+
// dependency family, whose scheme this otherwise copies.
|
|
227
|
+
//
|
|
228
|
+
// `getBaseName()` collides, measured: two sibling feature folders each with an
|
|
229
|
+
// `index.ts` re-exporting the same name from the same specifier produce one identity
|
|
230
|
+
// for two distinct violations — so one baseline entry accepts both. That is the very
|
|
231
|
+
// defect plan 0088 was written to fix, in a different shape, and it is the commonest
|
|
232
|
+
// layout there is. `src/conditions/dependency.ts` has the same collision
|
|
233
|
+
// ([ts-archunit bug 0063](https://github.com/nielspeter/ts-archunit/blob/main/bugs/fixed/0063-a-dependency-identity-collides-across-files-sharing-a-basename.md)),
|
|
234
|
+
// which is how it got here: the shape was right to copy, this component was not.
|
|
235
|
+
//
|
|
236
|
+
// An absolute path is safe here — `hashViolation` normalises the repository root out of
|
|
237
|
+
// identity text (`src/core/identity-root.ts`), which is what makes a baseline portable
|
|
238
|
+
// between a laptop and CI.
|
|
239
|
+
site.sourceFile.getFilePath(),
|
|
240
|
+
site.edge.kind,
|
|
241
|
+
site.edge.specifier,
|
|
242
|
+
// Names when the edge carries them, the source-order ordinal when it does not — see
|
|
243
|
+
// `edgeDiscriminator`.
|
|
244
|
+
//
|
|
245
|
+
// This comment used to say the gap was unreachable here, on the reasoning that before
|
|
246
|
+
// bug 0059 the family only saw `import` and `reexport`, "both of which carry names".
|
|
247
|
+
// That was false: it is the SPELLING that carries names, not the kind. Measured on
|
|
248
|
+
// `main` through `notDependOn`, two default imports of one module from one file gave
|
|
249
|
+
// two findings and ONE identity, as did two bare side-effect imports. The collision
|
|
250
|
+
// was live in this family, not merely reachable — which is why the fix is in
|
|
251
|
+
// `edgeDiscriminator` where both families read it, rather than in either caller.
|
|
252
|
+
edgeDiscriminator(site.edge),
|
|
253
|
+
].join('::');
|
|
254
|
+
}
|
|
255
|
+
export function respectLayerOrder(...args) {
|
|
256
|
+
const { globs: layers, options } = splitGlobArgs(args);
|
|
257
|
+
// `?? false` explicitly, not "undefined is falsy". Layering is a COUPLING question, so
|
|
258
|
+
// type edges count by default — the opposite of `beFreeOfCycles`, and stated so a
|
|
259
|
+
// future default change is a one-line edit rather than an audit (bug 0057).
|
|
260
|
+
const resolved = { ignoreTypeImports: options?.ignoreTypeImports ?? false };
|
|
80
261
|
return {
|
|
81
262
|
description: `respect layer order [${layers.join(' -> ')}]`,
|
|
82
263
|
evaluate(slices, context) {
|
|
83
264
|
const fileToSlice = buildFileToSliceMap(slices);
|
|
84
|
-
|
|
265
|
+
// 'type-bindings': layering and isolation are about COUPLING, so
|
|
266
|
+
// `ignoreTypeImports` here means what it means on `dependOn`/`notImportFrom` —
|
|
267
|
+
// ignore type-level references. Deliberately NOT the cycle question (plan 0087).
|
|
268
|
+
const graph = sliceGraph(slices, fileToSlice, resolved, 'type-bindings');
|
|
269
|
+
const edges = graph.edges;
|
|
85
270
|
// Map layer names to their position (lower index = higher layer)
|
|
86
271
|
const layerIndex = new Map(layers.map((name, i) => [name, i]));
|
|
87
272
|
const violations = [];
|
|
@@ -93,14 +278,15 @@ export function respectLayerOrder(...layers) {
|
|
|
93
278
|
continue;
|
|
94
279
|
// Violation: depending on a higher layer (lower index)
|
|
95
280
|
if (toIdx < fromIdx) {
|
|
96
|
-
const details =
|
|
281
|
+
const details = graph.detailsFor(edge.from, edge.to);
|
|
97
282
|
for (const detail of details) {
|
|
98
283
|
violations.push({
|
|
99
284
|
rule: context.rule,
|
|
100
285
|
element: detail.sourceFile.getBaseName(),
|
|
101
286
|
file: detail.sourceFile.getFilePath(),
|
|
102
287
|
line: detail.importLine,
|
|
103
|
-
|
|
288
|
+
identity: siteIdentity(edge.from, edge.to, detail),
|
|
289
|
+
message: `Layer "${edge.from}" ${edgeVerb(detail.edge.kind)} higher layer "${edge.to}" (allowed: ${layers.slice(fromIdx + 1).join(', ') || 'none'})`,
|
|
104
290
|
because: context.because,
|
|
105
291
|
});
|
|
106
292
|
}
|
|
@@ -110,37 +296,32 @@ export function respectLayerOrder(...layers) {
|
|
|
110
296
|
},
|
|
111
297
|
};
|
|
112
298
|
}
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
*
|
|
118
|
-
* @param forbiddenSlices - Names of slices that must not be depended upon
|
|
119
|
-
*
|
|
120
|
-
* @example
|
|
121
|
-
* slices(project)
|
|
122
|
-
* .matching('src/features/*\/')
|
|
123
|
-
* .should().notDependOn('legacy', 'deprecated')
|
|
124
|
-
* .check()
|
|
125
|
-
*/
|
|
126
|
-
export function notDependOn(...forbiddenSlices) {
|
|
299
|
+
export function notDependOn(...args) {
|
|
300
|
+
const { globs: forbiddenSlices, options } = splitGlobArgs(args);
|
|
301
|
+
// `?? false` — see `respectLayerOrder` above. Isolation is a coupling question.
|
|
302
|
+
const resolved = { ignoreTypeImports: options?.ignoreTypeImports ?? false };
|
|
127
303
|
const forbiddenSet = new Set(forbiddenSlices);
|
|
128
304
|
return {
|
|
129
305
|
description: `not depend on [${forbiddenSlices.join(', ')}]`,
|
|
130
306
|
evaluate(slices, context) {
|
|
131
307
|
const fileToSlice = buildFileToSliceMap(slices);
|
|
132
|
-
|
|
308
|
+
// 'type-bindings': layering and isolation are about COUPLING, so
|
|
309
|
+
// `ignoreTypeImports` here means what it means on `dependOn`/`notImportFrom` —
|
|
310
|
+
// ignore type-level references. Deliberately NOT the cycle question (plan 0087).
|
|
311
|
+
const graph = sliceGraph(slices, fileToSlice, resolved, 'type-bindings');
|
|
312
|
+
const edges = graph.edges;
|
|
133
313
|
const violations = [];
|
|
134
314
|
for (const edge of edges) {
|
|
135
315
|
if (forbiddenSet.has(edge.to)) {
|
|
136
|
-
const details =
|
|
316
|
+
const details = graph.detailsFor(edge.from, edge.to);
|
|
137
317
|
for (const detail of details) {
|
|
138
318
|
violations.push({
|
|
139
319
|
rule: context.rule,
|
|
140
320
|
element: detail.sourceFile.getBaseName(),
|
|
141
321
|
file: detail.sourceFile.getFilePath(),
|
|
142
322
|
line: detail.importLine,
|
|
143
|
-
|
|
323
|
+
identity: siteIdentity(edge.from, edge.to, detail),
|
|
324
|
+
message: `Slice "${edge.from}" ${edgeVerb(detail.edge.kind)} forbidden slice "${edge.to}"`,
|
|
144
325
|
because: context.because,
|
|
145
326
|
});
|
|
146
327
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"slice.js","sourceRoot":"","sources":["../../src/conditions/slice.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"slice.js","sourceRoot":"","sources":["../../src/conditions/slice.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"structural.d.ts","sourceRoot":"","sources":["../../src/conditions/structural.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,UAAU,CAAA;AAE/B,OAAO,KAAK,EAAE,SAAS,EAAoB,MAAM,kBAAkB,CAAA;
|
|
1
|
+
{"version":3,"file":"structural.d.ts","sourceRoot":"","sources":["../../src/conditions/structural.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,UAAU,CAAA;AAE/B,OAAO,KAAK,EAAE,SAAS,EAAoB,MAAM,kBAAkB,CAAA;AAOnE;;;;;;;;GAQG;AACH,wBAAgB,YAAY,CAAC,CAAC,SAAS,IAAI,EAAE,IAAI,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC,CAAC,CAcvE;AAED;;;;;;;;;GASG;AACH,wBAAgB,cAAc,CAAC,CAAC,SAAS,IAAI,EAAE,IAAI,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC,CAAC,CAgBzE;AAED;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,CAAC,SAAS,IAAI,EAAE,KAAK,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC,CAAC,CAM5E;AAED;;;;;;;;;GASG;AACH,wBAAgB,UAAU,CAAC,CAAC,SAAS,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,CAyBzD;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,QAAQ,CAAC,CAAC,SAAS,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,CAavD"}
|
|
@@ -2,6 +2,8 @@ import { Node } from 'ts-morph';
|
|
|
2
2
|
import picomatch from 'picomatch';
|
|
3
3
|
import { createViolation, getElementFile, getElementName } from '../core/violation.js';
|
|
4
4
|
import { elementCondition } from './helpers.js';
|
|
5
|
+
import { globNode } from '@nielspeter/eess';
|
|
6
|
+
import { marksAssertsCardinality } from '@nielspeter/eess';
|
|
5
7
|
/**
|
|
6
8
|
* Elements must reside in a file matching the glob pattern.
|
|
7
9
|
*
|
|
@@ -13,7 +15,13 @@ import { elementCondition } from './helpers.js';
|
|
|
13
15
|
*/
|
|
14
16
|
export function resideInFile(glob) {
|
|
15
17
|
const isMatch = picomatch(glob);
|
|
16
|
-
return elementCondition(`reside in file matching '${glob}'`, (element) => isMatch(getElementFile(element)), (element) => `${getElementName(element)} resides in '${getElementFile(element)}' which does not match '${glob}'
|
|
18
|
+
return elementCondition(`reside in file matching '${glob}'`, (element) => isMatch(getElementFile(element)), (element) => `${getElementName(element)} resides in '${getElementFile(element)}' which does not match '${glob}'`,
|
|
19
|
+
// The generic element twin of `function.ts`'s condition and of the
|
|
20
|
+
// `identity.ts:78` predicate — same absolute path, so the same kind. Plan
|
|
21
|
+
// 0073's table listed only the `function.ts` pair; these two are exported from
|
|
22
|
+
// `index.ts:86` and used by the class, module and type builders, so they were
|
|
23
|
+
// the more reachable half of the hole.
|
|
24
|
+
globNode({ glob, kind: 'file-path' }));
|
|
17
25
|
}
|
|
18
26
|
/**
|
|
19
27
|
* Elements must reside in a folder matching the glob pattern.
|
|
@@ -35,7 +43,7 @@ export function resideInFolder(glob) {
|
|
|
35
43
|
const filePath = getElementFile(element);
|
|
36
44
|
const folder = filePath.substring(0, filePath.lastIndexOf('/'));
|
|
37
45
|
return `${getElementName(element)} resides in folder '${folder}' which does not match '${glob}'`;
|
|
38
|
-
});
|
|
46
|
+
}, globNode({ glob, kind: 'parent-dir' }));
|
|
39
47
|
}
|
|
40
48
|
/**
|
|
41
49
|
* Elements must have a name matching the regex pattern.
|
|
@@ -92,11 +100,15 @@ export function beExported() {
|
|
|
92
100
|
* .because('use shared parseOrder() utility instead')
|
|
93
101
|
*/
|
|
94
102
|
export function notExist() {
|
|
95
|
-
|
|
103
|
+
// Satisfied by an EMPTY selection — registered rather than tagged, because a
|
|
104
|
+
// symbol keyed on this object is readable off it and forgeable (bug 0050).
|
|
105
|
+
return marksAssertsCardinality({
|
|
96
106
|
description: 'not exist',
|
|
107
|
+
// Zero subjects is this condition's PASSING state, so an empty selection
|
|
108
|
+
// and an unsatisfiable selector glob are both correct here (plan 0074).
|
|
97
109
|
evaluate(elements, context) {
|
|
98
110
|
return elements.map((element) => createViolation(element, `${getElementName(element)} should not exist`, context));
|
|
99
111
|
},
|
|
100
|
-
};
|
|
112
|
+
});
|
|
101
113
|
}
|
|
102
114
|
//# sourceMappingURL=structural.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"structural.js","sourceRoot":"","sources":["../../src/conditions/structural.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,UAAU,CAAA;AAC/B,OAAO,SAAS,MAAM,WAAW,CAAA;AAGjC,OAAO,EAAE,eAAe,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAA;AACtF,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAA;
|
|
1
|
+
{"version":3,"file":"structural.js","sourceRoot":"","sources":["../../src/conditions/structural.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { RuleBuilderLike } from '@nielspeter/eess';
|
|
2
|
+
import type { CheckOptions } from '@nielspeter/eess';
|
|
3
|
+
/**
|
|
4
|
+
* Run an array of rules (e.g. a spread preset) and throw one aggregated
|
|
5
|
+
* `ArchRuleError` if any **error-severity** violation is found. Warn-severity
|
|
6
|
+
* violations are reported but never throw — the same severity contract as the
|
|
7
|
+
* CLI `check`. This is the test-file terminal for the returning form:
|
|
8
|
+
*
|
|
9
|
+
* ```ts
|
|
10
|
+
* checkAll(layeredArchitecture(p, opts))
|
|
11
|
+
* checkAll([...recommended(p), ...layeredArchitecture(p, opts)])
|
|
12
|
+
* ```
|
|
13
|
+
*
|
|
14
|
+
* Each builder's `.violations()` already carries its stamped severity
|
|
15
|
+
* (via `.asSeverity()`), so aggregation and severity are preserved across the
|
|
16
|
+
* whole array — one readable error listing every error-severity violation.
|
|
17
|
+
*/
|
|
18
|
+
export declare function checkAll(rules: RuleBuilderLike[], options?: CheckOptions): void;
|
|
19
|
+
//# sourceMappingURL=check-all.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"check-all.d.ts","sourceRoot":"","sources":["../../src/core/check-all.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAiB,eAAe,EAAE,MAAM,kBAAkB,CAAA;AACtE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAA;AASpD;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,QAAQ,CAAC,KAAK,EAAE,eAAe,EAAE,EAAE,OAAO,CAAC,EAAE,YAAY,GAAG,IAAI,CAmF/E"}
|