@nielspeter/eess-ts 0.1.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/LICENSE +21 -0
- package/README.md +364 -0
- package/dist/builders/call-rule-builder.d.ts +199 -0
- package/dist/builders/call-rule-builder.d.ts.map +1 -0
- package/dist/builders/call-rule-builder.js +254 -0
- package/dist/builders/call-rule-builder.js.map +1 -0
- package/dist/builders/class-rule-builder.d.ts +136 -0
- package/dist/builders/class-rule-builder.d.ts.map +1 -0
- package/dist/builders/class-rule-builder.js +253 -0
- package/dist/builders/class-rule-builder.js.map +1 -0
- package/dist/builders/cross-layer-builder.d.ts +96 -0
- package/dist/builders/cross-layer-builder.d.ts.map +1 -0
- package/dist/builders/cross-layer-builder.js +172 -0
- package/dist/builders/cross-layer-builder.js.map +1 -0
- package/dist/builders/function-rule-builder.d.ts +198 -0
- package/dist/builders/function-rule-builder.d.ts.map +1 -0
- package/dist/builders/function-rule-builder.js +287 -0
- package/dist/builders/function-rule-builder.js.map +1 -0
- package/dist/builders/jsx-rule-builder.d.ts +113 -0
- package/dist/builders/jsx-rule-builder.d.ts.map +1 -0
- package/dist/builders/jsx-rule-builder.js +150 -0
- package/dist/builders/jsx-rule-builder.js.map +1 -0
- package/dist/builders/module-rule-builder.d.ts +159 -0
- package/dist/builders/module-rule-builder.d.ts.map +1 -0
- package/dist/builders/module-rule-builder.js +237 -0
- package/dist/builders/module-rule-builder.js.map +1 -0
- package/dist/builders/scoped-function-rule-builder.d.ts +21 -0
- package/dist/builders/scoped-function-rule-builder.d.ts.map +1 -0
- package/dist/builders/scoped-function-rule-builder.js +26 -0
- package/dist/builders/scoped-function-rule-builder.js.map +1 -0
- package/dist/builders/slice-rule-builder.d.ts +85 -0
- package/dist/builders/slice-rule-builder.d.ts.map +1 -0
- package/dist/builders/slice-rule-builder.js +134 -0
- package/dist/builders/slice-rule-builder.js.map +1 -0
- package/dist/builders/type-rule-builder.d.ts +103 -0
- package/dist/builders/type-rule-builder.d.ts.map +1 -0
- package/dist/builders/type-rule-builder.js +170 -0
- package/dist/builders/type-rule-builder.js.map +1 -0
- package/dist/cli/bin.d.ts +3 -0
- package/dist/cli/bin.d.ts.map +1 -0
- package/dist/cli/bin.js +4 -0
- package/dist/cli/bin.js.map +1 -0
- package/dist/cli/commands/baseline.d.ts +11 -0
- package/dist/cli/commands/baseline.d.ts.map +1 -0
- package/dist/cli/commands/baseline.js +16 -0
- package/dist/cli/commands/baseline.js.map +1 -0
- package/dist/cli/commands/check.d.ts +21 -0
- package/dist/cli/commands/check.d.ts.map +1 -0
- package/dist/cli/commands/check.js +94 -0
- package/dist/cli/commands/check.js.map +1 -0
- package/dist/cli/commands/explain.d.ts +9 -0
- package/dist/cli/commands/explain.d.ts.map +1 -0
- package/dist/cli/commands/explain.js +49 -0
- package/dist/cli/commands/explain.js.map +1 -0
- package/dist/cli/config.d.ts +31 -0
- package/dist/cli/config.d.ts.map +1 -0
- package/dist/cli/config.js +20 -0
- package/dist/cli/config.js.map +1 -0
- package/dist/cli/index.d.ts +21 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +168 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/load-rules.d.ts +20 -0
- package/dist/cli/load-rules.d.ts.map +1 -0
- package/dist/cli/load-rules.js +97 -0
- package/dist/cli/load-rules.js.map +1 -0
- package/dist/cli/resolve-config.d.ts +11 -0
- package/dist/cli/resolve-config.d.ts.map +1 -0
- package/dist/cli/resolve-config.js +61 -0
- package/dist/cli/resolve-config.js.map +1 -0
- package/dist/cli/watch.d.ts +49 -0
- package/dist/cli/watch.d.ts.map +1 -0
- package/dist/cli/watch.js +138 -0
- package/dist/cli/watch.js.map +1 -0
- package/dist/conditions/body-analysis-function.d.ts +23 -0
- package/dist/conditions/body-analysis-function.d.ts.map +1 -0
- package/dist/conditions/body-analysis-function.js +103 -0
- package/dist/conditions/body-analysis-function.js.map +1 -0
- package/dist/conditions/body-analysis-module.d.ts +27 -0
- package/dist/conditions/body-analysis-module.d.ts.map +1 -0
- package/dist/conditions/body-analysis-module.js +99 -0
- package/dist/conditions/body-analysis-module.js.map +1 -0
- package/dist/conditions/body-analysis.d.ts +34 -0
- package/dist/conditions/body-analysis.d.ts.map +1 -0
- package/dist/conditions/body-analysis.js +95 -0
- package/dist/conditions/body-analysis.js.map +1 -0
- package/dist/conditions/call.d.ts +62 -0
- package/dist/conditions/call.d.ts.map +1 -0
- package/dist/conditions/call.js +267 -0
- package/dist/conditions/call.js.map +1 -0
- package/dist/conditions/catch-analysis.d.ts +31 -0
- package/dist/conditions/catch-analysis.d.ts.map +1 -0
- package/dist/conditions/catch-analysis.js +78 -0
- package/dist/conditions/catch-analysis.js.map +1 -0
- package/dist/conditions/class.d.ts +33 -0
- package/dist/conditions/class.d.ts.map +1 -0
- package/dist/conditions/class.js +110 -0
- package/dist/conditions/class.js.map +1 -0
- package/dist/conditions/cross-layer.d.ts +28 -0
- package/dist/conditions/cross-layer.d.ts.map +1 -0
- package/dist/conditions/cross-layer.js +105 -0
- package/dist/conditions/cross-layer.js.map +1 -0
- package/dist/conditions/dependency.d.ts +73 -0
- package/dist/conditions/dependency.d.ts.map +1 -0
- package/dist/conditions/dependency.js +177 -0
- package/dist/conditions/dependency.js.map +1 -0
- package/dist/conditions/exports.d.ts +33 -0
- package/dist/conditions/exports.d.ts.map +1 -0
- package/dist/conditions/exports.js +101 -0
- package/dist/conditions/exports.js.map +1 -0
- package/dist/conditions/function.d.ts +79 -0
- package/dist/conditions/function.d.ts.map +1 -0
- package/dist/conditions/function.js +167 -0
- package/dist/conditions/function.js.map +1 -0
- package/dist/conditions/helpers.d.ts +14 -0
- package/dist/conditions/helpers.d.ts.map +1 -0
- package/dist/conditions/helpers.js +26 -0
- package/dist/conditions/helpers.js.map +1 -0
- package/dist/conditions/jsx.d.ts +40 -0
- package/dist/conditions/jsx.d.ts.map +1 -0
- package/dist/conditions/jsx.js +133 -0
- package/dist/conditions/jsx.js.map +1 -0
- package/dist/conditions/members.d.ts +74 -0
- package/dist/conditions/members.d.ts.map +1 -0
- package/dist/conditions/members.js +224 -0
- package/dist/conditions/members.js.map +1 -0
- package/dist/conditions/pattern.d.ts +20 -0
- package/dist/conditions/pattern.d.ts.map +1 -0
- package/dist/conditions/pattern.js +108 -0
- package/dist/conditions/pattern.js.map +1 -0
- package/dist/conditions/reverse-dependency.d.ts +28 -0
- package/dist/conditions/reverse-dependency.d.ts.map +1 -0
- package/dist/conditions/reverse-dependency.js +275 -0
- package/dist/conditions/reverse-dependency.js.map +1 -0
- package/dist/conditions/slice.d.ts +49 -0
- package/dist/conditions/slice.d.ts.map +1 -0
- package/dist/conditions/slice.js +153 -0
- package/dist/conditions/slice.js.map +1 -0
- package/dist/conditions/structural.d.ts +58 -0
- package/dist/conditions/structural.d.ts.map +1 -0
- package/dist/conditions/structural.js +102 -0
- package/dist/conditions/structural.js.map +1 -0
- package/dist/conditions/type-level.d.ts +29 -0
- package/dist/conditions/type-level.d.ts.map +1 -0
- package/dist/conditions/type-level.js +48 -0
- package/dist/conditions/type-level.js.map +1 -0
- package/dist/core/import-options.d.ts +32 -0
- package/dist/core/import-options.d.ts.map +1 -0
- package/dist/core/import-options.js +29 -0
- package/dist/core/import-options.js.map +1 -0
- package/dist/core/module-dependencies.d.ts +28 -0
- package/dist/core/module-dependencies.d.ts.map +1 -0
- package/dist/core/module-dependencies.js +35 -0
- package/dist/core/module-dependencies.js.map +1 -0
- package/dist/core/pair-condition.d.ts +10 -0
- package/dist/core/pair-condition.d.ts.map +1 -0
- package/dist/core/pair-condition.js +2 -0
- package/dist/core/pair-condition.js.map +1 -0
- package/dist/core/project.d.ts +68 -0
- package/dist/core/project.d.ts.map +1 -0
- package/dist/core/project.js +127 -0
- package/dist/core/project.js.map +1 -0
- package/dist/core/type-matcher.d.ts +10 -0
- package/dist/core/type-matcher.d.ts.map +1 -0
- package/dist/core/type-matcher.js +2 -0
- package/dist/core/type-matcher.js.map +1 -0
- package/dist/core/violation.d.ts +38 -0
- package/dist/core/violation.d.ts.map +1 -0
- package/dist/core/violation.js +130 -0
- package/dist/core/violation.js.map +1 -0
- package/dist/graphql/index.d.ts +76 -0
- package/dist/graphql/index.d.ts.map +1 -0
- package/dist/graphql/index.js +108 -0
- package/dist/graphql/index.js.map +1 -0
- package/dist/graphql/resolver-rule-builder.d.ts +75 -0
- package/dist/graphql/resolver-rule-builder.d.ts.map +1 -0
- package/dist/graphql/resolver-rule-builder.js +146 -0
- package/dist/graphql/resolver-rule-builder.js.map +1 -0
- package/dist/graphql/schema-conditions.d.ts +31 -0
- package/dist/graphql/schema-conditions.d.ts.map +1 -0
- package/dist/graphql/schema-conditions.js +119 -0
- package/dist/graphql/schema-conditions.js.map +1 -0
- package/dist/graphql/schema-loader.d.ts +75 -0
- package/dist/graphql/schema-loader.d.ts.map +1 -0
- package/dist/graphql/schema-loader.js +113 -0
- package/dist/graphql/schema-loader.js.map +1 -0
- package/dist/graphql/schema-predicates.d.ts +42 -0
- package/dist/graphql/schema-predicates.d.ts.map +1 -0
- package/dist/graphql/schema-predicates.js +74 -0
- package/dist/graphql/schema-predicates.js.map +1 -0
- package/dist/graphql/schema-rule-builder.d.ts +74 -0
- package/dist/graphql/schema-rule-builder.d.ts.map +1 -0
- package/dist/graphql/schema-rule-builder.js +188 -0
- package/dist/graphql/schema-rule-builder.js.map +1 -0
- package/dist/helpers/body-traversal.d.ts +58 -0
- package/dist/helpers/body-traversal.d.ts.map +1 -0
- package/dist/helpers/body-traversal.js +180 -0
- package/dist/helpers/body-traversal.js.map +1 -0
- package/dist/helpers/callback-extractor.d.ts +28 -0
- package/dist/helpers/callback-extractor.d.ts.map +1 -0
- package/dist/helpers/callback-extractor.js +159 -0
- package/dist/helpers/callback-extractor.js.map +1 -0
- package/dist/helpers/complexity.d.ts +26 -0
- package/dist/helpers/complexity.d.ts.map +1 -0
- package/dist/helpers/complexity.js +64 -0
- package/dist/helpers/complexity.js.map +1 -0
- package/dist/helpers/matchers.d.ts +206 -0
- package/dist/helpers/matchers.d.ts.map +1 -0
- package/dist/helpers/matchers.js +470 -0
- package/dist/helpers/matchers.js.map +1 -0
- package/dist/helpers/pattern.d.ts +37 -0
- package/dist/helpers/pattern.d.ts.map +1 -0
- package/dist/helpers/pattern.js +22 -0
- package/dist/helpers/pattern.js.map +1 -0
- package/dist/helpers/slice-graph.d.ts +32 -0
- package/dist/helpers/slice-graph.d.ts.map +1 -0
- package/dist/helpers/slice-graph.js +89 -0
- package/dist/helpers/slice-graph.js.map +1 -0
- package/dist/helpers/tarjan.d.ts +21 -0
- package/dist/helpers/tarjan.d.ts.map +1 -0
- package/dist/helpers/tarjan.js +71 -0
- package/dist/helpers/tarjan.js.map +1 -0
- package/dist/helpers/type-matchers.d.ts +67 -0
- package/dist/helpers/type-matchers.d.ts.map +1 -0
- package/dist/helpers/type-matchers.js +108 -0
- package/dist/helpers/type-matchers.js.map +1 -0
- package/dist/helpers/within.d.ts +41 -0
- package/dist/helpers/within.d.ts.map +1 -0
- package/dist/helpers/within.js +32 -0
- package/dist/helpers/within.js.map +1 -0
- package/dist/index.d.ts +101 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +116 -0
- package/dist/index.js.map +1 -0
- package/dist/models/arch-call.d.ts +83 -0
- package/dist/models/arch-call.d.ts.map +1 -0
- package/dist/models/arch-call.js +90 -0
- package/dist/models/arch-call.js.map +1 -0
- package/dist/models/arch-function.d.ts +76 -0
- package/dist/models/arch-function.d.ts.map +1 -0
- package/dist/models/arch-function.js +122 -0
- package/dist/models/arch-function.js.map +1 -0
- package/dist/models/arch-jsx-element.d.ts +75 -0
- package/dist/models/arch-jsx-element.d.ts.map +1 -0
- package/dist/models/arch-jsx-element.js +231 -0
- package/dist/models/arch-jsx-element.js.map +1 -0
- package/dist/models/cross-layer.d.ts +15 -0
- package/dist/models/cross-layer.d.ts.map +1 -0
- package/dist/models/cross-layer.js +2 -0
- package/dist/models/cross-layer.js.map +1 -0
- package/dist/models/slice.d.ts +60 -0
- package/dist/models/slice.d.ts.map +1 -0
- package/dist/models/slice.js +89 -0
- package/dist/models/slice.js.map +1 -0
- package/dist/predicates/call.d.ts +49 -0
- package/dist/predicates/call.d.ts.map +1 -0
- package/dist/predicates/call.js +115 -0
- package/dist/predicates/call.js.map +1 -0
- package/dist/predicates/class.d.ts +42 -0
- package/dist/predicates/class.d.ts.map +1 -0
- package/dist/predicates/class.js +83 -0
- package/dist/predicates/class.js.map +1 -0
- package/dist/predicates/function.d.ts +81 -0
- package/dist/predicates/function.d.ts.map +1 -0
- package/dist/predicates/function.js +157 -0
- package/dist/predicates/function.js.map +1 -0
- package/dist/predicates/identity.d.ts +55 -0
- package/dist/predicates/identity.d.ts.map +1 -0
- package/dist/predicates/identity.js +96 -0
- package/dist/predicates/identity.js.map +1 -0
- package/dist/predicates/index.d.ts +4 -0
- package/dist/predicates/index.d.ts.map +1 -0
- package/dist/predicates/index.js +3 -0
- package/dist/predicates/index.js.map +1 -0
- package/dist/predicates/jsx.d.ts +41 -0
- package/dist/predicates/jsx.d.ts.map +1 -0
- package/dist/predicates/jsx.js +84 -0
- package/dist/predicates/jsx.js.map +1 -0
- package/dist/predicates/metrics.d.ts +30 -0
- package/dist/predicates/metrics.d.ts.map +1 -0
- package/dist/predicates/metrics.js +65 -0
- package/dist/predicates/metrics.js.map +1 -0
- package/dist/predicates/module.d.ts +44 -0
- package/dist/predicates/module.d.ts.map +1 -0
- package/dist/predicates/module.js +70 -0
- package/dist/predicates/module.js.map +1 -0
- package/dist/predicates/type.d.ts +48 -0
- package/dist/predicates/type.d.ts.map +1 -0
- package/dist/predicates/type.js +107 -0
- package/dist/predicates/type.js.map +1 -0
- package/dist/presets/boundaries.d.ts +19 -0
- package/dist/presets/boundaries.d.ts.map +1 -0
- package/dist/presets/boundaries.js +93 -0
- package/dist/presets/boundaries.js.map +1 -0
- package/dist/presets/data-layer.d.ts +20 -0
- package/dist/presets/data-layer.d.ts.map +1 -0
- package/dist/presets/data-layer.js +30 -0
- package/dist/presets/data-layer.js.map +1 -0
- package/dist/presets/index.d.ts +9 -0
- package/dist/presets/index.d.ts.map +1 -0
- package/dist/presets/index.js +5 -0
- package/dist/presets/index.js.map +1 -0
- package/dist/presets/layered.d.ts +21 -0
- package/dist/presets/layered.d.ts.map +1 -0
- package/dist/presets/layered.js +103 -0
- package/dist/presets/layered.js.map +1 -0
- package/dist/presets/shared.d.ts +3 -0
- package/dist/presets/shared.d.ts.map +1 -0
- package/dist/presets/shared.js +5 -0
- package/dist/presets/shared.js.map +1 -0
- package/dist/rules/architecture.d.ts +10 -0
- package/dist/rules/architecture.d.ts.map +1 -0
- package/dist/rules/architecture.js +14 -0
- package/dist/rules/architecture.js.map +1 -0
- package/dist/rules/code-quality.d.ts +55 -0
- package/dist/rules/code-quality.d.ts.map +1 -0
- package/dist/rules/code-quality.js +116 -0
- package/dist/rules/code-quality.js.map +1 -0
- package/dist/rules/dependencies.d.ts +32 -0
- package/dist/rules/dependencies.d.ts.map +1 -0
- package/dist/rules/dependencies.js +37 -0
- package/dist/rules/dependencies.js.map +1 -0
- package/dist/rules/errors.d.ts +31 -0
- package/dist/rules/errors.d.ts.map +1 -0
- package/dist/rules/errors.js +97 -0
- package/dist/rules/errors.js.map +1 -0
- package/dist/rules/hygiene.d.ts +54 -0
- package/dist/rules/hygiene.d.ts.map +1 -0
- package/dist/rules/hygiene.js +62 -0
- package/dist/rules/hygiene.js.map +1 -0
- package/dist/rules/metrics-function.d.ts +45 -0
- package/dist/rules/metrics-function.d.ts.map +1 -0
- package/dist/rules/metrics-function.js +87 -0
- package/dist/rules/metrics-function.js.map +1 -0
- package/dist/rules/metrics.d.ts +64 -0
- package/dist/rules/metrics.d.ts.map +1 -0
- package/dist/rules/metrics.js +157 -0
- package/dist/rules/metrics.js.map +1 -0
- package/dist/rules/naming.d.ts +24 -0
- package/dist/rules/naming.d.ts.map +1 -0
- package/dist/rules/naming.js +51 -0
- package/dist/rules/naming.js.map +1 -0
- package/dist/rules/security.d.ts +59 -0
- package/dist/rules/security.d.ts.map +1 -0
- package/dist/rules/security.js +92 -0
- package/dist/rules/security.js.map +1 -0
- package/dist/rules/typescript.d.ts +73 -0
- package/dist/rules/typescript.d.ts.map +1 -0
- package/dist/rules/typescript.js +105 -0
- package/dist/rules/typescript.js.map +1 -0
- package/dist/smells/duplicate-bodies.d.ts +24 -0
- package/dist/smells/duplicate-bodies.d.ts.map +1 -0
- package/dist/smells/duplicate-bodies.js +131 -0
- package/dist/smells/duplicate-bodies.js.map +1 -0
- package/dist/smells/fingerprint.d.ts +27 -0
- package/dist/smells/fingerprint.d.ts.map +1 -0
- package/dist/smells/fingerprint.js +50 -0
- package/dist/smells/fingerprint.js.map +1 -0
- package/dist/smells/inconsistent-siblings.d.ts +21 -0
- package/dist/smells/inconsistent-siblings.d.ts.map +1 -0
- package/dist/smells/inconsistent-siblings.js +135 -0
- package/dist/smells/inconsistent-siblings.js.map +1 -0
- package/dist/smells/index.d.ts +12 -0
- package/dist/smells/index.d.ts.map +1 -0
- package/dist/smells/index.js +15 -0
- package/dist/smells/index.js.map +1 -0
- package/dist/smells/smell-builder.d.ts +37 -0
- package/dist/smells/smell-builder.d.ts.map +1 -0
- package/dist/smells/smell-builder.js +51 -0
- package/dist/smells/smell-builder.js.map +1 -0
- package/package.json +121 -0
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { ClassDeclaration } from 'ts-morph';
|
|
2
|
+
import type { Predicate } from '@nielspeter/eess';
|
|
3
|
+
import type { ArchFunction } from '../models/arch-function.js';
|
|
4
|
+
/**
|
|
5
|
+
* Predicate: class has a method (or constructor/getter/setter) with
|
|
6
|
+
* cyclomatic complexity above threshold.
|
|
7
|
+
*/
|
|
8
|
+
export declare function haveCyclomaticComplexity(opts: {
|
|
9
|
+
greaterThan: number;
|
|
10
|
+
}): Predicate<ClassDeclaration>;
|
|
11
|
+
/**
|
|
12
|
+
* Predicate: function has cyclomatic complexity above threshold.
|
|
13
|
+
* Uses ArchFunction.getBody() — works for all function kinds.
|
|
14
|
+
*/
|
|
15
|
+
export declare function haveComplexity(opts: {
|
|
16
|
+
greaterThan: number;
|
|
17
|
+
}): Predicate<ArchFunction>;
|
|
18
|
+
/**
|
|
19
|
+
* Predicate: class has more than N lines of code (span lines).
|
|
20
|
+
*/
|
|
21
|
+
export declare function haveMoreLinesThan(threshold: number): Predicate<ClassDeclaration>;
|
|
22
|
+
/**
|
|
23
|
+
* Predicate: function has more than N lines of code (span lines).
|
|
24
|
+
*/
|
|
25
|
+
export declare function haveMoreFunctionLinesThan(threshold: number): Predicate<ArchFunction>;
|
|
26
|
+
/**
|
|
27
|
+
* Predicate: class has more than N methods.
|
|
28
|
+
*/
|
|
29
|
+
export declare function haveMoreMethodsThan(threshold: number): Predicate<ClassDeclaration>;
|
|
30
|
+
//# sourceMappingURL=metrics.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"metrics.d.ts","sourceRoot":"","sources":["../../src/predicates/metrics.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAA;AAChD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAA;AACjD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAA;AAG9D;;;GAGG;AACH,wBAAgB,wBAAwB,CAAC,IAAI,EAAE;IAC7C,WAAW,EAAE,MAAM,CAAA;CACpB,GAAG,SAAS,CAAC,gBAAgB,CAAC,CAa9B;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE;IAAE,WAAW,EAAE,MAAM,CAAA;CAAE,GAAG,SAAS,CAAC,YAAY,CAAC,CAOrF;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,MAAM,GAAG,SAAS,CAAC,gBAAgB,CAAC,CAOhF;AAED;;GAEG;AACH,wBAAgB,yBAAyB,CAAC,SAAS,EAAE,MAAM,GAAG,SAAS,CAAC,YAAY,CAAC,CAOpF;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,SAAS,EAAE,MAAM,GAAG,SAAS,CAAC,gBAAgB,CAAC,CAOlF"}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { cyclomaticComplexity, linesOfCode, methodCount } from '../helpers/complexity.js';
|
|
2
|
+
/**
|
|
3
|
+
* Predicate: class has a method (or constructor/getter/setter) with
|
|
4
|
+
* cyclomatic complexity above threshold.
|
|
5
|
+
*/
|
|
6
|
+
export function haveCyclomaticComplexity(opts) {
|
|
7
|
+
return {
|
|
8
|
+
description: `have a method with cyclomatic complexity > ${String(opts.greaterThan)}`,
|
|
9
|
+
test(cls) {
|
|
10
|
+
const bodies = [
|
|
11
|
+
...cls.getMethods().map((m) => m.getBody()),
|
|
12
|
+
...cls.getConstructors().map((c) => c.getBody()),
|
|
13
|
+
...cls.getGetAccessors().map((g) => g.getBody()),
|
|
14
|
+
...cls.getSetAccessors().map((s) => s.getBody()),
|
|
15
|
+
];
|
|
16
|
+
return bodies.some((body) => cyclomaticComplexity(body) > opts.greaterThan);
|
|
17
|
+
},
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Predicate: function has cyclomatic complexity above threshold.
|
|
22
|
+
* Uses ArchFunction.getBody() — works for all function kinds.
|
|
23
|
+
*/
|
|
24
|
+
export function haveComplexity(opts) {
|
|
25
|
+
return {
|
|
26
|
+
description: `have cyclomatic complexity > ${String(opts.greaterThan)}`,
|
|
27
|
+
test(fn) {
|
|
28
|
+
return cyclomaticComplexity(fn.getBody()) > opts.greaterThan;
|
|
29
|
+
},
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Predicate: class has more than N lines of code (span lines).
|
|
34
|
+
*/
|
|
35
|
+
export function haveMoreLinesThan(threshold) {
|
|
36
|
+
return {
|
|
37
|
+
description: `have more than ${String(threshold)} lines`,
|
|
38
|
+
test(cls) {
|
|
39
|
+
return linesOfCode(cls) > threshold;
|
|
40
|
+
},
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Predicate: function has more than N lines of code (span lines).
|
|
45
|
+
*/
|
|
46
|
+
export function haveMoreFunctionLinesThan(threshold) {
|
|
47
|
+
return {
|
|
48
|
+
description: `have more than ${String(threshold)} lines`,
|
|
49
|
+
test(fn) {
|
|
50
|
+
return linesOfCode(fn.getNode()) > threshold;
|
|
51
|
+
},
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Predicate: class has more than N methods.
|
|
56
|
+
*/
|
|
57
|
+
export function haveMoreMethodsThan(threshold) {
|
|
58
|
+
return {
|
|
59
|
+
description: `have more than ${String(threshold)} methods`,
|
|
60
|
+
test(cls) {
|
|
61
|
+
return methodCount(cls) > threshold;
|
|
62
|
+
},
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
//# sourceMappingURL=metrics.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"metrics.js","sourceRoot":"","sources":["../../src/predicates/metrics.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,oBAAoB,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAA;AAEzF;;;GAGG;AACH,MAAM,UAAU,wBAAwB,CAAC,IAExC;IACC,OAAO;QACL,WAAW,EAAE,8CAA8C,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,EAAE;QACrF,IAAI,CAAC,GAAqB;YACxB,MAAM,MAAM,GAAG;gBACb,GAAG,GAAG,CAAC,UAAU,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC;gBAC3C,GAAG,GAAG,CAAC,eAAe,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC;gBAChD,GAAG,GAAG,CAAC,eAAe,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC;gBAChD,GAAG,GAAG,CAAC,eAAe,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC;aACjD,CAAA;YACD,OAAO,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,oBAAoB,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,WAAW,CAAC,CAAA;QAC7E,CAAC;KACF,CAAA;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,cAAc,CAAC,IAA6B;IAC1D,OAAO;QACL,WAAW,EAAE,gCAAgC,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,EAAE;QACvE,IAAI,CAAC,EAAgB;YACnB,OAAO,oBAAoB,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,GAAG,IAAI,CAAC,WAAW,CAAA;QAC9D,CAAC;KACF,CAAA;AACH,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,iBAAiB,CAAC,SAAiB;IACjD,OAAO;QACL,WAAW,EAAE,kBAAkB,MAAM,CAAC,SAAS,CAAC,QAAQ;QACxD,IAAI,CAAC,GAAqB;YACxB,OAAO,WAAW,CAAC,GAAG,CAAC,GAAG,SAAS,CAAA;QACrC,CAAC;KACF,CAAA;AACH,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,yBAAyB,CAAC,SAAiB;IACzD,OAAO;QACL,WAAW,EAAE,kBAAkB,MAAM,CAAC,SAAS,CAAC,QAAQ;QACxD,IAAI,CAAC,EAAgB;YACnB,OAAO,WAAW,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,GAAG,SAAS,CAAA;QAC9C,CAAC;KACF,CAAA;AACH,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,mBAAmB,CAAC,SAAiB;IACnD,OAAO;QACL,WAAW,EAAE,kBAAkB,MAAM,CAAC,SAAS,CAAC,UAAU;QAC1D,IAAI,CAAC,GAAqB;YACxB,OAAO,WAAW,CAAC,GAAG,CAAC,GAAG,SAAS,CAAA;QACrC,CAAC;KACF,CAAA;AACH,CAAC"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import type { SourceFile } from 'ts-morph';
|
|
2
|
+
import type { Predicate } from '@nielspeter/eess';
|
|
3
|
+
import type { ImportOptions } from '../core/import-options.js';
|
|
4
|
+
/**
|
|
5
|
+
* Matches modules that import from a path matching any of the given globs.
|
|
6
|
+
*
|
|
7
|
+
* The globs are matched against resolved absolute import paths.
|
|
8
|
+
* For external (non-resolvable) imports, they match against the raw specifier.
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* modules(p).that().importFrom('** /infrastructure/**')
|
|
12
|
+
* modules(p).that().importFrom('fastify', 'knex', 'bullmq')
|
|
13
|
+
*/
|
|
14
|
+
export declare function importFrom(globs: string[], options: ImportOptions): Predicate<SourceFile>;
|
|
15
|
+
export declare function importFrom(...globs: string[]): Predicate<SourceFile>;
|
|
16
|
+
/**
|
|
17
|
+
* Matches modules that do NOT import from any path matching the given globs.
|
|
18
|
+
*
|
|
19
|
+
* @example
|
|
20
|
+
* modules(p).that().notImportFrom('** /legacy/**')
|
|
21
|
+
* modules(p).that().notImportFrom('fastify', 'knex', 'bullmq')
|
|
22
|
+
*/
|
|
23
|
+
export declare function notImportFrom(globs: string[], options: ImportOptions): Predicate<SourceFile>;
|
|
24
|
+
export declare function notImportFrom(...globs: string[]): Predicate<SourceFile>;
|
|
25
|
+
/**
|
|
26
|
+
* Matches modules that export a symbol with the given name.
|
|
27
|
+
*
|
|
28
|
+
* Checks the module's exported declarations for a matching name.
|
|
29
|
+
*
|
|
30
|
+
* @example
|
|
31
|
+
* modules(p).that().exportSymbolNamed('default')
|
|
32
|
+
*/
|
|
33
|
+
export declare function exportSymbolNamed(name: string): Predicate<SourceFile>;
|
|
34
|
+
/**
|
|
35
|
+
* Matches modules whose file path matches the given glob.
|
|
36
|
+
*
|
|
37
|
+
* Similar to resideInFile but semantically clearer for modules —
|
|
38
|
+
* "modules that have path matching" vs "elements that reside in file".
|
|
39
|
+
*
|
|
40
|
+
* @example
|
|
41
|
+
* modules(p).that().havePathMatching('** /services/*.ts')
|
|
42
|
+
*/
|
|
43
|
+
export declare function havePathMatching(glob: string): Predicate<SourceFile>;
|
|
44
|
+
//# sourceMappingURL=module.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"module.d.ts","sourceRoot":"","sources":["../../src/predicates/module.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,UAAU,CAAA;AAC1C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAA;AACjD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAA;AAmB9D;;;;;;;;;GASG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,OAAO,EAAE,aAAa,GAAG,SAAS,CAAC,UAAU,CAAC,CAAA;AAC1F,wBAAgB,UAAU,CAAC,GAAG,KAAK,EAAE,MAAM,EAAE,GAAG,SAAS,CAAC,UAAU,CAAC,CAAA;AAgBrE;;;;;;GAMG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,OAAO,EAAE,aAAa,GAAG,SAAS,CAAC,UAAU,CAAC,CAAA;AAC7F,wBAAgB,aAAa,CAAC,GAAG,KAAK,EAAE,MAAM,EAAE,GAAG,SAAS,CAAC,UAAU,CAAC,CAAA;AAkBxE;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,CAAC,UAAU,CAAC,CAKrE;AAED;;;;;;;;GAQG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,CAAC,UAAU,CAAC,CAMpE"}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import picomatch from 'picomatch';
|
|
2
|
+
import { getDependencyDecls, resolveDependencyPath, isTypeOnlyDependency, } from '../core/module-dependencies.js';
|
|
3
|
+
/**
|
|
4
|
+
* Resolve the dependency paths for a source file — `import … from` plus
|
|
5
|
+
* `export … from` re-exports (both are dependency edges) — optionally filtering
|
|
6
|
+
* out type-only edges. Returns absolute paths for resolvable targets, raw
|
|
7
|
+
* specifiers for external packages.
|
|
8
|
+
*/
|
|
9
|
+
function getImportPaths(sourceFile, ignoreTypeImports = false) {
|
|
10
|
+
return getDependencyDecls(sourceFile)
|
|
11
|
+
.filter((decl) => (ignoreTypeImports ? !isTypeOnlyDependency(decl) : true))
|
|
12
|
+
.map(resolveDependencyPath);
|
|
13
|
+
}
|
|
14
|
+
export function importFrom(...args) {
|
|
15
|
+
// ADR-005: as casts required — TS cannot narrow tuple union rest params after Array.isArray
|
|
16
|
+
// eess-exclude eess/adr005-no-type-assertions: tuple-union rest param — TS cannot narrow [string[], ImportOptions] | string[] to string[] from Array.isArray(args[0])
|
|
17
|
+
const globs = Array.isArray(args[0]) ? args[0] : args;
|
|
18
|
+
// eess-exclude eess/adr005-no-type-assertions: tuple-union rest param — args[1] is ImportOptions only in the [globs, options] overload
|
|
19
|
+
const options = Array.isArray(args[0]) && args.length > 1 ? args[1] : undefined;
|
|
20
|
+
const ignoreType = options?.ignoreTypeImports === true;
|
|
21
|
+
const matchers = globs.map((g) => picomatch(g));
|
|
22
|
+
return {
|
|
23
|
+
description: 'import from ' + globs.map((g) => `"${g}"`).join(', '),
|
|
24
|
+
test: (sourceFile) => getImportPaths(sourceFile, ignoreType).some((p) => matchers.some((m) => m(p))),
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
export function notImportFrom(...args) {
|
|
28
|
+
// ADR-005: as casts required — TS cannot narrow tuple union rest params after Array.isArray
|
|
29
|
+
// eess-exclude eess/adr005-no-type-assertions: tuple-union rest param — TS cannot narrow [string[], ImportOptions] | string[] to string[] from Array.isArray(args[0])
|
|
30
|
+
const globs = Array.isArray(args[0]) ? args[0] : args;
|
|
31
|
+
// eess-exclude eess/adr005-no-type-assertions: tuple-union rest param — args[1] is ImportOptions only in the [globs, options] overload
|
|
32
|
+
const options = Array.isArray(args[0]) && args.length > 1 ? args[1] : undefined;
|
|
33
|
+
const ignoreType = options?.ignoreTypeImports === true;
|
|
34
|
+
const matchers = globs.map((g) => picomatch(g));
|
|
35
|
+
return {
|
|
36
|
+
description: 'not import from ' + globs.map((g) => `"${g}"`).join(', '),
|
|
37
|
+
test: (sourceFile) => !getImportPaths(sourceFile, ignoreType).some((p) => matchers.some((m) => m(p))),
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Matches modules that export a symbol with the given name.
|
|
42
|
+
*
|
|
43
|
+
* Checks the module's exported declarations for a matching name.
|
|
44
|
+
*
|
|
45
|
+
* @example
|
|
46
|
+
* modules(p).that().exportSymbolNamed('default')
|
|
47
|
+
*/
|
|
48
|
+
export function exportSymbolNamed(name) {
|
|
49
|
+
return {
|
|
50
|
+
description: `export symbol named "${name}"`,
|
|
51
|
+
test: (sourceFile) => sourceFile.getExportedDeclarations().has(name),
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Matches modules whose file path matches the given glob.
|
|
56
|
+
*
|
|
57
|
+
* Similar to resideInFile but semantically clearer for modules —
|
|
58
|
+
* "modules that have path matching" vs "elements that reside in file".
|
|
59
|
+
*
|
|
60
|
+
* @example
|
|
61
|
+
* modules(p).that().havePathMatching('** /services/*.ts')
|
|
62
|
+
*/
|
|
63
|
+
export function havePathMatching(glob) {
|
|
64
|
+
const isMatch = picomatch(glob);
|
|
65
|
+
return {
|
|
66
|
+
description: `have path matching "${glob}"`,
|
|
67
|
+
test: (sourceFile) => isMatch(sourceFile.getFilePath()),
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
//# sourceMappingURL=module.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"module.js","sourceRoot":"","sources":["../../src/predicates/module.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { type InterfaceDeclaration, type TypeAliasDeclaration } from 'ts-morph';
|
|
2
|
+
import type { Predicate } from '@nielspeter/eess';
|
|
3
|
+
import type { TypeMatcher } from '../helpers/type-matchers.js';
|
|
4
|
+
/**
|
|
5
|
+
* Union type representing both interface and type alias declarations.
|
|
6
|
+
* Used as the element type for TypeRuleBuilder.
|
|
7
|
+
*/
|
|
8
|
+
export type TypeDeclaration = InterfaceDeclaration | TypeAliasDeclaration;
|
|
9
|
+
/**
|
|
10
|
+
* Matches only InterfaceDeclaration elements.
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* types(project).that().areInterfaces() // only interfaces, not type aliases
|
|
14
|
+
*/
|
|
15
|
+
export declare function areInterfaces(): Predicate<TypeDeclaration>;
|
|
16
|
+
/**
|
|
17
|
+
* Matches only TypeAliasDeclaration elements.
|
|
18
|
+
*
|
|
19
|
+
* @example
|
|
20
|
+
* types(project).that().areTypeAliases() // only type aliases, not interfaces
|
|
21
|
+
*/
|
|
22
|
+
export declare function areTypeAliases(): Predicate<TypeDeclaration>;
|
|
23
|
+
/**
|
|
24
|
+
* Matches types that have a property with the given name.
|
|
25
|
+
* Works for both interfaces (direct properties) and type aliases
|
|
26
|
+
* (resolved type properties).
|
|
27
|
+
*
|
|
28
|
+
* @example
|
|
29
|
+
* types(project).that().haveProperty('sortBy')
|
|
30
|
+
*/
|
|
31
|
+
export declare function haveProperty(name: string): Predicate<TypeDeclaration>;
|
|
32
|
+
/**
|
|
33
|
+
* Matches types that have a property whose type satisfies the given matcher.
|
|
34
|
+
* Resolves through type aliases, Partial<>, Pick<>, etc.
|
|
35
|
+
*
|
|
36
|
+
* @example
|
|
37
|
+
* types(project).that().havePropertyOfType('sortBy', isString())
|
|
38
|
+
*/
|
|
39
|
+
export declare function havePropertyOfType(name: string, matcher: TypeMatcher): Predicate<TypeDeclaration>;
|
|
40
|
+
/**
|
|
41
|
+
* Matches interfaces that extend the given type name.
|
|
42
|
+
* For type aliases, checks if the type text references the name.
|
|
43
|
+
*
|
|
44
|
+
* @example
|
|
45
|
+
* types(project).that().extendType('BaseConfig')
|
|
46
|
+
*/
|
|
47
|
+
export declare function extendType(name: string): Predicate<TypeDeclaration>;
|
|
48
|
+
//# sourceMappingURL=type.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"type.d.ts","sourceRoot":"","sources":["../../src/predicates/type.ts"],"names":[],"mappings":"AAAA,OAAO,EAAQ,KAAK,oBAAoB,EAAE,KAAK,oBAAoB,EAAE,MAAM,UAAU,CAAA;AACrF,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAA;AACjD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,6BAA6B,CAAA;AAE9D;;;GAGG;AACH,MAAM,MAAM,eAAe,GAAG,oBAAoB,GAAG,oBAAoB,CAAA;AAEzE;;;;;GAKG;AACH,wBAAgB,aAAa,IAAI,SAAS,CAAC,eAAe,CAAC,CAK1D;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,IAAI,SAAS,CAAC,eAAe,CAAC,CAK3D;AAED;;;;;;;GAOG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,CAAC,eAAe,CAAC,CAQrE;AAED;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,WAAW,GAAG,SAAS,CAAC,eAAe,CAAC,CASjG;AAED;;;;;;GAMG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,CAAC,eAAe,CAAC,CAgBnE"}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import { Node } from 'ts-morph';
|
|
2
|
+
/**
|
|
3
|
+
* Matches only InterfaceDeclaration elements.
|
|
4
|
+
*
|
|
5
|
+
* @example
|
|
6
|
+
* types(project).that().areInterfaces() // only interfaces, not type aliases
|
|
7
|
+
*/
|
|
8
|
+
export function areInterfaces() {
|
|
9
|
+
return {
|
|
10
|
+
description: 'are interfaces',
|
|
11
|
+
test: (element) => Node.isInterfaceDeclaration(element),
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Matches only TypeAliasDeclaration elements.
|
|
16
|
+
*
|
|
17
|
+
* @example
|
|
18
|
+
* types(project).that().areTypeAliases() // only type aliases, not interfaces
|
|
19
|
+
*/
|
|
20
|
+
export function areTypeAliases() {
|
|
21
|
+
return {
|
|
22
|
+
description: 'are type aliases',
|
|
23
|
+
test: (element) => Node.isTypeAliasDeclaration(element),
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Matches types that have a property with the given name.
|
|
28
|
+
* Works for both interfaces (direct properties) and type aliases
|
|
29
|
+
* (resolved type properties).
|
|
30
|
+
*
|
|
31
|
+
* @example
|
|
32
|
+
* types(project).that().haveProperty('sortBy')
|
|
33
|
+
*/
|
|
34
|
+
export function haveProperty(name) {
|
|
35
|
+
return {
|
|
36
|
+
description: `have property "${name}"`,
|
|
37
|
+
test: (element) => {
|
|
38
|
+
const type = getResolvedType(element);
|
|
39
|
+
return type.getProperty(name) !== undefined;
|
|
40
|
+
},
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Matches types that have a property whose type satisfies the given matcher.
|
|
45
|
+
* Resolves through type aliases, Partial<>, Pick<>, etc.
|
|
46
|
+
*
|
|
47
|
+
* @example
|
|
48
|
+
* types(project).that().havePropertyOfType('sortBy', isString())
|
|
49
|
+
*/
|
|
50
|
+
export function havePropertyOfType(name, matcher) {
|
|
51
|
+
return {
|
|
52
|
+
description: `have property "${name}" of matching type`,
|
|
53
|
+
test: (element) => {
|
|
54
|
+
const propType = getPropertyType(element, name);
|
|
55
|
+
if (propType === undefined)
|
|
56
|
+
return false;
|
|
57
|
+
return matcher(propType);
|
|
58
|
+
},
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Matches interfaces that extend the given type name.
|
|
63
|
+
* For type aliases, checks if the type text references the name.
|
|
64
|
+
*
|
|
65
|
+
* @example
|
|
66
|
+
* types(project).that().extendType('BaseConfig')
|
|
67
|
+
*/
|
|
68
|
+
export function extendType(name) {
|
|
69
|
+
return {
|
|
70
|
+
description: `extend type "${name}"`,
|
|
71
|
+
test: (element) => {
|
|
72
|
+
if (Node.isInterfaceDeclaration(element)) {
|
|
73
|
+
const escaped = name.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
74
|
+
const nameRegex = new RegExp(`^${escaped}(\\b|$|<)`);
|
|
75
|
+
return element.getExtends().some((ext) => nameRegex.test(ext.getText()));
|
|
76
|
+
}
|
|
77
|
+
// For type aliases, check if the type directly references the named type
|
|
78
|
+
// Use word boundary matching to avoid false positives (e.g., "BaseConfig" inside "{ bar: BaseConfig }")
|
|
79
|
+
const typeText = element.getType().getText();
|
|
80
|
+
const nameRegex = new RegExp(`\\b${name.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}\\b`);
|
|
81
|
+
return nameRegex.test(typeText);
|
|
82
|
+
},
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
// --- Internal helpers ---
|
|
86
|
+
/**
|
|
87
|
+
* Resolve a TypeDeclaration to its ts-morph Type.
|
|
88
|
+
*/
|
|
89
|
+
function getResolvedType(element) {
|
|
90
|
+
return element.getType();
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Get the Type of a named property on a TypeDeclaration.
|
|
94
|
+
*
|
|
95
|
+
* Uses getTypeAtLocation() to resolve in context, which is critical
|
|
96
|
+
* for Partial<T>, Pick<T, K>, and other mapped types.
|
|
97
|
+
*/
|
|
98
|
+
function getPropertyType(element, name) {
|
|
99
|
+
const type = getResolvedType(element);
|
|
100
|
+
const prop = type.getProperty(name);
|
|
101
|
+
if (prop === undefined)
|
|
102
|
+
return undefined;
|
|
103
|
+
// getTypeAtLocation resolves the property type in the context of the declaration.
|
|
104
|
+
// Without this, Partial<StrictOptions>['sortBy'] would not resolve correctly.
|
|
105
|
+
return prop.getTypeAtLocation(element);
|
|
106
|
+
}
|
|
107
|
+
//# sourceMappingURL=type.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"type.js","sourceRoot":"","sources":["../../src/predicates/type.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAwD,MAAM,UAAU,CAAA;AAUrF;;;;;GAKG;AACH,MAAM,UAAU,aAAa;IAC3B,OAAO;QACL,WAAW,EAAE,gBAAgB;QAC7B,IAAI,EAAE,CAAC,OAAO,EAAE,EAAE,CAAC,IAAI,CAAC,sBAAsB,CAAC,OAAO,CAAC;KACxD,CAAA;AACH,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,cAAc;IAC5B,OAAO;QACL,WAAW,EAAE,kBAAkB;QAC/B,IAAI,EAAE,CAAC,OAAO,EAAE,EAAE,CAAC,IAAI,CAAC,sBAAsB,CAAC,OAAO,CAAC;KACxD,CAAA;AACH,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,YAAY,CAAC,IAAY;IACvC,OAAO;QACL,WAAW,EAAE,kBAAkB,IAAI,GAAG;QACtC,IAAI,EAAE,CAAC,OAAO,EAAE,EAAE;YAChB,MAAM,IAAI,GAAG,eAAe,CAAC,OAAO,CAAC,CAAA;YACrC,OAAO,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,KAAK,SAAS,CAAA;QAC7C,CAAC;KACF,CAAA;AACH,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,kBAAkB,CAAC,IAAY,EAAE,OAAoB;IACnE,OAAO;QACL,WAAW,EAAE,kBAAkB,IAAI,oBAAoB;QACvD,IAAI,EAAE,CAAC,OAAO,EAAE,EAAE;YAChB,MAAM,QAAQ,GAAG,eAAe,CAAC,OAAO,EAAE,IAAI,CAAC,CAAA;YAC/C,IAAI,QAAQ,KAAK,SAAS;gBAAE,OAAO,KAAK,CAAA;YACxC,OAAO,OAAO,CAAC,QAAQ,CAAC,CAAA;QAC1B,CAAC;KACF,CAAA;AACH,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,UAAU,CAAC,IAAY;IACrC,OAAO;QACL,WAAW,EAAE,gBAAgB,IAAI,GAAG;QACpC,IAAI,EAAE,CAAC,OAAO,EAAE,EAAE;YAChB,IAAI,IAAI,CAAC,sBAAsB,CAAC,OAAO,CAAC,EAAE,CAAC;gBACzC,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,qBAAqB,EAAE,MAAM,CAAC,CAAA;gBAC3D,MAAM,SAAS,GAAG,IAAI,MAAM,CAAC,IAAI,OAAO,WAAW,CAAC,CAAA;gBACpD,OAAO,OAAO,CAAC,UAAU,EAAE,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC,CAAA;YAC1E,CAAC;YACD,yEAAyE;YACzE,wGAAwG;YACxG,MAAM,QAAQ,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC,OAAO,EAAE,CAAA;YAC5C,MAAM,SAAS,GAAG,IAAI,MAAM,CAAC,MAAM,IAAI,CAAC,OAAO,CAAC,qBAAqB,EAAE,MAAM,CAAC,KAAK,CAAC,CAAA;YACpF,OAAO,SAAS,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAA;QACjC,CAAC;KACF,CAAA;AACH,CAAC;AAED,2BAA2B;AAE3B;;GAEG;AACH,SAAS,eAAe,CAAC,OAAwB;IAC/C,OAAO,OAAO,CAAC,OAAO,EAAE,CAAA;AAC1B,CAAC;AAED;;;;;GAKG;AACH,SAAS,eAAe,CAAC,OAAwB,EAAE,IAAY;IAC7D,MAAM,IAAI,GAAG,eAAe,CAAC,OAAO,CAAC,CAAA;IACrC,MAAM,IAAI,GAAG,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,CAAA;IACnC,IAAI,IAAI,KAAK,SAAS;QAAE,OAAO,SAAS,CAAA;IAExC,kFAAkF;IAClF,8EAA8E;IAC9E,OAAO,IAAI,CAAC,iBAAiB,CAAC,OAAO,CAAC,CAAA;AACxC,CAAC"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { ArchProject } from '../core/project.js';
|
|
2
|
+
import type { ArchViolation } from '../core/violation.js';
|
|
3
|
+
import type { PresetBaseOptions } from './shared.js';
|
|
4
|
+
export interface StrictBoundariesOptions extends PresetBaseOptions {
|
|
5
|
+
/** Glob pattern for boundary folders (e.g., 'src/features/*') */
|
|
6
|
+
folders: string;
|
|
7
|
+
/** Glob patterns for shared folders accessible by all boundaries */
|
|
8
|
+
shared?: string[];
|
|
9
|
+
/** If true, test files cannot import from other boundaries' tests */
|
|
10
|
+
isolateTests?: boolean;
|
|
11
|
+
/** If true, warn on copy-pasted function bodies across boundaries */
|
|
12
|
+
noCopyPaste?: boolean;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Enforce strict module boundaries: no cycles, no cross-boundary imports,
|
|
16
|
+
* shared isolation, and optional copy-paste detection.
|
|
17
|
+
*/
|
|
18
|
+
export declare function strictBoundaries(p: ArchProject, options: StrictBoundariesOptions): ArchViolation[];
|
|
19
|
+
//# sourceMappingURL=boundaries.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"boundaries.d.ts","sourceRoot":"","sources":["../../src/presets/boundaries.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAA;AACrD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAA;AAIzD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAA;AAGpD,MAAM,WAAW,uBAAwB,SAAQ,iBAAiB;IAChE,iEAAiE;IACjE,OAAO,EAAE,MAAM,CAAA;IACf,oEAAoE;IACpE,MAAM,CAAC,EAAE,MAAM,EAAE,CAAA;IACjB,qEAAqE;IACrE,YAAY,CAAC,EAAE,OAAO,CAAA;IACtB,qEAAqE;IACrE,WAAW,CAAC,EAAE,OAAO,CAAA;CACtB;AAgED;;;GAGG;AACH,wBAAgB,gBAAgB,CAC9B,CAAC,EAAE,WAAW,EACd,OAAO,EAAE,uBAAuB,GAC/B,aAAa,EAAE,CA8EjB"}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import picomatch from 'picomatch';
|
|
2
|
+
import { slices } from '../builders/slice-rule-builder.js';
|
|
3
|
+
import { modules } from '../builders/module-rule-builder.js';
|
|
4
|
+
import { smells } from '../smells/index.js';
|
|
5
|
+
import { dispatchRule, validateOverrides, finishPreset } from './shared.js';
|
|
6
|
+
const RULE_IDS = [
|
|
7
|
+
'preset/boundaries/no-cycles',
|
|
8
|
+
'preset/boundaries/no-cross-boundary',
|
|
9
|
+
'preset/boundaries/shared-isolation',
|
|
10
|
+
'preset/boundaries/test-isolation',
|
|
11
|
+
'preset/boundaries/no-duplicate-bodies',
|
|
12
|
+
];
|
|
13
|
+
/**
|
|
14
|
+
* Collect violations for shared-folder isolation rules.
|
|
15
|
+
*/
|
|
16
|
+
function applySharedIsolation(p, sharedGlobs, boundaryFolders, overrides) {
|
|
17
|
+
const violations = [];
|
|
18
|
+
for (const sharedGlob of sharedGlobs) {
|
|
19
|
+
for (const dir of boundaryFolders) {
|
|
20
|
+
violations.push(...dispatchRule(modules(p).that().resideInFolder(sharedGlob).should().notImportFrom(`${dir}/**`), 'preset/boundaries/shared-isolation', 'error', overrides));
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
return violations;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Collect violations for test-isolation rules across boundaries.
|
|
27
|
+
*/
|
|
28
|
+
function applyTestIsolation(p, boundaryFolders, overrides) {
|
|
29
|
+
const violations = [];
|
|
30
|
+
for (const dir of boundaryFolders) {
|
|
31
|
+
const testPattern = `${dir}/**/*.test.*`;
|
|
32
|
+
const otherBoundaryTests = boundaryFolders
|
|
33
|
+
.filter((d) => d !== dir)
|
|
34
|
+
.map((d) => `${d}/**/*.test.*`);
|
|
35
|
+
for (const otherTestGlob of otherBoundaryTests) {
|
|
36
|
+
violations.push(...dispatchRule(modules(p).that().resideInFile(testPattern).should().notImportFrom(otherTestGlob), 'preset/boundaries/test-isolation', 'error', overrides));
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
return violations;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Enforce strict module boundaries: no cycles, no cross-boundary imports,
|
|
43
|
+
* shared isolation, and optional copy-paste detection.
|
|
44
|
+
*/
|
|
45
|
+
export function strictBoundaries(p, options) {
|
|
46
|
+
const overrides = options.overrides;
|
|
47
|
+
validateOverrides(overrides, [...RULE_IDS]);
|
|
48
|
+
const sharedGlobs = options.shared ?? [];
|
|
49
|
+
const violations = [];
|
|
50
|
+
// Discover boundary folders from the glob pattern
|
|
51
|
+
const boundaryGlob = options.folders;
|
|
52
|
+
const matcher = picomatch(boundaryGlob);
|
|
53
|
+
const boundaryFolders = [];
|
|
54
|
+
for (const sf of p.getSourceFiles()) {
|
|
55
|
+
const dir = sf.getFilePath().replace(/\/[^/]+$/, '');
|
|
56
|
+
if (matcher(dir) && !boundaryFolders.includes(dir)) {
|
|
57
|
+
boundaryFolders.push(dir);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
// Build a slice definition from discovered boundaries
|
|
61
|
+
const sliceDef = {};
|
|
62
|
+
for (const dir of boundaryFolders) {
|
|
63
|
+
const name = dir.split('/').pop() ?? dir;
|
|
64
|
+
sliceDef[name] = `${dir}/**`;
|
|
65
|
+
}
|
|
66
|
+
// --- No cycles between boundaries ---
|
|
67
|
+
if (Object.keys(sliceDef).length > 0) {
|
|
68
|
+
violations.push(...dispatchRule(slices(p).assignedFrom(sliceDef).should().beFreeOfCycles(), 'preset/boundaries/no-cycles', 'error', overrides));
|
|
69
|
+
}
|
|
70
|
+
// --- No cross-boundary imports ---
|
|
71
|
+
// Each boundary folder: modules in it can only import from itself + shared
|
|
72
|
+
for (const dir of boundaryFolders) {
|
|
73
|
+
const boundaryPattern = `${dir}/**`;
|
|
74
|
+
const allowedGlobs = [boundaryPattern, ...sharedGlobs];
|
|
75
|
+
violations.push(...dispatchRule(modules(p)
|
|
76
|
+
.that()
|
|
77
|
+
.resideInFolder(boundaryPattern)
|
|
78
|
+
.should()
|
|
79
|
+
.onlyImportFrom(...allowedGlobs), 'preset/boundaries/no-cross-boundary', 'error', overrides));
|
|
80
|
+
}
|
|
81
|
+
// --- Shared isolation: shared folders don't import from boundaries ---
|
|
82
|
+
violations.push(...applySharedIsolation(p, sharedGlobs, boundaryFolders, overrides));
|
|
83
|
+
// --- Test isolation ---
|
|
84
|
+
if (options.isolateTests) {
|
|
85
|
+
violations.push(...applyTestIsolation(p, boundaryFolders, overrides));
|
|
86
|
+
}
|
|
87
|
+
// --- No copy-paste across boundaries ---
|
|
88
|
+
if (options.noCopyPaste) {
|
|
89
|
+
violations.push(...dispatchRule(smells.duplicateBodies(p), 'preset/boundaries/no-duplicate-bodies', 'warn', overrides));
|
|
90
|
+
}
|
|
91
|
+
return finishPreset(violations, options);
|
|
92
|
+
}
|
|
93
|
+
//# sourceMappingURL=boundaries.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"boundaries.js","sourceRoot":"","sources":["../../src/presets/boundaries.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { ArchProject } from '../core/project.js';
|
|
2
|
+
import type { ArchViolation } from '../core/violation.js';
|
|
3
|
+
import type { PresetBaseOptions } from './shared.js';
|
|
4
|
+
export interface DataLayerIsolationOptions extends PresetBaseOptions {
|
|
5
|
+
/** Glob pattern for repository files */
|
|
6
|
+
repositories: string;
|
|
7
|
+
/** Base class that all repositories must extend */
|
|
8
|
+
baseClass?: string;
|
|
9
|
+
/** If true, repositories must throw typed errors, not generic Error */
|
|
10
|
+
requireTypedErrors?: boolean;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Companion to `layeredArchitecture`. Enforces repository pattern:
|
|
14
|
+
* base class extension and typed error throwing.
|
|
15
|
+
*
|
|
16
|
+
* Does NOT duplicate layer ordering or import direction — those
|
|
17
|
+
* are `layeredArchitecture`'s job.
|
|
18
|
+
*/
|
|
19
|
+
export declare function dataLayerIsolation(p: ArchProject, options: DataLayerIsolationOptions): ArchViolation[];
|
|
20
|
+
//# sourceMappingURL=data-layer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"data-layer.d.ts","sourceRoot":"","sources":["../../src/presets/data-layer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAA;AACrD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAA;AAGzD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAA;AAGpD,MAAM,WAAW,yBAA0B,SAAQ,iBAAiB;IAClE,wCAAwC;IACxC,YAAY,EAAE,MAAM,CAAA;IACpB,mDAAmD;IACnD,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,uEAAuE;IACvE,kBAAkB,CAAC,EAAE,OAAO,CAAA;CAC7B;AAID;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAChC,CAAC,EAAE,WAAW,EACd,OAAO,EAAE,yBAAyB,GACjC,aAAa,EAAE,CAmCjB"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { classes } from '../builders/class-rule-builder.js';
|
|
2
|
+
import { newExpr } from '../helpers/matchers.js';
|
|
3
|
+
import { dispatchRule, validateOverrides, finishPreset } from './shared.js';
|
|
4
|
+
const RULE_IDS = ['preset/data/extend-base', 'preset/data/typed-errors'];
|
|
5
|
+
/**
|
|
6
|
+
* Companion to `layeredArchitecture`. Enforces repository pattern:
|
|
7
|
+
* base class extension and typed error throwing.
|
|
8
|
+
*
|
|
9
|
+
* Does NOT duplicate layer ordering or import direction — those
|
|
10
|
+
* are `layeredArchitecture`'s job.
|
|
11
|
+
*/
|
|
12
|
+
export function dataLayerIsolation(p, options) {
|
|
13
|
+
const overrides = options.overrides;
|
|
14
|
+
validateOverrides(overrides, [...RULE_IDS]);
|
|
15
|
+
const violations = [];
|
|
16
|
+
// --- Base class enforcement ---
|
|
17
|
+
if (options.baseClass) {
|
|
18
|
+
violations.push(...dispatchRule(classes(p).that().resideInFolder(options.repositories).should().extend(options.baseClass), 'preset/data/extend-base', 'error', overrides));
|
|
19
|
+
}
|
|
20
|
+
// --- Typed errors ---
|
|
21
|
+
if (options.requireTypedErrors) {
|
|
22
|
+
violations.push(...dispatchRule(classes(p)
|
|
23
|
+
.that()
|
|
24
|
+
.resideInFolder(options.repositories)
|
|
25
|
+
.should()
|
|
26
|
+
.notContain(newExpr('Error')), 'preset/data/typed-errors', 'error', overrides));
|
|
27
|
+
}
|
|
28
|
+
return finishPreset(violations, options);
|
|
29
|
+
}
|
|
30
|
+
//# sourceMappingURL=data-layer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"data-layer.js","sourceRoot":"","sources":["../../src/presets/data-layer.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,mCAAmC,CAAA;AAC3D,OAAO,EAAE,OAAO,EAAE,MAAM,wBAAwB,CAAA;AAEhD,OAAO,EAAE,YAAY,EAAE,iBAAiB,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAW3E,MAAM,QAAQ,GAAG,CAAC,yBAAyB,EAAE,0BAA0B,CAAU,CAAA;AAEjF;;;;;;GAMG;AACH,MAAM,UAAU,kBAAkB,CAChC,CAAc,EACd,OAAkC;IAElC,MAAM,SAAS,GAAG,OAAO,CAAC,SAAS,CAAA;IACnC,iBAAiB,CAAC,SAAS,EAAE,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAA;IAE3C,MAAM,UAAU,GAAoB,EAAE,CAAA;IAEtC,iCAAiC;IACjC,IAAI,OAAO,CAAC,SAAS,EAAE,CAAC;QACtB,UAAU,CAAC,IAAI,CACb,GAAG,YAAY,CACb,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,cAAc,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC,MAAM,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,EACzF,yBAAyB,EACzB,OAAO,EACP,SAAS,CACV,CACF,CAAA;IACH,CAAC;IAED,uBAAuB;IACvB,IAAI,OAAO,CAAC,kBAAkB,EAAE,CAAC;QAC/B,UAAU,CAAC,IAAI,CACb,GAAG,YAAY,CACb,OAAO,CAAC,CAAC,CAAC;aACP,IAAI,EAAE;aACN,cAAc,CAAC,OAAO,CAAC,YAAY,CAAC;aACpC,MAAM,EAAE;aACR,UAAU,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,EAC/B,0BAA0B,EAC1B,OAAO,EACP,SAAS,CACV,CACF,CAAA;IACH,CAAC;IAED,OAAO,YAAY,CAAC,UAAU,EAAE,OAAO,CAAC,CAAA;AAC1C,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export type { RuleSeverity, PresetBaseOptions } from './shared.js';
|
|
2
|
+
export { dispatchRule, validateOverrides, throwIfViolations } from './shared.js';
|
|
3
|
+
export type { LayeredArchitectureOptions } from './layered.js';
|
|
4
|
+
export { layeredArchitecture } from './layered.js';
|
|
5
|
+
export type { DataLayerIsolationOptions } from './data-layer.js';
|
|
6
|
+
export { dataLayerIsolation } from './data-layer.js';
|
|
7
|
+
export type { StrictBoundariesOptions } from './boundaries.js';
|
|
8
|
+
export { strictBoundaries } from './boundaries.js';
|
|
9
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/presets/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,YAAY,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAA;AAClE,OAAO,EAAE,YAAY,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAA;AAEhF,YAAY,EAAE,0BAA0B,EAAE,MAAM,cAAc,CAAA;AAC9D,OAAO,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAA;AAElD,YAAY,EAAE,yBAAyB,EAAE,MAAM,iBAAiB,CAAA;AAChE,OAAO,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAA;AAEpD,YAAY,EAAE,uBAAuB,EAAE,MAAM,iBAAiB,CAAA;AAC9D,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAA"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { dispatchRule, validateOverrides, throwIfViolations } from './shared.js';
|
|
2
|
+
export { layeredArchitecture } from './layered.js';
|
|
3
|
+
export { dataLayerIsolation } from './data-layer.js';
|
|
4
|
+
export { strictBoundaries } from './boundaries.js';
|
|
5
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/presets/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAA;AAGhF,OAAO,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAA;AAGlD,OAAO,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAA;AAGpD,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAA"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { ArchProject } from '../core/project.js';
|
|
2
|
+
import type { ArchViolation } from '../core/violation.js';
|
|
3
|
+
import type { PresetBaseOptions } from './shared.js';
|
|
4
|
+
export interface LayeredArchitectureOptions extends PresetBaseOptions {
|
|
5
|
+
/** Layer name → glob pattern mapping. Order = dependency direction (first depends on second, etc.) */
|
|
6
|
+
layers: Record<string, string>;
|
|
7
|
+
/** Glob patterns for shared/utility folders accessible by all layers */
|
|
8
|
+
shared?: string[];
|
|
9
|
+
/** If true, innermost layer only imports from itself + shared */
|
|
10
|
+
strict?: boolean;
|
|
11
|
+
/** Layers where cross-layer type imports are allowed (value imports still forbidden) */
|
|
12
|
+
typeImportsAllowed?: string[];
|
|
13
|
+
/** Package restriction: glob → list of npm package name patterns. Only those layers may import those packages. */
|
|
14
|
+
restrictedPackages?: Record<string, string[]>;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Enforce a layered architecture: dependency direction, cycle freedom,
|
|
18
|
+
* and optional package restrictions.
|
|
19
|
+
*/
|
|
20
|
+
export declare function layeredArchitecture(p: ArchProject, options: LayeredArchitectureOptions): ArchViolation[];
|
|
21
|
+
//# sourceMappingURL=layered.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"layered.d.ts","sourceRoot":"","sources":["../../src/presets/layered.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAA;AACrD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAA;AAKzD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAA;AAGpD,MAAM,WAAW,0BAA2B,SAAQ,iBAAiB;IACnE,sGAAsG;IACtG,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAC9B,wEAAwE;IACxE,MAAM,CAAC,EAAE,MAAM,EAAE,CAAA;IACjB,iEAAiE;IACjE,MAAM,CAAC,EAAE,OAAO,CAAA;IAChB,wFAAwF;IACxF,kBAAkB,CAAC,EAAE,MAAM,EAAE,CAAA;IAC7B,kHAAkH;IAClH,kBAAkB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAA;CAC9C;AAiFD;;;GAGG;AACH,wBAAgB,mBAAmB,CACjC,CAAC,EAAE,WAAW,EACd,OAAO,EAAE,0BAA0B,GAClC,aAAa,EAAE,CAsEjB"}
|