@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
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import type { GlobSite } from '@nielspeter/eess';
|
|
2
|
+
import type { PathUniverse } from './path-universe.js';
|
|
3
|
+
import type { DiskSet, OnDisk } from './disk-set.js';
|
|
4
|
+
/**
|
|
5
|
+
* Why a glob matches nothing.
|
|
6
|
+
*
|
|
7
|
+
* Two of these name a cause, and only because the fix is a transformation that
|
|
8
|
+
* can be *verified*: removing `./`, and adding the `**\/` anchor. A third,
|
|
9
|
+
* `file-not-folder`, is verifiable in the other direction — the glob matches a
|
|
10
|
+
* file and no directory, and the predicate reads directories. Everything else
|
|
11
|
+
* falls into `no-match`, which lists likely causes without asserting one.
|
|
12
|
+
*
|
|
13
|
+
* That restraint is deliberate and was learned the hard way. Earlier revisions
|
|
14
|
+
* asserted a specific cause — "the directory does not exist", "append `/**`" —
|
|
15
|
+
* and each was false on a reachable input: a glob targeting a file, a
|
|
16
|
+
* directory whose name ends in `]`, a path that plainly existed. Under ADR-008
|
|
17
|
+
* a confidently wrong cause is worse than an honest list, because the agent
|
|
18
|
+
* acts on it.
|
|
19
|
+
*/
|
|
20
|
+
export type GlobFault = 'dot-segment' | 'unanchored' | 'file-not-folder' | 'no-match';
|
|
21
|
+
interface GlobDiagnosis {
|
|
22
|
+
readonly fault: GlobFault;
|
|
23
|
+
readonly onDisk?: OnDisk;
|
|
24
|
+
}
|
|
25
|
+
/** Where the glob conventions these messages talk about are documented. */
|
|
26
|
+
export declare const GLOB_DOCS = "https://github.com/nielspeter/eess/blob/main/docs/slices.md";
|
|
27
|
+
/**
|
|
28
|
+
* Whether a glob can already match an absolute path.
|
|
29
|
+
*
|
|
30
|
+
* Defined in `project-relative.ts` and re-exported here, where its callers are.
|
|
31
|
+
* It has to live at the lower level: `isProjectRelative` is defined as its
|
|
32
|
+
* negation, and importing it upward from there closed a cycle —
|
|
33
|
+
* `disk-set -> path-universe -> glob-diagnosis -> project-relative -> project
|
|
34
|
+
* -> disk-set`, caught by this repository's own `beFreeOfCycles` rule. The
|
|
35
|
+
* predicate is pure string syntax with no dependencies, so the lower level is
|
|
36
|
+
* where it belonged anyway.
|
|
37
|
+
*/
|
|
38
|
+
export { isAnchored } from './project-relative.js';
|
|
39
|
+
/**
|
|
40
|
+
* The faults decidable from the glob string alone, with no project to compare
|
|
41
|
+
* against.
|
|
42
|
+
*
|
|
43
|
+
* Split out because two callers need exactly this and nothing more: the
|
|
44
|
+
* `assignedFrom()` message, which groups entries by cause before any universe
|
|
45
|
+
* is available, and `diagnoseGlob` below. One source of truth for the syntax
|
|
46
|
+
* rules, so the two can never drift into disagreeing about what `./src/**` is.
|
|
47
|
+
*/
|
|
48
|
+
export declare function syntacticFault(glob: string, kind: GlobSite['kind'], base?: GlobSite['base']): 'dot-segment' | 'unanchored' | undefined;
|
|
49
|
+
/**
|
|
50
|
+
* Diagnose one unsatisfiable glob.
|
|
51
|
+
*
|
|
52
|
+
* Call only on a site already known to be dead — this explains a fault, it
|
|
53
|
+
* does not detect one. Keeping detection (`isDeadSite`) and explanation apart
|
|
54
|
+
* is what stops the disk walk from ever becoming a *trigger*: a project with
|
|
55
|
+
* no faults never touches the filesystem.
|
|
56
|
+
*
|
|
57
|
+
* Each fault has a different fix, so they are reported separately. A message
|
|
58
|
+
* that lumps them together, or reports only the first kind it finds, sends the
|
|
59
|
+
* caller through repeated failing runs.
|
|
60
|
+
*/
|
|
61
|
+
export declare function diagnoseGlob(site: GlobSite, universe: PathUniverse, diskSet?: DiskSet): GlobDiagnosis;
|
|
62
|
+
/**
|
|
63
|
+
* The remedy for each fault, or an honest list of causes where no remedy is
|
|
64
|
+
* verifiable.
|
|
65
|
+
*/
|
|
66
|
+
export declare const FAULT_ADVICE: Readonly<Record<GlobFault, string>>;
|
|
67
|
+
/**
|
|
68
|
+
* What the filesystem adds, when it adds anything.
|
|
69
|
+
*
|
|
70
|
+
* Stated as a fact and never as a remedy. Every candidate remedy here is wrong
|
|
71
|
+
* on a reachable input: "add it to your tsconfig `include`" is wrong for
|
|
72
|
+
* `dist/`, for codegen output, and absurd for the Rust crate that a real
|
|
73
|
+
* TypeScript monorepo turned out to contain. So this contributes the fact and
|
|
74
|
+
* its own two causes, rather than deferring to `no-match`'s list — two of
|
|
75
|
+
* whose three causes are refuted by the fact printed one line above.
|
|
76
|
+
*/
|
|
77
|
+
export declare const ON_DISK_ADVICE: Readonly<Record<OnDisk, string>>;
|
|
78
|
+
//# sourceMappingURL=glob-diagnosis.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"glob-diagnosis.d.ts","sourceRoot":"","sources":["../../src/core/glob-diagnosis.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAA;AAChD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA;AACtD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,eAAe,CAAA;AAEpD;;;;;;;;;;;;;;;GAeG;AACH,MAAM,MAAM,SAAS,GAAG,aAAa,GAAG,YAAY,GAAG,iBAAiB,GAAG,UAAU,CAAA;AAErF,UAAU,aAAa;IACrB,QAAQ,CAAC,KAAK,EAAE,SAAS,CAAA;IACzB,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CACzB;AAED,2EAA2E;AAC3E,eAAO,MAAM,SAAS,gEAAgE,CAAA;AAEtF;;;;;;;;;;GAUG;AACH,OAAO,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAA;AAGlD;;;;;;;;GAQG;AACH,wBAAgB,cAAc,CAC5B,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,QAAQ,CAAC,MAAM,CAAC,EACtB,IAAI,GAAE,QAAQ,CAAC,MAAM,CAAc,GAClC,aAAa,GAAG,YAAY,GAAG,SAAS,CAiB1C;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,YAAY,CAC1B,IAAI,EAAE,QAAQ,EACd,QAAQ,EAAE,YAAY,EACtB,OAAO,CAAC,EAAE,OAAO,GAChB,aAAa,CAiBf;AAED;;;GAGG;AACH,eAAO,MAAM,YAAY,EAAE,QAAQ,CAAC,MAAM,CAAC,SAAS,EAAE,MAAM,CAAC,CAS5D,CAAA;AAED;;;;;;;;;GASG;AACH,eAAO,MAAM,cAAc,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAoC3D,CAAA"}
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
import picomatch from 'picomatch';
|
|
2
|
+
/** Where the glob conventions these messages talk about are documented. */
|
|
3
|
+
export const GLOB_DOCS = 'https://github.com/nielspeter/eess/blob/main/docs/slices.md';
|
|
4
|
+
/**
|
|
5
|
+
* Whether a glob can already match an absolute path.
|
|
6
|
+
*
|
|
7
|
+
* Defined in `project-relative.ts` and re-exported here, where its callers are.
|
|
8
|
+
* It has to live at the lower level: `isProjectRelative` is defined as its
|
|
9
|
+
* negation, and importing it upward from there closed a cycle —
|
|
10
|
+
* `disk-set -> path-universe -> glob-diagnosis -> project-relative -> project
|
|
11
|
+
* -> disk-set`, caught by this repository's own `beFreeOfCycles` rule. The
|
|
12
|
+
* predicate is pure string syntax with no dependencies, so the lower level is
|
|
13
|
+
* where it belonged anyway.
|
|
14
|
+
*/
|
|
15
|
+
export { isAnchored } from './project-relative.js';
|
|
16
|
+
import { isAnchored } from './project-relative.js';
|
|
17
|
+
/**
|
|
18
|
+
* The faults decidable from the glob string alone, with no project to compare
|
|
19
|
+
* against.
|
|
20
|
+
*
|
|
21
|
+
* Split out because two callers need exactly this and nothing more: the
|
|
22
|
+
* `assignedFrom()` message, which groups entries by cause before any universe
|
|
23
|
+
* is available, and `diagnoseGlob` below. One source of truth for the syntax
|
|
24
|
+
* rules, so the two can never drift into disagreeing about what `./src/**` is.
|
|
25
|
+
*/
|
|
26
|
+
export function syntacticFault(glob, kind, base = 'absolute') {
|
|
27
|
+
// A './' anywhere — not just leading — makes the glob unmatchable, and
|
|
28
|
+
// adding '**/' in front of it does not help ('**/./src/**' still matches
|
|
29
|
+
// nothing). True for every base.
|
|
30
|
+
if (/(?:^|\/)\.\//.test(glob))
|
|
31
|
+
return 'dot-segment';
|
|
32
|
+
// Exempt for the kinds that are not paths: after the bug 0014 fix,
|
|
33
|
+
// `notImportFrom('fastify')` is a working rule and `isAnchored('fastify')`
|
|
34
|
+
// is false.
|
|
35
|
+
const isPathKind = kind === 'file-path' || kind === 'parent-dir';
|
|
36
|
+
// And exempt for the bases where a relative glob is the CORRECT spelling.
|
|
37
|
+
// `slices().matching()` strips and re-adds the anchor, and `resolvers()`
|
|
38
|
+
// resolves against the tsconfig directory; telling either of them to anchor
|
|
39
|
+
// would be telling the user to break a working rule.
|
|
40
|
+
if (isPathKind && base === 'absolute' && !isAnchored(glob))
|
|
41
|
+
return 'unanchored';
|
|
42
|
+
return undefined;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Diagnose one unsatisfiable glob.
|
|
46
|
+
*
|
|
47
|
+
* Call only on a site already known to be dead — this explains a fault, it
|
|
48
|
+
* does not detect one. Keeping detection (`isDeadSite`) and explanation apart
|
|
49
|
+
* is what stops the disk walk from ever becoming a *trigger*: a project with
|
|
50
|
+
* no faults never touches the filesystem.
|
|
51
|
+
*
|
|
52
|
+
* Each fault has a different fix, so they are reported separately. A message
|
|
53
|
+
* that lumps them together, or reports only the first kind it finds, sends the
|
|
54
|
+
* caller through repeated failing runs.
|
|
55
|
+
*/
|
|
56
|
+
export function diagnoseGlob(site, universe, diskSet) {
|
|
57
|
+
const syntactic = syntacticFault(site.glob, site.kind, site.base);
|
|
58
|
+
if (syntactic)
|
|
59
|
+
return { fault: syntactic };
|
|
60
|
+
// A `parent-dir` glob that matches a FILE and no directory is the
|
|
61
|
+
// `resideInFolder` mistake: the predicate reads the directory portion, so a
|
|
62
|
+
// glob written at a file can never match. Verifiable, and therefore safe to
|
|
63
|
+
// assert — measured instance: '**/src/predicates/module**' matches 1 file
|
|
64
|
+
// and 0 parent directories.
|
|
65
|
+
if (site.kind === 'parent-dir' && matchesAny(site.glob, universe.filePaths)) {
|
|
66
|
+
return { fault: 'file-not-folder' };
|
|
67
|
+
}
|
|
68
|
+
if (site.kind === 'file-path' && matchesAny(site.glob, universe.parentDirs)) {
|
|
69
|
+
return { fault: 'file-not-folder' };
|
|
70
|
+
}
|
|
71
|
+
return { fault: 'no-match', onDisk: diskSet?.classify(site.glob) ?? 'not-determined' };
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* The remedy for each fault, or an honest list of causes where no remedy is
|
|
75
|
+
* verifiable.
|
|
76
|
+
*/
|
|
77
|
+
export const FAULT_ADVICE = {
|
|
78
|
+
'dot-segment': 'a "./" segment never occurs in an absolute file path — remove it and anchor instead ("./src/x/**" -> "**/src/x/**")',
|
|
79
|
+
unanchored: 'these are matched against ABSOLUTE file paths, so a project-relative glob matches nothing — prefix these with "**/"',
|
|
80
|
+
'file-not-folder': 'this matches a FILE but is used where a directory is read, so it can never match — use resideInFile() for a file, or append "/**" to name the files inside a directory',
|
|
81
|
+
'no-match': 'these are anchored but matched no file. Common causes: the glob names a directory rather than the files inside it (append "/**"), a path segment is misspelled, or the directory holds no source files',
|
|
82
|
+
};
|
|
83
|
+
/**
|
|
84
|
+
* What the filesystem adds, when it adds anything.
|
|
85
|
+
*
|
|
86
|
+
* Stated as a fact and never as a remedy. Every candidate remedy here is wrong
|
|
87
|
+
* on a reachable input: "add it to your tsconfig `include`" is wrong for
|
|
88
|
+
* `dist/`, for codegen output, and absurd for the Rust crate that a real
|
|
89
|
+
* TypeScript monorepo turned out to contain. So this contributes the fact and
|
|
90
|
+
* its own two causes, rather than deferring to `no-match`'s list — two of
|
|
91
|
+
* whose three causes are refuted by the fact printed one line above.
|
|
92
|
+
*/
|
|
93
|
+
export const ON_DISK_ADVICE = {
|
|
94
|
+
'holds-typescript': 'this path exists and contains TypeScript, but your tsconfig include/exclude keeps it out of the project',
|
|
95
|
+
'no-typescript': 'this path exists but contains no TypeScript',
|
|
96
|
+
// Bug 0032. This was `''`, so a verified absence deferred to `no-match`'s
|
|
97
|
+
// list — the exact deferral the paragraph above rules out, and two of that
|
|
98
|
+
// list's three causes are refuted by the fact: there is no directory, so
|
|
99
|
+
// "append /**" and "holds no source files" are both false.
|
|
100
|
+
//
|
|
101
|
+
// TWO CORRECTIONS FROM REVIEW OF THE FIRST FIX, both of which made this
|
|
102
|
+
// string a new confidently-wrong message while removing an old one:
|
|
103
|
+
//
|
|
104
|
+
// 1. It said "nothing matching this exists on disk" — a universal claim the
|
|
105
|
+
// walk cannot support. `absent` means "not found in a BOUNDED walk" from
|
|
106
|
+
// `discoverIdentityRoot`, with pruned directory names and unreadable
|
|
107
|
+
// directories dropped. Measured false on two reachable inputs: a sibling
|
|
108
|
+
// package outside the identity root (a monorepo checkout with no `.git`,
|
|
109
|
+
// which `identity-root.ts` itself documents), and a real directory whose
|
|
110
|
+
// name holds glob metacharacters. So the claim is scoped to the search.
|
|
111
|
+
// 2. It offered "a folder you have not created yet — banning one
|
|
112
|
+
// pre-emptively is legitimate", borrowed from plan 0072. But 0072's case
|
|
113
|
+
// is a `notImportFrom`, a CONDITION glob, and `diagnose()` drops
|
|
114
|
+
// condition and exclusion positions before reaching here. This string is
|
|
115
|
+
// printed only for `selector` and `discovery`, where a glob matching
|
|
116
|
+
// nothing means the rule has no subjects — the false green 0069 is named
|
|
117
|
+
// after and R3b will fail the build on. It told the agent that was fine.
|
|
118
|
+
//
|
|
119
|
+
// The metacharacter cause is `slice-rule-builder.ts`'s, verbatim in
|
|
120
|
+
// substance, because it already states it for `check` — the same
|
|
121
|
+
// one-fact-two-texts trap this fix fell into elsewhere.
|
|
122
|
+
absent: 'no file or directory matching this was found under the project root (build and vendor directories are not searched, so a path inside one is not seen) — a path segment does not match what is on disk, or a literal "(", ")", "{", "}" or "!" in a folder name is being read as pattern syntax rather than a literal character, in which case match that level with "*" instead',
|
|
123
|
+
// Stays empty, and is NOT the same case as `absent` above despite looking
|
|
124
|
+
// identical. Here the walk was pruned, so no fact is known — deferring to
|
|
125
|
+
// `no-match`'s cause list is the honest move rather than a gap.
|
|
126
|
+
'not-determined': '',
|
|
127
|
+
};
|
|
128
|
+
function matchesAny(glob, candidates) {
|
|
129
|
+
const isMatch = picomatch(glob);
|
|
130
|
+
// Never `candidates.some(isMatch)` — picomatch reads the array index as its
|
|
131
|
+
// second argument and returns a truthy object from index 1 onwards.
|
|
132
|
+
return candidates.some((candidate) => isMatch(candidate));
|
|
133
|
+
}
|
|
134
|
+
//# sourceMappingURL=glob-diagnosis.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"glob-diagnosis.js","sourceRoot":"","sources":["../../src/core/glob-diagnosis.ts"],"names":[],"mappings":"AAAA,OAAO,SAAS,MAAM,WAAW,CAAA;AA4BjC,2EAA2E;AAC3E,MAAM,CAAC,MAAM,SAAS,GAAG,6DAA6D,CAAA;AAEtF;;;;;;;;;;GAUG;AACH,OAAO,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAA;AAClD,OAAO,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAA;AAElD;;;;;;;;GAQG;AACH,MAAM,UAAU,cAAc,CAC5B,IAAY,EACZ,IAAsB,EACtB,OAAyB,UAAU;IAEnC,uEAAuE;IACvE,yEAAyE;IACzE,iCAAiC;IACjC,IAAI,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC;QAAE,OAAO,aAAa,CAAA;IAEnD,mEAAmE;IACnE,2EAA2E;IAC3E,YAAY;IACZ,MAAM,UAAU,GAAG,IAAI,KAAK,WAAW,IAAI,IAAI,KAAK,YAAY,CAAA;IAEhE,0EAA0E;IAC1E,yEAAyE;IACzE,4EAA4E;IAC5E,qDAAqD;IACrD,IAAI,UAAU,IAAI,IAAI,KAAK,UAAU,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC;QAAE,OAAO,YAAY,CAAA;IAC/E,OAAO,SAAS,CAAA;AAClB,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,YAAY,CAC1B,IAAc,EACd,QAAsB,EACtB,OAAiB;IAEjB,MAAM,SAAS,GAAG,cAAc,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC,CAAA;IACjE,IAAI,SAAS;QAAE,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,CAAA;IAE1C,kEAAkE;IAClE,4EAA4E;IAC5E,4EAA4E;IAC5E,0EAA0E;IAC1E,4BAA4B;IAC5B,IAAI,IAAI,CAAC,IAAI,KAAK,YAAY,IAAI,UAAU,CAAC,IAAI,CAAC,IAAI,EAAE,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC;QAC5E,OAAO,EAAE,KAAK,EAAE,iBAAiB,EAAE,CAAA;IACrC,CAAC;IACD,IAAI,IAAI,CAAC,IAAI,KAAK,WAAW,IAAI,UAAU,CAAC,IAAI,CAAC,IAAI,EAAE,QAAQ,CAAC,UAAU,CAAC,EAAE,CAAC;QAC5E,OAAO,EAAE,KAAK,EAAE,iBAAiB,EAAE,CAAA;IACrC,CAAC;IAED,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,gBAAgB,EAAE,CAAA;AACxF,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,MAAM,YAAY,GAAwC;IAC/D,aAAa,EACX,qHAAqH;IACvH,UAAU,EACR,qHAAqH;IACvH,iBAAiB,EACf,wKAAwK;IAC1K,UAAU,EACR,wMAAwM;CAC3M,CAAA;AAED;;;;;;;;;GASG;AACH,MAAM,CAAC,MAAM,cAAc,GAAqC;IAC9D,kBAAkB,EAChB,yGAAyG;IAC3G,eAAe,EAAE,6CAA6C;IAC9D,0EAA0E;IAC1E,2EAA2E;IAC3E,yEAAyE;IACzE,2DAA2D;IAC3D,EAAE;IACF,wEAAwE;IACxE,oEAAoE;IACpE,EAAE;IACF,4EAA4E;IAC5E,4EAA4E;IAC5E,wEAAwE;IACxE,4EAA4E;IAC5E,4EAA4E;IAC5E,4EAA4E;IAC5E,2EAA2E;IAC3E,iEAAiE;IACjE,4EAA4E;IAC5E,oEAAoE;IACpE,4EAA4E;IAC5E,wEAAwE;IACxE,4EAA4E;IAC5E,4EAA4E;IAC5E,EAAE;IACF,oEAAoE;IACpE,iEAAiE;IACjE,wDAAwD;IACxD,MAAM,EACJ,iXAAiX;IACnX,0EAA0E;IAC1E,0EAA0E;IAC1E,gEAAgE;IAChE,gBAAgB,EAAE,EAAE;CACrB,CAAA;AAED,SAAS,UAAU,CAAC,IAAY,EAAE,UAA6B;IAC7D,MAAM,OAAO,GAAG,SAAS,CAAC,IAAI,CAAC,CAAA;IAC/B,4EAA4E;IAC5E,oEAAoE;IACpE,OAAO,UAAU,CAAC,IAAI,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,CAAA;AAC3D,CAAC"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import type { GlobNode, GlobSite } from '@nielspeter/eess';
|
|
2
|
+
import type { PathUniverse } from './path-universe.js';
|
|
3
|
+
/**
|
|
4
|
+
* Whether a glob tree can never match anything in this project.
|
|
5
|
+
*
|
|
6
|
+
* Three consecutive revisions of this function returned a false verdict, each
|
|
7
|
+
* on a shape its author had not thought to try, so it is now checked
|
|
8
|
+
* exhaustively rather than argued about:
|
|
9
|
+
* `tests/core/glob-evaluator-soundness.test.ts` enumerates every expression of
|
|
10
|
+
* at most three combinator nodes over {dead, live, opaque} and compares this
|
|
11
|
+
* implementation against plain set semantics. The requirement is **soundness**
|
|
12
|
+
* — a fault is justified only if the expression selects the empty set for
|
|
13
|
+
* every possible value of the leaves this function cannot see, since all it
|
|
14
|
+
* knows is that a dead site matches nothing.
|
|
15
|
+
*
|
|
16
|
+
* The three rules, and what each one is load-bearing for:
|
|
17
|
+
*
|
|
18
|
+
* - **A negative site is never dead.** `not(unsatisfiable)` selects
|
|
19
|
+
* *everything*; that is over-selection, not vacuity.
|
|
20
|
+
* - **An opaque leaf is never dead**, and is never dropped. See `OpaqueGlob`.
|
|
21
|
+
* - **`all` is dead if any child is; `any` is dead only if every child is.**
|
|
22
|
+
* Which is why `negateGlobs` has to invert `op` and not just polarity.
|
|
23
|
+
*/
|
|
24
|
+
export declare function isDeadGlobTree(node: GlobNode, universe: PathUniverse): boolean;
|
|
25
|
+
/**
|
|
26
|
+
* Whether one site's glob matches nothing in the project.
|
|
27
|
+
*
|
|
28
|
+
* Two independent ways to be dead, and both are needed:
|
|
29
|
+
*
|
|
30
|
+
* 1. **Syntactically** — `'src/domain/**'` on a predicate that matches
|
|
31
|
+
* absolute paths can never match, whatever the project contains.
|
|
32
|
+
* 2. **Against the universe** — anchored, well-formed, and nothing there.
|
|
33
|
+
*
|
|
34
|
+
* The syntactic check is not redundant, and leaving it out was a live false
|
|
35
|
+
* green caught by a test: the universe carries a tsconfig-relative view so
|
|
36
|
+
* that a wrong `base` cannot make a glob look UNmatched — and `'src/domain/**'`
|
|
37
|
+
* matches `src/domain` in that view while matching nothing at runtime, where
|
|
38
|
+
* `resideInFolder` reads absolute paths. Unanchored globs are the commonest
|
|
39
|
+
* real mistake and the entire subject of the 0.18.1 release, so a design that
|
|
40
|
+
* quietly calls them satisfiable defeats its own purpose.
|
|
41
|
+
*
|
|
42
|
+
* Only `file-path` and `parent-dir` are checkable; `viewsFor` returns no views
|
|
43
|
+
* for the others, and a site with no views is never dead.
|
|
44
|
+
*/
|
|
45
|
+
export declare function isDeadSite(site: GlobSite, universe: PathUniverse): boolean;
|
|
46
|
+
/** Every site in a tree, in declaration order. Opaque leaves are skipped. */
|
|
47
|
+
export declare function globSitesOf(node: GlobNode): GlobSite[];
|
|
48
|
+
//# sourceMappingURL=glob-evaluator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"glob-evaluator.d.ts","sourceRoot":"","sources":["../../src/core/glob-evaluator.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAY,QAAQ,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAA;AAEpE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA;AAItD;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,YAAY,GAAG,OAAO,CAQ9E;AAQD;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,YAAY,GAAG,OAAO,CAS1E;AAED,6EAA6E;AAC7E,wBAAgB,WAAW,CAAC,IAAI,EAAE,QAAQ,GAAG,QAAQ,EAAE,CAUtD"}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import picomatch from 'picomatch';
|
|
2
|
+
import { isGlobNode, isOpaqueGlob } from '@nielspeter/eess';
|
|
3
|
+
import { viewsFor } from './path-universe.js';
|
|
4
|
+
import { syntacticFault } from './glob-diagnosis.js';
|
|
5
|
+
/**
|
|
6
|
+
* Whether a glob tree can never match anything in this project.
|
|
7
|
+
*
|
|
8
|
+
* Three consecutive revisions of this function returned a false verdict, each
|
|
9
|
+
* on a shape its author had not thought to try, so it is now checked
|
|
10
|
+
* exhaustively rather than argued about:
|
|
11
|
+
* `tests/core/glob-evaluator-soundness.test.ts` enumerates every expression of
|
|
12
|
+
* at most three combinator nodes over {dead, live, opaque} and compares this
|
|
13
|
+
* implementation against plain set semantics. The requirement is **soundness**
|
|
14
|
+
* — a fault is justified only if the expression selects the empty set for
|
|
15
|
+
* every possible value of the leaves this function cannot see, since all it
|
|
16
|
+
* knows is that a dead site matches nothing.
|
|
17
|
+
*
|
|
18
|
+
* The three rules, and what each one is load-bearing for:
|
|
19
|
+
*
|
|
20
|
+
* - **A negative site is never dead.** `not(unsatisfiable)` selects
|
|
21
|
+
* *everything*; that is over-selection, not vacuity.
|
|
22
|
+
* - **An opaque leaf is never dead**, and is never dropped. See `OpaqueGlob`.
|
|
23
|
+
* - **`all` is dead if any child is; `any` is dead only if every child is.**
|
|
24
|
+
* Which is why `negateGlobs` has to invert `op` and not just polarity.
|
|
25
|
+
*/
|
|
26
|
+
export function isDeadGlobTree(node, universe) {
|
|
27
|
+
return node.op === 'all'
|
|
28
|
+
? node.children.some((child) => isDeadChild(child, universe))
|
|
29
|
+
: // `every` on an empty array is `true`, which would fault a rule that
|
|
30
|
+
// declares no globs at all. Unreachable, because every combinator
|
|
31
|
+
// contributes one child per input and a missing declaration becomes an
|
|
32
|
+
// opaque leaf rather than nothing — but stated, not assumed.
|
|
33
|
+
node.children.length > 0 && node.children.every((child) => isDeadChild(child, universe));
|
|
34
|
+
}
|
|
35
|
+
function isDeadChild(child, universe) {
|
|
36
|
+
if (isGlobNode(child))
|
|
37
|
+
return isDeadGlobTree(child, universe);
|
|
38
|
+
if (isOpaqueGlob(child))
|
|
39
|
+
return false;
|
|
40
|
+
return isDeadSite(child, universe);
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Whether one site's glob matches nothing in the project.
|
|
44
|
+
*
|
|
45
|
+
* Two independent ways to be dead, and both are needed:
|
|
46
|
+
*
|
|
47
|
+
* 1. **Syntactically** — `'src/domain/**'` on a predicate that matches
|
|
48
|
+
* absolute paths can never match, whatever the project contains.
|
|
49
|
+
* 2. **Against the universe** — anchored, well-formed, and nothing there.
|
|
50
|
+
*
|
|
51
|
+
* The syntactic check is not redundant, and leaving it out was a live false
|
|
52
|
+
* green caught by a test: the universe carries a tsconfig-relative view so
|
|
53
|
+
* that a wrong `base` cannot make a glob look UNmatched — and `'src/domain/**'`
|
|
54
|
+
* matches `src/domain` in that view while matching nothing at runtime, where
|
|
55
|
+
* `resideInFolder` reads absolute paths. Unanchored globs are the commonest
|
|
56
|
+
* real mistake and the entire subject of the 0.18.1 release, so a design that
|
|
57
|
+
* quietly calls them satisfiable defeats its own purpose.
|
|
58
|
+
*
|
|
59
|
+
* Only `file-path` and `parent-dir` are checkable; `viewsFor` returns no views
|
|
60
|
+
* for the others, and a site with no views is never dead.
|
|
61
|
+
*/
|
|
62
|
+
export function isDeadSite(site, universe) {
|
|
63
|
+
if ((site.polarity ?? 'positive') === 'negative')
|
|
64
|
+
return false;
|
|
65
|
+
const views = viewsFor(universe, site.kind);
|
|
66
|
+
if (views.length === 0)
|
|
67
|
+
return false;
|
|
68
|
+
if (syntacticFault(site.glob, site.kind, site.base) !== undefined)
|
|
69
|
+
return true;
|
|
70
|
+
const isMatch = picomatch(site.glob);
|
|
71
|
+
// Never `view.some(isMatch)` — picomatch reads the array index as its
|
|
72
|
+
// second argument and returns a truthy object from index 1 onwards.
|
|
73
|
+
return !views.some((view) => view.some((candidate) => isMatch(candidate)));
|
|
74
|
+
}
|
|
75
|
+
/** Every site in a tree, in declaration order. Opaque leaves are skipped. */
|
|
76
|
+
export function globSitesOf(node) {
|
|
77
|
+
const sites = [];
|
|
78
|
+
const walk = (current) => {
|
|
79
|
+
for (const child of current.children) {
|
|
80
|
+
if (isGlobNode(child))
|
|
81
|
+
walk(child);
|
|
82
|
+
else if (!isOpaqueGlob(child))
|
|
83
|
+
sites.push(child);
|
|
84
|
+
}
|
|
85
|
+
};
|
|
86
|
+
walk(node);
|
|
87
|
+
return sites;
|
|
88
|
+
}
|
|
89
|
+
//# sourceMappingURL=glob-evaluator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"glob-evaluator.js","sourceRoot":"","sources":["../../src/core/glob-evaluator.ts"],"names":[],"mappings":"AAAA,OAAO,SAAS,MAAM,WAAW,CAAA;AAEjC,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAA;AAE3D,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAA;AAC7C,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAA;AAEpD;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,UAAU,cAAc,CAAC,IAAc,EAAE,QAAsB;IACnE,OAAO,IAAI,CAAC,EAAE,KAAK,KAAK;QACtB,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,WAAW,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC;QAC7D,CAAC,CAAC,qEAAqE;YACrE,kEAAkE;YAClE,uEAAuE;YACvE,6DAA6D;YAC7D,IAAI,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,WAAW,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC,CAAA;AAC9F,CAAC;AAED,SAAS,WAAW,CAAC,KAAoC,EAAE,QAAsB;IAC/E,IAAI,UAAU,CAAC,KAAK,CAAC;QAAE,OAAO,cAAc,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAA;IAC7D,IAAI,YAAY,CAAC,KAAK,CAAC;QAAE,OAAO,KAAK,CAAA;IACrC,OAAO,UAAU,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAA;AACpC,CAAC;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,UAAU,UAAU,CAAC,IAAc,EAAE,QAAsB;IAC/D,IAAI,CAAC,IAAI,CAAC,QAAQ,IAAI,UAAU,CAAC,KAAK,UAAU;QAAE,OAAO,KAAK,CAAA;IAC9D,MAAM,KAAK,GAAG,QAAQ,CAAC,QAAQ,EAAE,IAAI,CAAC,IAAI,CAAC,CAAA;IAC3C,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,KAAK,CAAA;IACpC,IAAI,cAAc,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC,KAAK,SAAS;QAAE,OAAO,IAAI,CAAA;IAC9E,MAAM,OAAO,GAAG,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;IACpC,sEAAsE;IACtE,oEAAoE;IACpE,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,CAAA;AAC5E,CAAC;AAED,6EAA6E;AAC7E,MAAM,UAAU,WAAW,CAAC,IAAc;IACxC,MAAM,KAAK,GAAe,EAAE,CAAA;IAC5B,MAAM,IAAI,GAAG,CAAC,OAAiB,EAAQ,EAAE;QACvC,KAAK,MAAM,KAAK,IAAI,OAAO,CAAC,QAAQ,EAAE,CAAC;YACrC,IAAI,UAAU,CAAC,KAAK,CAAC;gBAAE,IAAI,CAAC,KAAK,CAAC,CAAA;iBAC7B,IAAI,CAAC,YAAY,CAAC,KAAK,CAAC;gBAAE,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;QAClD,CAAC;IACH,CAAC,CAAA;IACD,IAAI,CAAC,IAAI,CAAC,CAAA;IACV,OAAO,KAAK,CAAA;AACd,CAAC"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import type picomatch from 'picomatch';
|
|
2
|
+
import type { ImportDeclaration } from 'ts-morph';
|
|
3
|
+
/**
|
|
4
|
+
* Every string an import glob may be matched against, primary first.
|
|
5
|
+
*
|
|
6
|
+
* Non-empty by construction, and `[0]` is the primary — see `importCandidates`.
|
|
7
|
+
*/
|
|
8
|
+
type ImportCandidates = readonly [primary: string, ...alternates: string[]];
|
|
9
|
+
/**
|
|
10
|
+
* Every string a glob may legitimately be matched against for one import.
|
|
11
|
+
*
|
|
12
|
+
* The old rule was "the resolved path, **or** the raw specifier if it does not
|
|
13
|
+
* resolve" — which is backwards. An installed package with types resolves, so
|
|
14
|
+
* `notImportFrom('fastify')` was compared against
|
|
15
|
+
* `/…/node_modules/@types/fastify/index.d.ts` and never matched. The documented
|
|
16
|
+
* way to ban a dependency worked only on dependencies you had not installed
|
|
17
|
+
* (bug 0014).
|
|
18
|
+
*
|
|
19
|
+
* So: match against **both**, and a glob matches the import if it matches
|
|
20
|
+
* either. Path globs keep working, because the resolved path is still tested.
|
|
21
|
+
*
|
|
22
|
+
* The specifier is offered only when it is **non-relative**. A relative
|
|
23
|
+
* specifier (`'../services/foo.js'`) carries no information the resolved path
|
|
24
|
+
* lacks, and testing it as a string would let `'**\/services/**'` match an
|
|
25
|
+
* import that resolves somewhere else entirely. Bare package names and path
|
|
26
|
+
* aliases (`'@/lib/x'`) are the cases this exists for, and both are
|
|
27
|
+
* non-relative.
|
|
28
|
+
*
|
|
29
|
+
* **`[0]` is the primary candidate, and it is exactly what the old
|
|
30
|
+
* `resolveImportPath` returned.** That is load-bearing rather than incidental:
|
|
31
|
+
* violation messages interpolate it, `hashViolation` hashes the message, and a
|
|
32
|
+
* changed message silently invalidates every baselined dependency violation.
|
|
33
|
+
* Keeping the primary stable means only genuinely *new* findings get new text.
|
|
34
|
+
* A test asserts the equivalence across the whole fixture corpus.
|
|
35
|
+
*/
|
|
36
|
+
export declare function importCandidates(decl: ImportDeclaration): ImportCandidates;
|
|
37
|
+
/**
|
|
38
|
+
* The same candidates, from the two values a `ModuleEdge` already carries.
|
|
39
|
+
*
|
|
40
|
+
* This is why `ModuleEdge` has **no `candidates` field** (plan 0071 §1):
|
|
41
|
+
* candidates are a function of `specifier` and `resolvedPath`, so storing them
|
|
42
|
+
* beside their own two inputs would be two representations of one fact, free to
|
|
43
|
+
* disagree. The function is exposed instead.
|
|
44
|
+
*
|
|
45
|
+
* `importCandidates` above is now a thin wrapper over this, which is what lets
|
|
46
|
+
* `tests/core/module-edges-corpus.test.ts` compare the two derivations across
|
|
47
|
+
* the whole repository: same rule, reached from a declaration on one side and
|
|
48
|
+
* from an edge on the other.
|
|
49
|
+
*/
|
|
50
|
+
export declare function candidatesFor(specifier: string, resolvedPath: string | undefined, projectRoot?: string): ImportCandidates;
|
|
51
|
+
/**
|
|
52
|
+
* The first candidate matching any matcher, or `undefined` if none do.
|
|
53
|
+
*
|
|
54
|
+
* "First" is what keeps messages stable: the primary is tested before the
|
|
55
|
+
* specifier, so an import that already matched on its resolved path reports
|
|
56
|
+
* the same string it reported before this fix.
|
|
57
|
+
*/
|
|
58
|
+
export declare function matchedCandidate(candidates: ImportCandidates, matchers: readonly picomatch.Matcher[]): string | undefined;
|
|
59
|
+
export {};
|
|
60
|
+
//# sourceMappingURL=import-candidates.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"import-candidates.d.ts","sourceRoot":"","sources":["../../src/core/import-candidates.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,SAAS,MAAM,WAAW,CAAA;AACtC,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAA;AAEjD;;;;GAIG;AACH,KAAK,gBAAgB,GAAG,SAAS,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,UAAU,EAAE,MAAM,EAAE,CAAC,CAAA;AAE3E;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,iBAAiB,GAAG,gBAAgB,CAK1E;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,aAAa,CAC3B,SAAS,EAAE,MAAM,EACjB,YAAY,EAAE,MAAM,GAAG,SAAS,EAChC,WAAW,CAAC,EAAE,MAAM,GACnB,gBAAgB,CAsBlB;AASD;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAC9B,UAAU,EAAE,gBAAgB,EAC5B,QAAQ,EAAE,SAAS,SAAS,CAAC,OAAO,EAAE,GACrC,MAAM,GAAG,SAAS,CAIpB"}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Every string a glob may legitimately be matched against for one import.
|
|
3
|
+
*
|
|
4
|
+
* The old rule was "the resolved path, **or** the raw specifier if it does not
|
|
5
|
+
* resolve" — which is backwards. An installed package with types resolves, so
|
|
6
|
+
* `notImportFrom('fastify')` was compared against
|
|
7
|
+
* `/…/node_modules/@types/fastify/index.d.ts` and never matched. The documented
|
|
8
|
+
* way to ban a dependency worked only on dependencies you had not installed
|
|
9
|
+
* (bug 0014).
|
|
10
|
+
*
|
|
11
|
+
* So: match against **both**, and a glob matches the import if it matches
|
|
12
|
+
* either. Path globs keep working, because the resolved path is still tested.
|
|
13
|
+
*
|
|
14
|
+
* The specifier is offered only when it is **non-relative**. A relative
|
|
15
|
+
* specifier (`'../services/foo.js'`) carries no information the resolved path
|
|
16
|
+
* lacks, and testing it as a string would let `'**\/services/**'` match an
|
|
17
|
+
* import that resolves somewhere else entirely. Bare package names and path
|
|
18
|
+
* aliases (`'@/lib/x'`) are the cases this exists for, and both are
|
|
19
|
+
* non-relative.
|
|
20
|
+
*
|
|
21
|
+
* **`[0]` is the primary candidate, and it is exactly what the old
|
|
22
|
+
* `resolveImportPath` returned.** That is load-bearing rather than incidental:
|
|
23
|
+
* violation messages interpolate it, `hashViolation` hashes the message, and a
|
|
24
|
+
* changed message silently invalidates every baselined dependency violation.
|
|
25
|
+
* Keeping the primary stable means only genuinely *new* findings get new text.
|
|
26
|
+
* A test asserts the equivalence across the whole fixture corpus.
|
|
27
|
+
*/
|
|
28
|
+
// eess-exclude eess/no-unused-exports: consumed by the test suite; the build tsconfig this gate reads excludes tests, so `src` is the only usage it can see
|
|
29
|
+
export function importCandidates(decl) {
|
|
30
|
+
return candidatesFor(decl.getModuleSpecifierValue(), decl.getModuleSpecifierSourceFile()?.getFilePath());
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* The same candidates, from the two values a `ModuleEdge` already carries.
|
|
34
|
+
*
|
|
35
|
+
* This is why `ModuleEdge` has **no `candidates` field** (plan 0071 §1):
|
|
36
|
+
* candidates are a function of `specifier` and `resolvedPath`, so storing them
|
|
37
|
+
* beside their own two inputs would be two representations of one fact, free to
|
|
38
|
+
* disagree. The function is exposed instead.
|
|
39
|
+
*
|
|
40
|
+
* `importCandidates` above is now a thin wrapper over this, which is what lets
|
|
41
|
+
* `tests/core/module-edges-corpus.test.ts` compare the two derivations across
|
|
42
|
+
* the whole repository: same rule, reached from a declaration on one side and
|
|
43
|
+
* from an edge on the other.
|
|
44
|
+
*/
|
|
45
|
+
export function candidatesFor(specifier, resolvedPath, projectRoot) {
|
|
46
|
+
if (resolvedPath === undefined)
|
|
47
|
+
return [specifier];
|
|
48
|
+
const alternates = isRelativeSpecifier(specifier) ? [] : [specifier];
|
|
49
|
+
// The resolved path named from the project root, **appended** — bug 0037.
|
|
50
|
+
//
|
|
51
|
+
// An import glob is matched against an ABSOLUTE resolved path, so a
|
|
52
|
+
// project-relative one could never match it: measured,
|
|
53
|
+
// `layeredArchitecture({ shared: ['src/shared/**'] })` reported a violation
|
|
54
|
+
// on a correct architecture, because `shared` also reaches
|
|
55
|
+
// `onlyImportFrom(...)`. A **false red**, with no configuration finding and a
|
|
56
|
+
// silent `doctor` — worse than a false green for an agent, which will edit
|
|
57
|
+
// real imports to satisfy a broken allowlist.
|
|
58
|
+
//
|
|
59
|
+
// Appended, never prepended: `[0]` is the primary candidate that violation
|
|
60
|
+
// messages interpolate and `hashViolation` hashes, so putting the relative
|
|
61
|
+
// form first would rewrite every baselined dependency finding.
|
|
62
|
+
//
|
|
63
|
+
// Bare specifiers are untouched — they have no `resolvedPath`, and returning
|
|
64
|
+
// early above is what keeps `notImportFrom('fastify')` working (bug 0014).
|
|
65
|
+
const fromRoot = relativeTo(projectRoot, resolvedPath);
|
|
66
|
+
if (fromRoot !== undefined)
|
|
67
|
+
alternates.push(fromRoot);
|
|
68
|
+
return [resolvedPath, ...alternates];
|
|
69
|
+
}
|
|
70
|
+
/** `absolutePath` named from `root`, or `undefined` when it is outside or unknown. */
|
|
71
|
+
function relativeTo(root, absolutePath) {
|
|
72
|
+
if (root === undefined)
|
|
73
|
+
return undefined;
|
|
74
|
+
const prefix = root === '/' ? '/' : `${root}/`;
|
|
75
|
+
return absolutePath.startsWith(prefix) ? absolutePath.slice(prefix.length) : undefined;
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* The first candidate matching any matcher, or `undefined` if none do.
|
|
79
|
+
*
|
|
80
|
+
* "First" is what keeps messages stable: the primary is tested before the
|
|
81
|
+
* specifier, so an import that already matched on its resolved path reports
|
|
82
|
+
* the same string it reported before this fix.
|
|
83
|
+
*/
|
|
84
|
+
export function matchedCandidate(candidates, matchers) {
|
|
85
|
+
// Never `candidates.some(matcher)` — picomatch reads the array index as its
|
|
86
|
+
// second argument and returns a truthy object from index 1 on.
|
|
87
|
+
return candidates.find((candidate) => matchers.some((isMatch) => isMatch(candidate)));
|
|
88
|
+
}
|
|
89
|
+
/** A specifier that names a location relative to the importing file. */
|
|
90
|
+
function isRelativeSpecifier(specifier) {
|
|
91
|
+
return specifier.startsWith('.') || specifier.startsWith('/');
|
|
92
|
+
}
|
|
93
|
+
//# sourceMappingURL=import-candidates.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"import-candidates.js","sourceRoot":"","sources":["../../src/core/import-candidates.ts"],"names":[],"mappings":"AAUA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,4JAA4J;AAC5J,MAAM,UAAU,gBAAgB,CAAC,IAAuB;IACtD,OAAO,aAAa,CAClB,IAAI,CAAC,uBAAuB,EAAE,EAC9B,IAAI,CAAC,4BAA4B,EAAE,EAAE,WAAW,EAAE,CACnD,CAAA;AACH,CAAC;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,aAAa,CAC3B,SAAiB,EACjB,YAAgC,EAChC,WAAoB;IAEpB,IAAI,YAAY,KAAK,SAAS;QAAE,OAAO,CAAC,SAAS,CAAC,CAAA;IAClD,MAAM,UAAU,GAAa,mBAAmB,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAA;IAC9E,0EAA0E;IAC1E,EAAE;IACF,oEAAoE;IACpE,uDAAuD;IACvD,4EAA4E;IAC5E,2DAA2D;IAC3D,8EAA8E;IAC9E,2EAA2E;IAC3E,8CAA8C;IAC9C,EAAE;IACF,2EAA2E;IAC3E,2EAA2E;IAC3E,+DAA+D;IAC/D,EAAE;IACF,6EAA6E;IAC7E,2EAA2E;IAC3E,MAAM,QAAQ,GAAG,UAAU,CAAC,WAAW,EAAE,YAAY,CAAC,CAAA;IACtD,IAAI,QAAQ,KAAK,SAAS;QAAE,UAAU,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAA;IACrD,OAAO,CAAC,YAAY,EAAE,GAAG,UAAU,CAAC,CAAA;AACtC,CAAC;AAED,sFAAsF;AACtF,SAAS,UAAU,CAAC,IAAwB,EAAE,YAAoB;IAChE,IAAI,IAAI,KAAK,SAAS;QAAE,OAAO,SAAS,CAAA;IACxC,MAAM,MAAM,GAAG,IAAI,KAAK,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,IAAI,GAAG,CAAA;IAC9C,OAAO,YAAY,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,SAAS,CAAA;AACxF,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,gBAAgB,CAC9B,UAA4B,EAC5B,QAAsC;IAEtC,4EAA4E;IAC5E,+DAA+D;IAC/D,OAAO,UAAU,CAAC,IAAI,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,CAAA;AACvF,CAAC;AAED,wEAAwE;AACxE,SAAS,mBAAmB,CAAC,SAAiB;IAC5C,OAAO,SAAS,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,SAAS,CAAC,UAAU,CAAC,GAAG,CAAC,CAAA;AAC/D,CAAC"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { ImportDeclaration } from 'ts-morph';
|
|
1
|
+
import type { ExportDeclaration, ImportDeclaration } from 'ts-morph';
|
|
2
2
|
/**
|
|
3
3
|
* Options for import-related conditions and predicates.
|
|
4
4
|
*/
|
|
@@ -10,7 +10,11 @@ export interface ImportOptions {
|
|
|
10
10
|
* Type-only imports are erased at compile time and create no runtime dependency.
|
|
11
11
|
* Useful for layer isolation rules where type-sharing is acceptable.
|
|
12
12
|
*
|
|
13
|
-
* Default: false
|
|
13
|
+
* Default: **per condition.** `false` — count every import — for `dependOn`,
|
|
14
|
+
* `importFrom`, `notImportFrom`, `onlyImportFrom`, `notDependOn` and
|
|
15
|
+
* `respectLayerOrder`, which ask whether the code is *coupled*. `true` for
|
|
16
|
+
* `beFreeOfCycles`, which asks whether the module is *evaluated*: an erased import
|
|
17
|
+
* cannot contribute to an initialization cycle. See `docs/slices.md`.
|
|
14
18
|
*/
|
|
15
19
|
ignoreTypeImports?: boolean;
|
|
16
20
|
}
|
|
@@ -29,4 +33,53 @@ export interface ImportOptions {
|
|
|
29
33
|
* - `import * as Foo from '...'` (namespace import is runtime)
|
|
30
34
|
*/
|
|
31
35
|
export declare function isTypeOnlyImport(decl: ImportDeclaration): boolean;
|
|
36
|
+
/**
|
|
37
|
+
* Check whether a re-export is purely type-only (no runtime dependency).
|
|
38
|
+
*
|
|
39
|
+
* The `export … from` analogue of {@link isTypeOnlyImport}, and **both halves of
|
|
40
|
+
* the disjunction are needed** — measured, the two spellings put the flag in
|
|
41
|
+
* different places:
|
|
42
|
+
*
|
|
43
|
+
* | form | `decl.isTypeOnly()` | specifiers |
|
|
44
|
+
* | ------------------------------- | ------------------- | ---------- |
|
|
45
|
+
* | `export type { X } from 's'` | **true** | false |
|
|
46
|
+
* | `export { type X } from 's'` | false | **true** |
|
|
47
|
+
* | `export type * from 's'` | **true** | (none) |
|
|
48
|
+
* | `export { X } from 's'` | false | false |
|
|
49
|
+
*
|
|
50
|
+
* No default or namespace analogue exists, verified: there is no way to write a
|
|
51
|
+
* re-export that binds a runtime value while every named specifier is
|
|
52
|
+
* type-only, so this needs none of {@link isTypeOnlyImport}'s guards. A bare
|
|
53
|
+
* `export * from 's'` has no named specifiers and is runtime, which is why the
|
|
54
|
+
* second half requires a non-empty list.
|
|
55
|
+
*/
|
|
56
|
+
export declare function isTypeOnlyReExport(decl: ExportDeclaration): boolean;
|
|
57
|
+
/**
|
|
58
|
+
* Split a variadic glob API's arguments, without a type assertion.
|
|
59
|
+
*
|
|
60
|
+
* Five entry points take `...args: [string[], ImportOptions] | string[]` —
|
|
61
|
+
* `onlyImportFrom`, `notImportFrom`, `dependOn`, `importFrom`, `importFromAny` —
|
|
62
|
+
* so a caller can write either `f('a', 'b')` or `f(['a', 'b'], { … })`. TypeScript
|
|
63
|
+
* cannot narrow a tuple-union rest parameter from `Array.isArray(args[0])`, which
|
|
64
|
+
* is true and was the stated reason for **ten** `as` casts across three files:
|
|
65
|
+
*
|
|
66
|
+
* ```ts
|
|
67
|
+
* const globs: string[] = Array.isArray(args[0]) ? args[0] : (args as string[])
|
|
68
|
+
* const options = Array.isArray(args[0]) && args.length > 1 ? (args[1] as ImportOptions) : undefined
|
|
69
|
+
* ```
|
|
70
|
+
*
|
|
71
|
+
* [ADR-005](../../../../adr/005-no-any-no-type-assertions.md) prescribes a type guard,
|
|
72
|
+
* and a guard does narrow it: `.filter((a): a is string => …)` produces `string[]`
|
|
73
|
+
* with no assertion, and `typeof second === 'object'` narrows the options. The
|
|
74
|
+
* casts were avoidable; only the direct narrowing was not.
|
|
75
|
+
*
|
|
76
|
+
* One owner rather than five copies, which is the other half. The dispatch was
|
|
77
|
+
* duplicated five times, and a duplicated predicate in this repo has already
|
|
78
|
+
* caused a measurement error once —
|
|
79
|
+
* [ts-archunit bug 0044](https://github.com/nielspeter/ts-archunit/blob/main/bugs/fixed/0044-an-inline-exclusion-comment-has-no-feedback-channel.md).
|
|
80
|
+
*/
|
|
81
|
+
export declare function splitGlobArgs(args: readonly (string[] | ImportOptions | string)[]): {
|
|
82
|
+
globs: string[];
|
|
83
|
+
options: ImportOptions | undefined;
|
|
84
|
+
};
|
|
32
85
|
//# sourceMappingURL=import-options.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"import-options.d.ts","sourceRoot":"","sources":["../../src/core/import-options.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAA;
|
|
1
|
+
{"version":3,"file":"import-options.d.ts","sourceRoot":"","sources":["../../src/core/import-options.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAA;AAEpE;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B;;;;;;;;;;;;OAYG;IACH,iBAAiB,CAAC,EAAE,OAAO,CAAA;CAC5B;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,iBAAiB,GAAG,OAAO,CAUjE;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,iBAAiB,GAAG,OAAO,CAInE;AAED;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,SAAS,CAAC,MAAM,EAAE,GAAG,aAAa,GAAG,MAAM,CAAC,EAAE,GAAG;IACnF,KAAK,EAAE,MAAM,EAAE,CAAA;IACf,OAAO,EAAE,aAAa,GAAG,SAAS,CAAA;CACnC,CAcA"}
|