@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,75 +1,271 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { withBaseline } from '
|
|
3
|
-
import { diffAware } from '
|
|
4
|
-
import {
|
|
1
|
+
import { applyFixes, detectFormat } from '@nielspeter/eess';
|
|
2
|
+
import { withBaseline } from '../../helpers/baseline.js';
|
|
3
|
+
import { diffAware } from '../../helpers/diff-aware.js';
|
|
4
|
+
import { isArchRuleError } from '@nielspeter/eess';
|
|
5
|
+
import { withCallerAggregating, violationsWritten, writeReport } from '../../core/execute-rule.js';
|
|
6
|
+
import { suppressionNotice } from '@nielspeter/eess';
|
|
7
|
+
import { edgeCoverageNotice, resetEdgeCoverage, untestedRules } from '@nielspeter/eess';
|
|
8
|
+
import { commentSuppressionNotice, resetCommentSuppression } from '@nielspeter/eess';
|
|
9
|
+
import { writeStderr } from '@nielspeter/eess';
|
|
5
10
|
import { loadRuleFiles } from '../load-rules.js';
|
|
11
|
+
import { dedupeConfigFindings } from '@nielspeter/eess';
|
|
12
|
+
import { attributeToRuleFile, baselineNotApplied, failureOrViolations, ruleFileContributedNoRules, ruleFileTruncated, } from '../rule-file-findings.js';
|
|
6
13
|
/**
|
|
7
14
|
* Run architecture rules from the specified rule files.
|
|
8
15
|
*
|
|
9
|
-
*
|
|
16
|
+
* Unified pipeline (plan 0060): collect `.violations()` across every builder
|
|
17
|
+
* (each stamped with its severity), apply baseline/diff, report ONCE, and set
|
|
18
|
+
* the exit code from the error-severity count. Warns are reported but do not
|
|
19
|
+
* fail. A rule file that throws `ArchRuleError` on import (a bare self-executing
|
|
20
|
+
* preset call) is handled by a best-effort catch — error-severity only.
|
|
10
21
|
*/
|
|
11
22
|
export async function runCheck(args) {
|
|
23
|
+
// Per run: the tally is module state (the `diff-disclosure` pattern), and a
|
|
24
|
+
// second `runCheck` in one process — the CLI's watch loop, or a test — must
|
|
25
|
+
// not inherit the first run's rules.
|
|
26
|
+
resetEdgeCoverage();
|
|
27
|
+
resetCommentSuppression();
|
|
12
28
|
const started = Date.now();
|
|
13
29
|
const format = args.format === 'auto' ? detectFormat() : args.format;
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
options.diff = diffAware(args.base);
|
|
20
|
-
}
|
|
21
|
-
const builders = await loadRuleFiles(args.ruleFiles, { fresh: args.fresh });
|
|
30
|
+
// `--fix` short-circuits the reporting pipeline: it renders what it changed
|
|
31
|
+
// (or would change) instead of the findings, and its exit code is the count
|
|
32
|
+
// of violations that have NO automatic fix — the real remaining failures.
|
|
33
|
+
// eess's own capability (plan 0066); upstream has no equivalent and plan
|
|
34
|
+
// 0165's engine copy dropped it. Restored in Phase 3.
|
|
22
35
|
if (args.fix === true) {
|
|
23
|
-
|
|
36
|
+
const builders = await loadRuleFiles(args.ruleFiles, { fresh: args.fresh });
|
|
37
|
+
return runFix(builders, { format }, args.apply === true);
|
|
24
38
|
}
|
|
25
|
-
|
|
26
|
-
|
|
39
|
+
// This command reports once, at the end, across every rule file. So a
|
|
40
|
+
// self-executing rule file's own terminals must not also write the findings that
|
|
41
|
+
// travel on their thrown error — see `withCallerAggregating`.
|
|
42
|
+
//
|
|
43
|
+
// A SCOPED extent, not a latch. It used to be a bare
|
|
44
|
+
// a bare flag-set that nothing ever reset, which was harmless
|
|
45
|
+
// while `executeCheck` was the only reader and stopped being harmless the moment
|
|
46
|
+
// presets and `checkAll()` read it too: a preset called directly after a
|
|
47
|
+
// `runCheck` in the same process went silent for the rest of that process.
|
|
48
|
+
return withCallerAggregating(async () => runCheckInner(args, format, started));
|
|
49
|
+
}
|
|
50
|
+
async function runCheckInner(args, format, started) {
|
|
51
|
+
const baseline = args.baseline !== undefined ? withBaseline(args.baseline) : undefined;
|
|
52
|
+
const diff = args.changed ? diffAware(args.base) : undefined;
|
|
53
|
+
let collected = [];
|
|
54
|
+
const total = args.ruleFiles.length;
|
|
55
|
+
// The denominator for the summary line below. Accumulated here rather than
|
|
56
|
+
// derived from `collected`, which counts violations and cannot distinguish
|
|
57
|
+
// "20 rules, none failing" from "no rules loaded" — the whole point of the line.
|
|
58
|
+
let ruleCount = 0;
|
|
59
|
+
let failedRules = 0;
|
|
60
|
+
for (const file of args.ruleFiles) {
|
|
61
|
+
// TWO catches, at the two boundaries that can fail independently. Loading is
|
|
62
|
+
// per file and can only be attributed to the file; evaluating is per builder,
|
|
63
|
+
// so a single malformed rule must not take its twenty siblings in the same
|
|
64
|
+
// file down with it — which one catch around the whole file would do
|
|
65
|
+
// (bug 0025).
|
|
66
|
+
let builders;
|
|
67
|
+
// Read before the module evaluates, so the delta below describes THIS file.
|
|
68
|
+
const writtenBefore = violationsWritten();
|
|
27
69
|
try {
|
|
28
|
-
|
|
70
|
+
builders = await loadRuleFiles([file], { fresh: args.fresh });
|
|
29
71
|
}
|
|
30
72
|
catch (error) {
|
|
31
|
-
|
|
32
|
-
|
|
73
|
+
// A user rule file that self-executes a throwing `.check()` at import
|
|
74
|
+
// surfaces its violations rather than crashing. (Presets no longer throw
|
|
75
|
+
// at import — they return builders.)
|
|
76
|
+
collected.push(...failureOrViolations(file, error, total));
|
|
77
|
+
// …and, for a thrown TERMINAL, say that the file stopped there — the part R3a
|
|
78
|
+
// specified and did not build (bug 0029). A throw during import aborts the
|
|
79
|
+
// module, so any rule declared after it never ran and its violations are not
|
|
80
|
+
// in this report, while the run is red for the thrown finding so nothing else
|
|
81
|
+
// reveals the gap.
|
|
82
|
+
//
|
|
83
|
+
// **Only for an `ArchRuleError`**, which is the signal that a terminal fired:
|
|
84
|
+
// rules before it DID run and report, rules after did not. For any other error
|
|
85
|
+
// — a syntax error, a missing dependency — nothing ran at all, and
|
|
86
|
+
// `ruleFileFailure` already says the file could not be evaluated. Adding
|
|
87
|
+
// "the rules after this never ran" there would imply some had, and point at a
|
|
88
|
+
// "finding above" that is an error rather than a finding. Three of bug 0025's
|
|
89
|
+
// own tests caught exactly that when this fired unconditionally.
|
|
90
|
+
//
|
|
91
|
+
// Only at THIS boundary either way. A throw from `builder.violations()` below
|
|
92
|
+
// happens after the module finished, so nothing was truncated, and the
|
|
93
|
+
// `export default [rule1, rule2]` shape never reaches here at all — an array
|
|
94
|
+
// export builds every rule before any of them runs.
|
|
95
|
+
if (isArchRuleError(error)) {
|
|
96
|
+
collected.push(ruleFileTruncated(file, total));
|
|
97
|
+
// Bug 0199 — the same boundary, the other consequence.
|
|
98
|
+
//
|
|
99
|
+
// `failureOrViolations` above DID collect this error's violations and
|
|
100
|
+
// `baseline.filterNew` below DOES filter them. What escaped is the rule
|
|
101
|
+
// file's OWN printing: `executeCheck` calls `writeReport` unconditionally
|
|
102
|
+
// one line before it throws (`core/execute-rule.ts`), so a `.check()`
|
|
103
|
+
// at module scope prints its findings before the CLI can filter anything.
|
|
104
|
+
// the aggregation flag does not stop it — that flag is read only by
|
|
105
|
+
// `executeWarn` (`:526`). Root cause is bug 0201.
|
|
106
|
+
//
|
|
107
|
+
// **Only when something was actually printed.** `executeWarn` throws the
|
|
108
|
+
// same error type, and when the CLI is aggregating it writes only the
|
|
109
|
+
// non-`bypassFilters` entries — for a configuration finding that is
|
|
110
|
+
// nothing at all. Firing on the bare `isArchRuleError` condition claimed a
|
|
111
|
+
// leak that did not happen, over a finding whose own text says a baseline
|
|
112
|
+
// can never suppress it: ADR-009 rule 2, a failure asserting a cause it
|
|
113
|
+
// cannot verify. Measured by review; `it('does not fire when the throw
|
|
114
|
+
// carried nothing the rule file could print')` holds it.
|
|
115
|
+
//
|
|
116
|
+
// **Only when output actually leaked**, measured rather than inferred.
|
|
117
|
+
//
|
|
118
|
+
// More than two paths reach this catch and they do not agree on whether
|
|
119
|
+
// they printed: a `.check()` (silent since bug 0201), a preset via the
|
|
120
|
+
// kernel's `reportViolations`, `checkAll()`, and a `.warn()` with a live
|
|
121
|
+
// selector. So the notice asks the only question it may assert — *did
|
|
122
|
+
// anything emit while this module was loading?* — by reading a delta over
|
|
123
|
+
// both emitters.
|
|
124
|
+
//
|
|
125
|
+
// **The first version inverted this and it was a measured defect.** It
|
|
126
|
+
// counted the writes `executeCheck` SUPPRESSED and read the absence of a
|
|
127
|
+
// suppression as "nothing leaked". A file that suppresses one terminal
|
|
128
|
+
// while leaking through another satisfies that and leaks: measured, a
|
|
129
|
+
// `report: 'warn'` preset beside a silenced `.check()` leaked 7 violation
|
|
130
|
+
// blocks in total silence. A silence built on a stale signal is worse than
|
|
131
|
+
// the false claim it replaced, because the run says nothing at all.
|
|
132
|
+
const leaked = violationsWritten() > writtenBefore;
|
|
133
|
+
const printedUnfiltered = error.violations.some((v) => v.bypassFilters !== true);
|
|
134
|
+
const filtering = args.baseline !== undefined || args.changed;
|
|
135
|
+
if (filtering && printedUnfiltered && leaked) {
|
|
136
|
+
collected.push(baselineNotApplied(file, { baseline: args.baseline, changed: args.changed }));
|
|
137
|
+
}
|
|
33
138
|
}
|
|
34
|
-
|
|
35
|
-
|
|
139
|
+
failedRules++;
|
|
140
|
+
continue;
|
|
141
|
+
}
|
|
142
|
+
// A file that loaded cleanly and produced nothing is the alarm value the
|
|
143
|
+
// summary line exists to print — and `check` used to print `✓ … 0 rules` over
|
|
144
|
+
// it while `doctor` refused the same file. See `ruleFileContributedNoRules`.
|
|
145
|
+
if (builders.length === 0) {
|
|
146
|
+
collected.push(ruleFileContributedNoRules(file));
|
|
147
|
+
failedRules++;
|
|
148
|
+
}
|
|
149
|
+
ruleCount += builders.length;
|
|
150
|
+
for (const builder of builders) {
|
|
151
|
+
try {
|
|
152
|
+
// Attributed here, where the rule file is known. A builder cannot do it
|
|
153
|
+
// — the same builder is legal in a test file, where vitest supplies the
|
|
154
|
+
// frame instead (bug 0026).
|
|
155
|
+
const found = attributeToRuleFile(builder.violations(), file);
|
|
156
|
+
if (found.length > 0)
|
|
157
|
+
failedRules++;
|
|
158
|
+
collected.push(...found);
|
|
159
|
+
}
|
|
160
|
+
catch (error) {
|
|
161
|
+
failedRules++;
|
|
162
|
+
collected.push(...failureOrViolations(file, error, total));
|
|
36
163
|
}
|
|
37
164
|
}
|
|
38
165
|
}
|
|
166
|
+
// One option, one finding (plan 0074) — after the per-file loop, because the
|
|
167
|
+
// key includes the rule file: two files with the same bad preset option are
|
|
168
|
+
// two edits and must both be reported.
|
|
169
|
+
collected = dedupeConfigFindings(collected);
|
|
170
|
+
let filtered = collected;
|
|
171
|
+
if (baseline)
|
|
172
|
+
filtered = baseline.filterNew(filtered);
|
|
173
|
+
// The one surface that can count. `filterToChanged` runs once here over every
|
|
174
|
+
// collected violation, so `before - after` is the whole run's suppression —
|
|
175
|
+
// unlike the per-rule terminals, which see one rule each (plan 0071,
|
|
176
|
+
// `core/diff-disclosure.ts`). Derived by subtraction rather than asked of the
|
|
177
|
+
// filter, so it holds for a caller-supplied `DiffFilterLike` too.
|
|
178
|
+
let notice;
|
|
179
|
+
if (diff) {
|
|
180
|
+
const before = filtered.length;
|
|
181
|
+
filtered = diff.filterToChanged(filtered);
|
|
182
|
+
notice = suppressionNotice(before - filtered.length, diff.size, diff.baseBranch);
|
|
183
|
+
if (notice !== undefined)
|
|
184
|
+
writeStderr(notice);
|
|
185
|
+
}
|
|
186
|
+
// writeReport handles empties: json always emits one document (so a clean run
|
|
187
|
+
// is still parseable), terminal/github emit nothing. The notice rides along as
|
|
188
|
+
// `summary.reason` so a `--format json` consumer reading only stdout still
|
|
189
|
+
// learns the report is partial — stderr and stdout are different streams, and
|
|
190
|
+
// an agent piping one of them would otherwise see `total: 0` and stop.
|
|
191
|
+
// `reason` is rendered as each violation's "Why:" line on the terminal path
|
|
192
|
+
// (`format.ts`: `v.because ?? reason`), so a RUN-level notice must not travel
|
|
193
|
+
// that way — it would appear as the justification for an unrelated finding.
|
|
194
|
+
// `summary.reason` in JSON is genuinely run-level, so it goes there, and
|
|
195
|
+
// stderr carries it for every other format. Found by sabotage: removing the
|
|
196
|
+
// `writeStderr` call left the tests green because the notice was reaching
|
|
197
|
+
// stderr through the "Why:" line instead.
|
|
198
|
+
writeReport(filtered, format, format === 'json' ? notice : undefined, untestedRules());
|
|
199
|
+
// Bug 0015, and it goes AFTER the report so it reads as a footnote rather than
|
|
200
|
+
// as part of the findings. JSON carries the same information structurally in
|
|
201
|
+
// `summary.untestedAllowlists`, so emitting the prose there too would duplicate
|
|
202
|
+
// it into a document a consumer parses.
|
|
203
|
+
if (format !== 'json') {
|
|
204
|
+
const coverage = edgeCoverageNotice();
|
|
205
|
+
if (coverage !== undefined)
|
|
206
|
+
writeStderr(`${coverage}\n`);
|
|
207
|
+
}
|
|
208
|
+
// Inline exclusion comments, same footnote position and the same reason. Kept
|
|
209
|
+
// out of the JSON prose for the same reason coverage is: a consumer parsing
|
|
210
|
+
// that document gets the identities structurally, not as a sentence to grep.
|
|
211
|
+
if (format !== 'json') {
|
|
212
|
+
const suppressed = commentSuppressionNotice();
|
|
213
|
+
if (suppressed !== undefined)
|
|
214
|
+
writeStderr(`${suppressed}\n`);
|
|
215
|
+
}
|
|
39
216
|
// Report the denominator so a fast green is provably non-vacuous, not silence.
|
|
40
217
|
// Terminal only — JSON/GitHub-annotation output on stdout stays machine-clean.
|
|
218
|
+
//
|
|
219
|
+
// Present on `main` and dropped by plan 0165's engine copy (`9489684`), which
|
|
220
|
+
// overwrote this file wholesale. Restored here rather than treated as the
|
|
221
|
+
// never-had-it gap bug 0174 filed it as: published `eess-ts@0.2.1` ships it,
|
|
222
|
+
// so its absence was a regression, and a green run that prints nothing cannot
|
|
223
|
+
// be told apart from a run that loaded no rules — the ADR-009/010 failure this
|
|
224
|
+
// package exists to prevent, arriving through its own CLI.
|
|
41
225
|
if (format === 'terminal') {
|
|
42
226
|
const ms = Date.now() - started;
|
|
43
|
-
const time = ms < 1000 ? `${ms}ms` : `${(ms / 1000).toFixed(2)}s`;
|
|
44
|
-
const
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
227
|
+
const time = ms < 1000 ? `${String(ms)}ms` : `${(ms / 1000).toFixed(2)}s`;
|
|
228
|
+
const scope = `${String(ruleCount)} rule${ruleCount === 1 ? '' : 's'} across ${String(total)} file${total === 1 ? '' : 's'}`;
|
|
229
|
+
// **The symbol is computed from exactly what the exit code is computed from**
|
|
230
|
+
// — the error-severity count after filtering. Two ways this line lied before,
|
|
231
|
+
// both measured on the documented on-ramp:
|
|
232
|
+
//
|
|
233
|
+
// - keyed on the RAW failure tally, a baseline that suppressed everything
|
|
234
|
+
// printed `✗ … · 0 violations` beside `exit 0`;
|
|
235
|
+
// - keyed on `filtered.length`, a warn-only run printed `✗` beside `exit 0`,
|
|
236
|
+
// because warnings are advisory and never fail (which the scaffold's own
|
|
237
|
+
// output tells the adopter).
|
|
238
|
+
//
|
|
239
|
+
// The symbol, the count and the exit code are three renderings of one fact.
|
|
240
|
+
// Warnings are disclosed alongside rather than folded in or dropped — a run
|
|
241
|
+
// with warnings is not failing, and is not the same as a silent one.
|
|
242
|
+
//
|
|
243
|
+
// `failedRules` is still counted because it answers a different question —
|
|
244
|
+
// how many RULES failed, versus how many violations there were — and a run
|
|
245
|
+
// where one rule produced forty is worth telling apart from forty rules
|
|
246
|
+
// producing one each.
|
|
247
|
+
const errors = filtered.filter((v) => (v.severity ?? 'error') === 'error').length;
|
|
248
|
+
const warns = filtered.length - errors;
|
|
249
|
+
const warnNote = warns === 0 ? '' : ` · ${String(warns)} warning${warns === 1 ? '' : 's'}`;
|
|
250
|
+
writeStderr(errors === 0
|
|
251
|
+
? `\n✓ eess-ts — ${scope} · 0 failing${warnNote} (${time})\n`
|
|
252
|
+
: `\n✗ eess-ts — ${scope} · ${String(failedRules)} of ${String(ruleCount)} rule${ruleCount === 1 ? '' : 's'} failing · ${String(errors)} violation${errors === 1 ? '' : 's'}${warnNote} (${time})\n`);
|
|
65
253
|
}
|
|
254
|
+
// Exit code = error-severity count; warns are reported but never fail.
|
|
255
|
+
return filtered.filter((v) => (v.severity ?? 'error') === 'error').length;
|
|
66
256
|
}
|
|
67
257
|
/**
|
|
68
258
|
* Apply deterministic fixes (plan 0066). Dry-run unless `write`. Returns the
|
|
69
|
-
* count of violations that have no automatic fix
|
|
259
|
+
* count of violations that have no automatic fix.
|
|
260
|
+
*
|
|
261
|
+
* The remaining-count IS the exit code, deliberately: a run that fixed
|
|
262
|
+
* everything it could and still leaves real findings must not exit 0 just
|
|
263
|
+
* because it did some work. `applyFixes` skips overlapping edits rather than
|
|
264
|
+
* guessing, and says how many it skipped — a silently-dropped edit would leave
|
|
265
|
+
* the file half-repaired with a green run to match.
|
|
70
266
|
*/
|
|
71
267
|
function runFix(builders, options, write) {
|
|
72
|
-
const all = builders.flatMap((b) =>
|
|
268
|
+
const all = builders.flatMap((b) => b.violations());
|
|
73
269
|
const fixable = all.filter((v) => v.fix !== undefined);
|
|
74
270
|
const result = applyFixes(fixable, { write });
|
|
75
271
|
const header = write
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"check.js","sourceRoot":"","sources":["../../../src/cli/commands/check.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"check.js","sourceRoot":"","sources":["../../../src/cli/commands/check.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
interface DoctorArgs {
|
|
2
|
+
ruleFiles: string[];
|
|
3
|
+
format: 'terminal' | 'json';
|
|
4
|
+
}
|
|
5
|
+
/**
|
|
6
|
+
* Report what each rule cannot enforce, without evaluating their conditions.
|
|
7
|
+
*
|
|
8
|
+
* It DOES materialize each rule's selection, as of plan 0096: "this rule examined
|
|
9
|
+
* nothing" is a fact about the selection, and the preview for 0098's floor has to
|
|
10
|
+
* read the same computation the floor will. The docstring used to say "without
|
|
11
|
+
* running any of them" and that stopped being true.
|
|
12
|
+
*
|
|
13
|
+
* **Supported and scoped** since plan 0077, which settled the keep-or-retire
|
|
14
|
+
* question 0069 left open. It diagnoses rule files the CLI can **load** — the
|
|
15
|
+
* `arch.rules.ts` shape `init` scaffolds, which `getting-started.md` calls the
|
|
16
|
+
* default path. Rules hosted in a vitest or jest file cannot be imported outside
|
|
17
|
+
* their runner; `diagnose()` is the answer there and reports the same findings.
|
|
18
|
+
*
|
|
19
|
+
* **Why the command earns its slot:** a **dead glob**. A rule whose selector can
|
|
20
|
+
* never match certifies nothing, and `check` never calls `diagnose()` — measured,
|
|
21
|
+
* `check` exits 0 with no output on such a rule while this reports it and exits
|
|
22
|
+
* 1. Until 0069's R3b turns that into a check-time failure, this and `diagnose()`
|
|
23
|
+
* are the only surfaces that see it.
|
|
24
|
+
*
|
|
25
|
+
* Not a build gate (0069): `check` is the gate.
|
|
26
|
+
*/
|
|
27
|
+
export declare function runDoctor(args: DoctorArgs): Promise<number>;
|
|
28
|
+
export {};
|
|
29
|
+
//# sourceMappingURL=doctor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"doctor.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/doctor.ts"],"names":[],"mappings":"AAOA,UAAU,UAAU;IAClB,SAAS,EAAE,MAAM,EAAE,CAAA;IACnB,MAAM,EAAE,UAAU,GAAG,MAAM,CAAA;CAC5B;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAsB,SAAS,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC,CAyIjE"}
|
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
import { diagnose } from '../../core/diagnose.js';
|
|
2
|
+
import { isArchRuleError } from '@nielspeter/eess';
|
|
3
|
+
import { loadRuleFiles } from '../load-rules.js';
|
|
4
|
+
import { writeStderr } from '@nielspeter/eess';
|
|
5
|
+
import { orphanExclusions } from '../../core/orphan-exclusions.js';
|
|
6
|
+
/**
|
|
7
|
+
* Report what each rule cannot enforce, without evaluating their conditions.
|
|
8
|
+
*
|
|
9
|
+
* It DOES materialize each rule's selection, as of plan 0096: "this rule examined
|
|
10
|
+
* nothing" is a fact about the selection, and the preview for 0098's floor has to
|
|
11
|
+
* read the same computation the floor will. The docstring used to say "without
|
|
12
|
+
* running any of them" and that stopped being true.
|
|
13
|
+
*
|
|
14
|
+
* **Supported and scoped** since plan 0077, which settled the keep-or-retire
|
|
15
|
+
* question 0069 left open. It diagnoses rule files the CLI can **load** — the
|
|
16
|
+
* `arch.rules.ts` shape `init` scaffolds, which `getting-started.md` calls the
|
|
17
|
+
* default path. Rules hosted in a vitest or jest file cannot be imported outside
|
|
18
|
+
* their runner; `diagnose()` is the answer there and reports the same findings.
|
|
19
|
+
*
|
|
20
|
+
* **Why the command earns its slot:** a **dead glob**. A rule whose selector can
|
|
21
|
+
* never match certifies nothing, and `check` never calls `diagnose()` — measured,
|
|
22
|
+
* `check` exits 0 with no output on such a rule while this reports it and exits
|
|
23
|
+
* 1. Until 0069's R3b turns that into a check-time failure, this and `diagnose()`
|
|
24
|
+
* are the only surfaces that see it.
|
|
25
|
+
*
|
|
26
|
+
* Not a build gate (0069): `check` is the gate.
|
|
27
|
+
*/
|
|
28
|
+
export async function runDoctor(args) {
|
|
29
|
+
if (args.ruleFiles.length === 0) {
|
|
30
|
+
writeStderr('Error: no rule files. Pass them as arguments or set `rules` in your config.\n');
|
|
31
|
+
return 1;
|
|
32
|
+
}
|
|
33
|
+
// Per file, not one flat array. `diagnose()` treats rules independently, so
|
|
34
|
+
// the results are identical — but the loop is the only place that knows which
|
|
35
|
+
// file a rule came from, and flattening first discarded it (bug 0026).
|
|
36
|
+
const findings = [];
|
|
37
|
+
const rules = [];
|
|
38
|
+
// Identities, never totals (docs/cli.md): a boolean told a JSON consumer that
|
|
39
|
+
// something failed without saying which file or why, leaving them to scrape
|
|
40
|
+
// stderr prose they do not read.
|
|
41
|
+
const loadFailures = [];
|
|
42
|
+
for (const file of args.ruleFiles) {
|
|
43
|
+
try {
|
|
44
|
+
const loaded = await loadRuleFiles([file]);
|
|
45
|
+
rules.push(...loaded);
|
|
46
|
+
findings.push(...diagnose(loaded).map((f) => ({ ...f, ruleFile: file })));
|
|
47
|
+
}
|
|
48
|
+
catch (error) {
|
|
49
|
+
// A rule file that self-executes a throwing `.check()` at import is a
|
|
50
|
+
// documented shape, and `runCheck` already tolerates it. Without this,
|
|
51
|
+
// `doctor` — the pre-flight R3b's gate depends on — crashes on the
|
|
52
|
+
// commonest legacy rule-file shape and abandons every remaining file,
|
|
53
|
+
// so the gate cannot be run on the population it was invented for.
|
|
54
|
+
// `loadRuleFiles` accumulates into a local array and returns it only
|
|
55
|
+
// after its own loop, so when the import throws NOTHING from that file
|
|
56
|
+
// survives. Saying "diagnosing what loaded" would be false, and
|
|
57
|
+
// swallowing it silently turned a visible crash into `exit 0` plus a
|
|
58
|
+
// clean bill of health — the ADR-009 rule 1 failure this command exists
|
|
59
|
+
// to surface, committed by the command.
|
|
60
|
+
//
|
|
61
|
+
// Two loud shapes (plan 0070 round 2): an ArchRuleError means the file
|
|
62
|
+
// self-executes a failing rule at import; anything else — measured, a
|
|
63
|
+
// raw TypeError from importing a vitest test file — used to crash the
|
|
64
|
+
// whole command and abandon every remaining file.
|
|
65
|
+
if (isArchRuleError(error)) {
|
|
66
|
+
writeStderr(`Error: ${file} executes its rules at import and threw, so none of it could be ` +
|
|
67
|
+
`diagnosed. Leave builders un-terminated in a rule file (see docs/running-in-tests).\n`);
|
|
68
|
+
}
|
|
69
|
+
else {
|
|
70
|
+
// The remedy is CONDITIONAL: this branch fires for any load failure —
|
|
71
|
+
// a syntax error, a missing dependency — and asserting "this imports a
|
|
72
|
+
// test runner" unconditionally would be a false cause (ADR-009 rule 2,
|
|
73
|
+
// caught in review). The error message is the evidence; the test-runner
|
|
74
|
+
// sentence is offered as the common case, not stated as the cause.
|
|
75
|
+
writeStderr(`Error: ${file} could not be loaded (${error instanceof Error ? error.message : String(error)}), ` +
|
|
76
|
+
`so none of it could be diagnosed. If this file imports a test runner (vitest/jest), ` +
|
|
77
|
+
`doctor cannot load it — run your test suite instead; the runtime writes the same ` +
|
|
78
|
+
`diagnostics to stderr.\n`);
|
|
79
|
+
}
|
|
80
|
+
loadFailures.push({ file, error: error instanceof Error ? error.message : String(error) });
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
// Orphan exclusion comments, AFTER the loop and over every rule at once
|
|
84
|
+
// (bug 0044). Not inside the loop and not inside `diagnose()`: the declared-id
|
|
85
|
+
// set is the union across rule files, so a per-file check would report a
|
|
86
|
+
// directive naming a rule declared in a sibling file as an orphan. That is a
|
|
87
|
+
// false positive on the commonest multi-file layout, and a diagnostic that
|
|
88
|
+
// cries wolf is one nobody runs.
|
|
89
|
+
//
|
|
90
|
+
// Reported as `dead-glob`'s sibling kind rather than a separate output
|
|
91
|
+
// section, so `--format json` consumers get it through the `findings` array
|
|
92
|
+
// they already parse.
|
|
93
|
+
// The scope is passed, so the advice can say what it checked. `doctor
|
|
94
|
+
// arch.rules.ts` — the single-file form `docs/cli.md` itself shows — sees a
|
|
95
|
+
// subset of a multi-file project's rules, and a directive naming a rule from
|
|
96
|
+
// another file would otherwise be reported as an orphan with "delete the
|
|
97
|
+
// comment" as its remedy. Deleting a working comment un-waives a real
|
|
98
|
+
// violation, which is the rule-2 failure this caveat exists to prevent.
|
|
99
|
+
for (const orphan of orphanExclusions(rules, { ruleFilesChecked: args.ruleFiles.length })) {
|
|
100
|
+
findings.push({
|
|
101
|
+
kind: 'orphan-exclusion',
|
|
102
|
+
rule: orphan.ruleId,
|
|
103
|
+
advice: orphan.advice,
|
|
104
|
+
// `sourceFile`, not `ruleFile`: that field is documented as "the rule file
|
|
105
|
+
// this rule was written in", and putting a *source* path there gave JSON
|
|
106
|
+
// consumers two different things under one name, by `kind`, undocumented.
|
|
107
|
+
sourceFile: orphan.file,
|
|
108
|
+
line: orphan.line,
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
// A load failure is a REPORT, and this command's contract is "exits
|
|
112
|
+
// non-zero when it reports anything". Review measured the mixed case —
|
|
113
|
+
// one broken file, one clean file, zero findings — printing the error and
|
|
114
|
+
// then exiting 0 with a clean bill of health: exactly the "exit 0 plus
|
|
115
|
+
// silence" this command exists to prevent, reintroduced by the catch that
|
|
116
|
+
// fixed the crash. Every exit path below folds the load failures in.
|
|
117
|
+
//
|
|
118
|
+
// And every exit path emits the JSON document when asked for it: a consumer
|
|
119
|
+
// parsing stdout used to get zero bytes on the commonest single-file failure,
|
|
120
|
+
// and `JSON.parse('')` throws — the exact consumer the exit-code fix was for.
|
|
121
|
+
const emitJson = (findings) => {
|
|
122
|
+
if (args.format === 'json') {
|
|
123
|
+
process.stdout.write(JSON.stringify({ findings, loadFailures }, null, 2) + '\n');
|
|
124
|
+
}
|
|
125
|
+
};
|
|
126
|
+
if (loadFailures.length > 0 && rules.length === 0) {
|
|
127
|
+
emitJson([]);
|
|
128
|
+
return 1;
|
|
129
|
+
}
|
|
130
|
+
// Nothing to diagnose is not the same as nothing wrong. The earlier guard
|
|
131
|
+
// checked `args.ruleFiles.length`, which is the wrong derivation: a file
|
|
132
|
+
// exporting `[]` reached this point and reported a clean bill of health.
|
|
133
|
+
if (rules.length === 0) {
|
|
134
|
+
writeStderr('Error: no rules found in the given files.\n');
|
|
135
|
+
emitJson([]);
|
|
136
|
+
return 1;
|
|
137
|
+
}
|
|
138
|
+
if (args.format === 'json') {
|
|
139
|
+
emitJson(findings);
|
|
140
|
+
return findings.length > 0 || loadFailures.length > 0 ? 1 : 0;
|
|
141
|
+
}
|
|
142
|
+
if (findings.length === 0) {
|
|
143
|
+
if (loadFailures.length > 0) {
|
|
144
|
+
writeStderr('No findings in the rules that loaded — but at least one file could not be ' +
|
|
145
|
+
'loaded (see above), so this is not a clean bill of health.\n');
|
|
146
|
+
return 1;
|
|
147
|
+
}
|
|
148
|
+
writeStderr('No rules that cannot enforce anything.\n');
|
|
149
|
+
return 0;
|
|
150
|
+
}
|
|
151
|
+
writeStderr(format(findings));
|
|
152
|
+
return 1;
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* Which kinds carry a glob, and therefore render with origin/position/fault.
|
|
156
|
+
*
|
|
157
|
+
* A `Record` over the union rather than a boolean expression, so that adding a
|
|
158
|
+
* kind fails `tsc` until someone decides how it renders. `project-empty` was
|
|
159
|
+
* added to `DiagnosticFinding['kind']` and this file kept compiling — the gap
|
|
160
|
+
* that made the choice implicit.
|
|
161
|
+
*/
|
|
162
|
+
const HAS_GLOB = {
|
|
163
|
+
'dead-glob': true,
|
|
164
|
+
'no-condition': false,
|
|
165
|
+
'project-unknown': false,
|
|
166
|
+
'project-empty': false,
|
|
167
|
+
// No glob: the fault is the family's own filters emptying the set, so there
|
|
168
|
+
// is no glob text to point at (plan 0096).
|
|
169
|
+
'zero-subjects': false,
|
|
170
|
+
// No glob: the fault is the family's own adequacy predicate, not a
|
|
171
|
+
// selector — the corpus was found and examined, it just cannot ever
|
|
172
|
+
// produce a finding as configured (plan 0102).
|
|
173
|
+
inert: false,
|
|
174
|
+
// No glob: the subject is a comment in a source file, and the identity is the
|
|
175
|
+
// rule id it names plus where it sits. That is why this kind carries `line`.
|
|
176
|
+
'orphan-exclusion': false,
|
|
177
|
+
// No glob: the fault is specific CURRENT violations not covered by the
|
|
178
|
+
// rule's own `accepted` list, not a selector — the corpus was found and
|
|
179
|
+
// examined, and some of what it found is not what was accepted (plan 0090).
|
|
180
|
+
'deferred-warning': false,
|
|
181
|
+
};
|
|
182
|
+
function format(findings) {
|
|
183
|
+
const lines = [''];
|
|
184
|
+
for (const finding of findings) {
|
|
185
|
+
// The rule file first: with two identical vacuous rules in two files, the
|
|
186
|
+
// rule's own description is the same sentence twice and says nothing about
|
|
187
|
+
// which to open.
|
|
188
|
+
// An orphan exclusion is located by its SOURCE file and line, not by a rule
|
|
189
|
+
// file — the subject is a comment. The changelog claimed this printed "the
|
|
190
|
+
// file and line" and the terminal format printed neither, so two stale
|
|
191
|
+
// directives in one file rendered as two identical headers.
|
|
192
|
+
if (finding.sourceFile !== undefined) {
|
|
193
|
+
const at = finding.line === undefined ? '' : `:${String(finding.line)}`;
|
|
194
|
+
lines.push(` ${finding.sourceFile}${at}`);
|
|
195
|
+
lines.push(` ${finding.rule}`);
|
|
196
|
+
}
|
|
197
|
+
else {
|
|
198
|
+
lines.push(finding.ruleFile === undefined ? ` ${finding.rule}` : ` ${finding.ruleFile}`);
|
|
199
|
+
if (finding.ruleFile !== undefined)
|
|
200
|
+
lines.push(` ${finding.rule}`);
|
|
201
|
+
}
|
|
202
|
+
if (HAS_GLOB[finding.kind]) {
|
|
203
|
+
lines.push(` ${finding.origin ?? finding.glob ?? '(unknown)'} [${finding.position ?? 'unknown'}]`, ` ${finding.fault ?? 'unknown'}: ${finding.advice}`);
|
|
204
|
+
}
|
|
205
|
+
else {
|
|
206
|
+
// `no-condition`, `project-unknown` and `project-empty` have no glob, no
|
|
207
|
+
// position and no fault. Rendering them through the dead-glob shape
|
|
208
|
+
// printed `(unknown) [unknown]` / `unknown: …`, which reads like a bug in
|
|
209
|
+
// the tool rather than a finding about the rule.
|
|
210
|
+
//
|
|
211
|
+
// `HAS_GLOB` below is what makes adding a fifth kind a COMPILE error
|
|
212
|
+
// rather than a silent fall into this branch. `project-empty` was added
|
|
213
|
+
// to the union and compiled without anyone choosing a rendering for it —
|
|
214
|
+
// an if/else cannot ask the question, and `Record<K, …>` can. Same device
|
|
215
|
+
// as `FAULT_ADVICE` and `ON_DISK_ADVICE` in `glob-diagnosis.ts`.
|
|
216
|
+
lines.push(` ${finding.kind}: ${finding.advice}`);
|
|
217
|
+
}
|
|
218
|
+
lines.push('');
|
|
219
|
+
}
|
|
220
|
+
// Deliberately no total. A count is the snapshot ADR-009 rule 4 bars, and it
|
|
221
|
+
// is the number people ratchet against instead of fixing the findings.
|
|
222
|
+
return lines.join('\n');
|
|
223
|
+
}
|
|
224
|
+
//# sourceMappingURL=doctor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"doctor.js","sourceRoot":"","sources":["../../../src/cli/commands/doctor.ts"],"names":[],"mappings":"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"}
|