@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,254 @@
|
|
|
1
|
+
import { RuleBuilder } from '@nielspeter/eess';
|
|
2
|
+
import { collectCalls } from '../models/arch-call.js';
|
|
3
|
+
import { haveNameMatching as identityHaveNameMatching, haveNameStartingWith as identityHaveNameStartingWith, haveNameEndingWith as identityHaveNameEndingWith, resideInFile as identityResideInFile, resideInFolder as identityResideInFolder, } from '../predicates/identity.js';
|
|
4
|
+
import { onObject as callOnObject, withMethod as callWithMethod, withArgMatching as callWithArgMatching, withStringArg as callWithStringArg, } from '../predicates/call.js';
|
|
5
|
+
import { haveCallbackContaining as conditionHaveCallbackContaining, notHaveCallbackContaining as conditionNotHaveCallbackContaining, notExist as callNotExist, haveArgumentWithProperty as conditionHaveArgumentWithProperty, notHaveArgumentWithProperty as conditionNotHaveArgumentWithProperty, haveArgumentContaining as conditionHaveArgumentContaining, notHaveArgumentContaining as conditionNotHaveArgumentContaining, } from '../conditions/call.js';
|
|
6
|
+
/**
|
|
7
|
+
* Rule builder for call-expression-level architecture rules.
|
|
8
|
+
*
|
|
9
|
+
* Operates on CallExpression nodes across all source files,
|
|
10
|
+
* wrapped in the ArchCall model for uniform predicate access.
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* ```typescript
|
|
14
|
+
* // All Express route handlers must call handleError()
|
|
15
|
+
* calls(project)
|
|
16
|
+
* .that().onObject('app')
|
|
17
|
+
* .and().withMethod(/^(get|post|put|delete|patch)$/)
|
|
18
|
+
* .should().haveCallbackContaining(call('handleError'))
|
|
19
|
+
* .because('unhandled errors crash the server')
|
|
20
|
+
* .check()
|
|
21
|
+
*
|
|
22
|
+
* // No route may call db.query() directly
|
|
23
|
+
* calls(project)
|
|
24
|
+
* .that().onObject('app')
|
|
25
|
+
* .and().withMethod(/^(get|post|put|delete|patch)$/)
|
|
26
|
+
* .should().notHaveCallbackContaining(call('db.query'))
|
|
27
|
+
* .because('use repository methods instead')
|
|
28
|
+
* .check()
|
|
29
|
+
*
|
|
30
|
+
* // Select specific routes by path pattern
|
|
31
|
+
* calls(project)
|
|
32
|
+
* .that().onObject('router')
|
|
33
|
+
* .and().withMethod('get')
|
|
34
|
+
* .and().withStringArg(0, '/api/users/**')
|
|
35
|
+
* .should().haveCallbackContaining(call('authenticate'))
|
|
36
|
+
* .check()
|
|
37
|
+
* ```
|
|
38
|
+
*/
|
|
39
|
+
export class CallRuleBuilder extends RuleBuilder {
|
|
40
|
+
/**
|
|
41
|
+
* Argument index to fold into the violation element/message. Set by
|
|
42
|
+
* `.identifiedByArg(index)`. Threaded into `ConditionContext.identifyByArgument`
|
|
43
|
+
* so the eight `archCall.getName()` sites in `src/conditions/call.ts`
|
|
44
|
+
* can build identity-keyed violation strings.
|
|
45
|
+
*
|
|
46
|
+
* Survives `fork()` via `Object.assign(fork, this)` in the base class
|
|
47
|
+
* (primitive field; no explicit copy needed). See plan 0057.
|
|
48
|
+
*/
|
|
49
|
+
_identifyByArgument;
|
|
50
|
+
getElements() {
|
|
51
|
+
return this.project.getSourceFiles().flatMap(collectCalls);
|
|
52
|
+
}
|
|
53
|
+
buildConditionContext() {
|
|
54
|
+
return {
|
|
55
|
+
...super.buildConditionContext(),
|
|
56
|
+
identifyByArgument: this._identifyByArgument,
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
// --- Identity predicates (subset: no areExported/areNotExported) ---
|
|
60
|
+
/**
|
|
61
|
+
* Filter to calls whose callee name matches the pattern.
|
|
62
|
+
* A string is compiled to a RegExp. For `app.get(...)` the name is `app.get`.
|
|
63
|
+
*/
|
|
64
|
+
haveNameMatching(pattern) {
|
|
65
|
+
return this.addPredicate(identityHaveNameMatching(pattern));
|
|
66
|
+
}
|
|
67
|
+
/** Filter to calls whose callee name starts with the given prefix. */
|
|
68
|
+
haveNameStartingWith(prefix) {
|
|
69
|
+
return this.addPredicate(identityHaveNameStartingWith(prefix));
|
|
70
|
+
}
|
|
71
|
+
/** Filter to calls whose callee name ends with the given suffix. */
|
|
72
|
+
haveNameEndingWith(suffix) {
|
|
73
|
+
return this.addPredicate(identityHaveNameEndingWith(suffix));
|
|
74
|
+
}
|
|
75
|
+
/** Filter to calls in a file whose absolute path matches the glob. */
|
|
76
|
+
resideInFile(glob) {
|
|
77
|
+
return this.addPredicate(identityResideInFile(glob));
|
|
78
|
+
}
|
|
79
|
+
/** Filter to calls in a folder whose path matches the glob. */
|
|
80
|
+
resideInFolder(glob) {
|
|
81
|
+
return this.addPredicate(identityResideInFolder(glob));
|
|
82
|
+
}
|
|
83
|
+
// Note: areExported() and areNotExported() are intentionally omitted.
|
|
84
|
+
// Call expressions cannot be exported. See spec section 5.1.
|
|
85
|
+
// --- Call-specific predicates ---
|
|
86
|
+
/**
|
|
87
|
+
* Filter to method calls on the object with the exact given name.
|
|
88
|
+
* For `app.get(...)` use `onObject('app')`; for `router.route.get(...)`
|
|
89
|
+
* use `onObject('router.route')`. Optional chaining is normalized.
|
|
90
|
+
*/
|
|
91
|
+
onObject(name) {
|
|
92
|
+
return this.addPredicate(callOnObject(name));
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Filter to calls whose method name matches. Accepts an exact string
|
|
96
|
+
* or a regex; also matches bare function calls (`handleError(...)`).
|
|
97
|
+
*/
|
|
98
|
+
withMethod(nameOrRegex) {
|
|
99
|
+
return this.addPredicate(callWithMethod(nameOrRegex));
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Filter to calls whose argument at `index` matches the pattern, tested
|
|
103
|
+
* against the argument's source text (so it matches identifiers and
|
|
104
|
+
* expressions, not just string literals).
|
|
105
|
+
*/
|
|
106
|
+
withArgMatching(index, pattern) {
|
|
107
|
+
return this.addPredicate(callWithArgMatching(index, pattern));
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Filter to calls whose argument at `index` is a string literal whose
|
|
111
|
+
* value matches the glob. Non-literal arguments (variables, expressions)
|
|
112
|
+
* never match.
|
|
113
|
+
*/
|
|
114
|
+
withStringArg(index, glob) {
|
|
115
|
+
return this.addPredicate(callWithStringArg(index, glob));
|
|
116
|
+
}
|
|
117
|
+
// --- Identity enrichment ---
|
|
118
|
+
/**
|
|
119
|
+
* Fold the indexed argument's source text into the violation
|
|
120
|
+
* `element` and `message`, so identity-keyed registrations (HTTP
|
|
121
|
+
* routes, event handlers, registry entries, etc.) can be excluded
|
|
122
|
+
* individually rather than only by file.
|
|
123
|
+
*
|
|
124
|
+
* When the indexed argument is a `StringLiteral` or
|
|
125
|
+
* `NoSubstitutionTemplateLiteral`, the violation reads
|
|
126
|
+
* `` `${callee}(${rawText})` `` (e.g. `app.post("/auth/token")`).
|
|
127
|
+
* Otherwise (template with substitutions, `as const`, parenthesized,
|
|
128
|
+
* identifier, spread, out-of-bounds, non-string literal) it degrades
|
|
129
|
+
* gracefully to the bare `${callee}` form.
|
|
130
|
+
*
|
|
131
|
+
* **Identity scope — predicates see the bare callee.** This method
|
|
132
|
+
* affects violation output and `.excluding()` matching only;
|
|
133
|
+
* predicates that read `archCall.getName()` (e.g. `haveNameMatching`,
|
|
134
|
+
* `haveNameStartingWith`) continue to see the bare `app.post`. To
|
|
135
|
+
* filter by argument value, use `.withStringArg(i, glob)` or
|
|
136
|
+
* `.withArgMatching(i, pattern)`.
|
|
137
|
+
*
|
|
138
|
+
* @example Filtering by path AND naming each violation by path:
|
|
139
|
+
* ```ts
|
|
140
|
+
* calls(p).that()
|
|
141
|
+
* .onObject('app').withMethod(/^(get|post)$/)
|
|
142
|
+
* .withStringArg(0, '/auth/**') // filter: only /auth routes
|
|
143
|
+
* .identifiedByArg(0) // identity: name violations by path
|
|
144
|
+
* .should().haveArgumentWithProperty('preHandler')
|
|
145
|
+
* .excluding(/"\/auth\/(login|register)"/)
|
|
146
|
+
* .check()
|
|
147
|
+
* ```
|
|
148
|
+
*
|
|
149
|
+
* @example Footgun — predicates do NOT see the enriched name:
|
|
150
|
+
* ```ts
|
|
151
|
+
* // This produces ZERO violations regardless of source — the
|
|
152
|
+
* // predicate sees bare "app.post", which never matches the regex.
|
|
153
|
+
* calls(p).that()
|
|
154
|
+
* .haveNameMatching(/app\.post\("\/auth/) // <-- never matches
|
|
155
|
+
* .identifiedByArg(0)
|
|
156
|
+
* .should()...
|
|
157
|
+
* ```
|
|
158
|
+
*
|
|
159
|
+
* See proposal 011 / plan 0057 for the full design, the 8-case
|
|
160
|
+
* generic-pattern table, and the edge-case behavior matrix.
|
|
161
|
+
*
|
|
162
|
+
* @param index — zero-based argument index to fold into the identity.
|
|
163
|
+
*/
|
|
164
|
+
identifiedByArg(index) {
|
|
165
|
+
this._identifyByArgument = index;
|
|
166
|
+
return this;
|
|
167
|
+
}
|
|
168
|
+
// --- Condition methods ---
|
|
169
|
+
/**
|
|
170
|
+
* Assert that the call's callback argument(s) contain a match.
|
|
171
|
+
*/
|
|
172
|
+
haveCallbackContaining(matcher) {
|
|
173
|
+
return this.addCondition(conditionHaveCallbackContaining(matcher));
|
|
174
|
+
}
|
|
175
|
+
/**
|
|
176
|
+
* Assert that the call's callback argument(s) do NOT contain a match.
|
|
177
|
+
*/
|
|
178
|
+
notHaveCallbackContaining(matcher) {
|
|
179
|
+
return this.addCondition(conditionNotHaveCallbackContaining(matcher));
|
|
180
|
+
}
|
|
181
|
+
/**
|
|
182
|
+
* The filtered call set must be empty.
|
|
183
|
+
*/
|
|
184
|
+
notExist() {
|
|
185
|
+
return this.addCondition(callNotExist());
|
|
186
|
+
}
|
|
187
|
+
/**
|
|
188
|
+
* Assert that at least one object literal argument has ALL named properties.
|
|
189
|
+
*/
|
|
190
|
+
haveArgumentWithProperty(...names) {
|
|
191
|
+
return this.addCondition(conditionHaveArgumentWithProperty(...names));
|
|
192
|
+
}
|
|
193
|
+
/**
|
|
194
|
+
* Assert that NO object literal argument has ANY of the named properties.
|
|
195
|
+
*/
|
|
196
|
+
notHaveArgumentWithProperty(...names) {
|
|
197
|
+
return this.addCondition(conditionNotHaveArgumentWithProperty(...names));
|
|
198
|
+
}
|
|
199
|
+
/**
|
|
200
|
+
* Assert that at least one argument subtree contains a match.
|
|
201
|
+
*
|
|
202
|
+
* Searches ALL arguments recursively — a superset of `haveCallbackContaining`.
|
|
203
|
+
* Use `haveCallbackContaining` when you only want to search callback bodies.
|
|
204
|
+
*/
|
|
205
|
+
haveArgumentContaining(matcher) {
|
|
206
|
+
return this.addCondition(conditionHaveArgumentContaining(matcher));
|
|
207
|
+
}
|
|
208
|
+
/**
|
|
209
|
+
* Assert that NO argument subtree contains a match.
|
|
210
|
+
*
|
|
211
|
+
* Searches ALL arguments recursively — a superset of `notHaveCallbackContaining`.
|
|
212
|
+
* Use `notHaveCallbackContaining` when you only want to search callback bodies.
|
|
213
|
+
*/
|
|
214
|
+
notHaveArgumentContaining(matcher) {
|
|
215
|
+
return this.addCondition(conditionNotHaveArgumentContaining(matcher));
|
|
216
|
+
}
|
|
217
|
+
// --- Public accessors (used by plan 0015 within()) ---
|
|
218
|
+
/**
|
|
219
|
+
* Get the underlying ArchProject.
|
|
220
|
+
* Used by within() to create scoped builders.
|
|
221
|
+
*/
|
|
222
|
+
getProject() {
|
|
223
|
+
return this.project;
|
|
224
|
+
}
|
|
225
|
+
/**
|
|
226
|
+
* Get the ArchCall elements that match the current predicate chain.
|
|
227
|
+
* Used by within() to extract callbacks from matched calls.
|
|
228
|
+
*/
|
|
229
|
+
getMatchedCalls() {
|
|
230
|
+
return this.getElements().filter((archCall) => this._predicates.every((p) => p.test(archCall)));
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
/**
|
|
234
|
+
* Entry point for call-expression architecture rules.
|
|
235
|
+
*
|
|
236
|
+
* Scans all source files in the project for CallExpression nodes
|
|
237
|
+
* and wraps them in ArchCall for predicate/condition evaluation.
|
|
238
|
+
*
|
|
239
|
+
* @example
|
|
240
|
+
* ```typescript
|
|
241
|
+
* import { project, calls, call } from '@nielspeter/eess-ts'
|
|
242
|
+
*
|
|
243
|
+
* const p = project('tsconfig.json')
|
|
244
|
+
*
|
|
245
|
+
* calls(p)
|
|
246
|
+
* .that().onObject('app').and().withMethod('get')
|
|
247
|
+
* .should().haveCallbackContaining(call('authenticate'))
|
|
248
|
+
* .check()
|
|
249
|
+
* ```
|
|
250
|
+
*/
|
|
251
|
+
export function calls(p) {
|
|
252
|
+
return new CallRuleBuilder(p);
|
|
253
|
+
}
|
|
254
|
+
//# sourceMappingURL=call-rule-builder.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"call-rule-builder.js","sourceRoot":"","sources":["../../src/builders/call-rule-builder.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
import type { ClassDeclaration } from 'ts-morph';
|
|
2
|
+
import { RuleBuilder } from '@nielspeter/eess';
|
|
3
|
+
import type { ArchProject } from '../core/project.js';
|
|
4
|
+
import type { ExpressionMatcher } from '../helpers/matchers.js';
|
|
5
|
+
import type { TypeMatcher } from '../helpers/type-matchers.js';
|
|
6
|
+
/**
|
|
7
|
+
* Rule builder for ClassDeclaration elements.
|
|
8
|
+
*
|
|
9
|
+
* Created by the `classes(p)` entry point. Provides class-specific
|
|
10
|
+
* predicates and conditions alongside the identity predicates and
|
|
11
|
+
* structural conditions from the foundation plans.
|
|
12
|
+
*/
|
|
13
|
+
export declare class ClassRuleBuilder extends RuleBuilder<ClassDeclaration, ArchProject> {
|
|
14
|
+
constructor(project: ArchProject);
|
|
15
|
+
protected getElements(): ClassDeclaration[];
|
|
16
|
+
/**
|
|
17
|
+
* After `.that()`: filter classes whose name matches the pattern.
|
|
18
|
+
* After `.should()`: assert matched classes have names matching the pattern.
|
|
19
|
+
*/
|
|
20
|
+
haveNameMatching(pattern: RegExp | string): this;
|
|
21
|
+
/** Filter to classes whose name starts with the given prefix. */
|
|
22
|
+
haveNameStartingWith(prefix: string): this;
|
|
23
|
+
/** Filter to classes whose name ends with the given suffix. */
|
|
24
|
+
haveNameEndingWith(suffix: string): this;
|
|
25
|
+
/**
|
|
26
|
+
* After `.that()`: filter classes that reside in a file matching the glob.
|
|
27
|
+
* After `.should()`: assert matched classes reside in a file matching the glob.
|
|
28
|
+
*/
|
|
29
|
+
resideInFile(glob: string): this;
|
|
30
|
+
/**
|
|
31
|
+
* After `.that()`: filter classes that reside in a folder matching the glob.
|
|
32
|
+
* After `.should()`: assert matched classes reside in a folder matching the glob.
|
|
33
|
+
*/
|
|
34
|
+
resideInFolder(glob: string): this;
|
|
35
|
+
/** Filter to classes that are exported from their module. */
|
|
36
|
+
areExported(): this;
|
|
37
|
+
/** Filter to classes that are NOT exported from their module. */
|
|
38
|
+
areNotExported(): this;
|
|
39
|
+
/**
|
|
40
|
+
* After `.that()`: filter classes that extend the given class.
|
|
41
|
+
* After `.should()`: assert matched classes extend the given class.
|
|
42
|
+
*/
|
|
43
|
+
extend(className: string): this;
|
|
44
|
+
/**
|
|
45
|
+
* After `.that()`: filter classes that implement the given interface.
|
|
46
|
+
* After `.should()`: assert matched classes implement the given interface.
|
|
47
|
+
*/
|
|
48
|
+
implement(interfaceName: string): this;
|
|
49
|
+
/** Filter to classes decorated with `@name` (e.g. `haveDecorator('Controller')`). */
|
|
50
|
+
haveDecorator(name: string): this;
|
|
51
|
+
/** Filter to classes that have a decorator whose name matches the regex. */
|
|
52
|
+
haveDecoratorMatching(regex: RegExp): this;
|
|
53
|
+
/** Filter to classes declared `abstract`. */
|
|
54
|
+
areAbstract(): this;
|
|
55
|
+
/**
|
|
56
|
+
* After `.that()`: filter classes that have a method with the given name.
|
|
57
|
+
* After `.should()`: assert matched classes have a method with the given name.
|
|
58
|
+
*/
|
|
59
|
+
haveMethodNamed(name: string): this;
|
|
60
|
+
/** Filter to classes that declare at least one method whose name matches the regex. */
|
|
61
|
+
haveMethodMatching(regex: RegExp): this;
|
|
62
|
+
/** Filter to classes that declare a property with the given name. */
|
|
63
|
+
havePropertyNamed(name: string): this;
|
|
64
|
+
/** @deprecated Use `resideInFile()` after `.should()` instead. */
|
|
65
|
+
shouldResideInFile(glob: string): this;
|
|
66
|
+
/** @deprecated Use `resideInFolder()` after `.should()` instead. */
|
|
67
|
+
shouldResideInFolder(glob: string): this;
|
|
68
|
+
/** Assert that matched classes are exported from their module. */
|
|
69
|
+
beExported(): this;
|
|
70
|
+
/** Assert that the filtered class set is empty (no matched class may exist). */
|
|
71
|
+
notExist(): this;
|
|
72
|
+
/** @deprecated Use `haveNameMatching()` after `.should()` instead. */
|
|
73
|
+
conditionHaveNameMatching(pattern: RegExp): this;
|
|
74
|
+
/** @deprecated Use `extend()` after `.should()` instead. */
|
|
75
|
+
shouldExtend(className: string): this;
|
|
76
|
+
/** @deprecated Use `implement()` after `.should()` instead. */
|
|
77
|
+
shouldImplement(interfaceName: string): this;
|
|
78
|
+
/** @deprecated Use `haveMethodNamed()` after `.should()` instead. */
|
|
79
|
+
shouldHaveMethodNamed(name: string): this;
|
|
80
|
+
/** Assert that no matched class declares a method whose name matches the regex. */
|
|
81
|
+
shouldNotHaveMethodMatching(regex: RegExp): this;
|
|
82
|
+
/** Assert that every matched class has all of the named properties (one violation per missing name). */
|
|
83
|
+
shouldHavePropertyNamed(...names: string[]): this;
|
|
84
|
+
/** Assert that no matched class has any of the named properties (one violation per forbidden name found). */
|
|
85
|
+
shouldNotHavePropertyNamed(...names: string[]): this;
|
|
86
|
+
/** Assert that every matched class has at least one property whose name matches the regex. */
|
|
87
|
+
havePropertyMatching(pattern: RegExp): this;
|
|
88
|
+
/** Assert that no matched class has a property whose name matches the regex (one violation per match). */
|
|
89
|
+
notHavePropertyMatching(pattern: RegExp): this;
|
|
90
|
+
/** Assert that every property of each matched class is `readonly` (resolves `Readonly<T>` too). */
|
|
91
|
+
haveOnlyReadonlyProperties(): this;
|
|
92
|
+
/** Assert that no matched class has more than `max` properties (guards against god objects). */
|
|
93
|
+
maxProperties(max: number): this;
|
|
94
|
+
/**
|
|
95
|
+
* Assert that each matched class has at least one parameter whose type
|
|
96
|
+
* satisfies the matcher, scanning constructor, method, and set-accessor
|
|
97
|
+
* parameters.
|
|
98
|
+
*/
|
|
99
|
+
acceptParameterOfType(matcher: TypeMatcher): this;
|
|
100
|
+
/**
|
|
101
|
+
* Assert that no constructor, method, or set-accessor parameter of any
|
|
102
|
+
* matched class has a type satisfying the matcher (one violation per
|
|
103
|
+
* offending parameter).
|
|
104
|
+
*/
|
|
105
|
+
notAcceptParameterOfType(matcher: TypeMatcher): this;
|
|
106
|
+
/**
|
|
107
|
+
* Assert that the class body contains at least one match.
|
|
108
|
+
* "Body" = all method bodies, constructor, getters, setters combined.
|
|
109
|
+
*/
|
|
110
|
+
contain(matcher: ExpressionMatcher): this;
|
|
111
|
+
/**
|
|
112
|
+
* Assert that the class body does NOT contain any match.
|
|
113
|
+
* Produces one violation per matching node found.
|
|
114
|
+
*/
|
|
115
|
+
notContain(matcher: ExpressionMatcher): this;
|
|
116
|
+
/**
|
|
117
|
+
* Assert: must NOT contain 'bad' AND must contain 'good'.
|
|
118
|
+
* Better violation messages than combining notContain + contain separately.
|
|
119
|
+
*/
|
|
120
|
+
useInsteadOf(bad: ExpressionMatcher, good: ExpressionMatcher): this;
|
|
121
|
+
/**
|
|
122
|
+
* Assert that matched classes do not have empty bodies (zero members).
|
|
123
|
+
*/
|
|
124
|
+
notHaveEmptyBody(): this;
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Entry point for class architecture rules.
|
|
128
|
+
*
|
|
129
|
+
* Returns a `ClassRuleBuilder` that operates on all `ClassDeclaration`
|
|
130
|
+
* nodes across the project's source files.
|
|
131
|
+
*
|
|
132
|
+
* @example
|
|
133
|
+
* classes(p).that().extend('BaseService').should().beExported().check()
|
|
134
|
+
*/
|
|
135
|
+
export declare function classes(project: ArchProject): ClassRuleBuilder;
|
|
136
|
+
//# sourceMappingURL=class-rule-builder.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"class-rule-builder.d.ts","sourceRoot":"","sources":["../../src/builders/class-rule-builder.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,253 @@
|
|
|
1
|
+
import { RuleBuilder } from '@nielspeter/eess';
|
|
2
|
+
import { classContain, classNotContain, classUseInsteadOf, classNotHaveEmptyBody, } from '../conditions/body-analysis.js';
|
|
3
|
+
// Identity predicates (plan 0003)
|
|
4
|
+
import { haveNameMatching as identityHaveNameMatching, haveNameStartingWith as identityHaveNameStartingWith, haveNameEndingWith as identityHaveNameEndingWith, resideInFile as predicateResideInFile, resideInFolder as predicateResideInFolder, areExported as identityAreExported, areNotExported as identityAreNotExported, } from '../predicates/identity.js';
|
|
5
|
+
// Class-specific predicates (this plan)
|
|
6
|
+
import { extend as predicateExtend, implement as predicateImplement, haveDecorator as predicateHaveDecorator, haveDecoratorMatching as predicateHaveDecoratorMatching, areAbstract as predicateAreAbstract, haveMethodNamed as predicateHaveMethodNamed, haveMethodMatching as predicateHaveMethodMatching, havePropertyNamed as predicateHavePropertyNamed, } from '../predicates/class.js';
|
|
7
|
+
// Structural conditions (plan 0004)
|
|
8
|
+
import { resideInFile as conditionResideInFile, resideInFolder as conditionResideInFolder, haveNameMatching as conditionHaveNameMatching, beExported as conditionBeExported, notExist as conditionNotExist, } from '../conditions/structural.js';
|
|
9
|
+
// Class-specific conditions (this plan)
|
|
10
|
+
import { shouldExtend as conditionExtend, shouldImplement as conditionImplement, shouldHaveMethodNamed as conditionHaveMethodNamed, shouldNotHaveMethodMatching as conditionNotHaveMethodMatching, acceptParameterOfType as conditionAcceptParameterOfType, notAcceptParameterOfType as conditionNotAcceptParameterOfType, } from '../conditions/class.js';
|
|
11
|
+
// Member property conditions (plan 0030)
|
|
12
|
+
import { havePropertyNamed as memberHavePropertyNamed, notHavePropertyNamed as memberNotHavePropertyNamed, havePropertyMatching as memberHavePropertyMatching, notHavePropertyMatching as memberNotHavePropertyMatching, haveOnlyReadonlyProperties as memberHaveOnlyReadonlyProperties, maxProperties as memberMaxProperties, } from '../conditions/members.js';
|
|
13
|
+
/**
|
|
14
|
+
* Rule builder for ClassDeclaration elements.
|
|
15
|
+
*
|
|
16
|
+
* Created by the `classes(p)` entry point. Provides class-specific
|
|
17
|
+
* predicates and conditions alongside the identity predicates and
|
|
18
|
+
* structural conditions from the foundation plans.
|
|
19
|
+
*/
|
|
20
|
+
export class ClassRuleBuilder extends RuleBuilder {
|
|
21
|
+
constructor(project) {
|
|
22
|
+
super(project);
|
|
23
|
+
}
|
|
24
|
+
getElements() {
|
|
25
|
+
const classes = [];
|
|
26
|
+
for (const sourceFile of this.project.getSourceFiles()) {
|
|
27
|
+
classes.push(...sourceFile.getClasses());
|
|
28
|
+
}
|
|
29
|
+
return classes;
|
|
30
|
+
}
|
|
31
|
+
// --- Identity predicate methods (plan 0003) ---
|
|
32
|
+
/**
|
|
33
|
+
* After `.that()`: filter classes whose name matches the pattern.
|
|
34
|
+
* After `.should()`: assert matched classes have names matching the pattern.
|
|
35
|
+
*/
|
|
36
|
+
haveNameMatching(pattern) {
|
|
37
|
+
if (this._phase === 'condition') {
|
|
38
|
+
const regex = typeof pattern === 'string' ? new RegExp(pattern) : pattern;
|
|
39
|
+
return this.addCondition(conditionHaveNameMatching(regex));
|
|
40
|
+
}
|
|
41
|
+
return this.addPredicate(identityHaveNameMatching(pattern));
|
|
42
|
+
}
|
|
43
|
+
/** Filter to classes whose name starts with the given prefix. */
|
|
44
|
+
haveNameStartingWith(prefix) {
|
|
45
|
+
return this.addPredicate(identityHaveNameStartingWith(prefix));
|
|
46
|
+
}
|
|
47
|
+
/** Filter to classes whose name ends with the given suffix. */
|
|
48
|
+
haveNameEndingWith(suffix) {
|
|
49
|
+
return this.addPredicate(identityHaveNameEndingWith(suffix));
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* After `.that()`: filter classes that reside in a file matching the glob.
|
|
53
|
+
* After `.should()`: assert matched classes reside in a file matching the glob.
|
|
54
|
+
*/
|
|
55
|
+
resideInFile(glob) {
|
|
56
|
+
if (this._phase === 'condition') {
|
|
57
|
+
return this.addCondition(conditionResideInFile(glob));
|
|
58
|
+
}
|
|
59
|
+
return this.addPredicate(predicateResideInFile(glob));
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* After `.that()`: filter classes that reside in a folder matching the glob.
|
|
63
|
+
* After `.should()`: assert matched classes reside in a folder matching the glob.
|
|
64
|
+
*/
|
|
65
|
+
resideInFolder(glob) {
|
|
66
|
+
if (this._phase === 'condition') {
|
|
67
|
+
return this.addCondition(conditionResideInFolder(glob));
|
|
68
|
+
}
|
|
69
|
+
return this.addPredicate(predicateResideInFolder(glob));
|
|
70
|
+
}
|
|
71
|
+
/** Filter to classes that are exported from their module. */
|
|
72
|
+
areExported() {
|
|
73
|
+
return this.addPredicate(identityAreExported());
|
|
74
|
+
}
|
|
75
|
+
/** Filter to classes that are NOT exported from their module. */
|
|
76
|
+
areNotExported() {
|
|
77
|
+
return this.addPredicate(identityAreNotExported());
|
|
78
|
+
}
|
|
79
|
+
// --- Class-specific predicate methods ---
|
|
80
|
+
/**
|
|
81
|
+
* After `.that()`: filter classes that extend the given class.
|
|
82
|
+
* After `.should()`: assert matched classes extend the given class.
|
|
83
|
+
*/
|
|
84
|
+
extend(className) {
|
|
85
|
+
if (this._phase === 'condition') {
|
|
86
|
+
return this.addCondition(conditionExtend(className));
|
|
87
|
+
}
|
|
88
|
+
return this.addPredicate(predicateExtend(className));
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* After `.that()`: filter classes that implement the given interface.
|
|
92
|
+
* After `.should()`: assert matched classes implement the given interface.
|
|
93
|
+
*/
|
|
94
|
+
implement(interfaceName) {
|
|
95
|
+
if (this._phase === 'condition') {
|
|
96
|
+
return this.addCondition(conditionImplement(interfaceName));
|
|
97
|
+
}
|
|
98
|
+
return this.addPredicate(predicateImplement(interfaceName));
|
|
99
|
+
}
|
|
100
|
+
/** Filter to classes decorated with `@name` (e.g. `haveDecorator('Controller')`). */
|
|
101
|
+
haveDecorator(name) {
|
|
102
|
+
return this.addPredicate(predicateHaveDecorator(name));
|
|
103
|
+
}
|
|
104
|
+
/** Filter to classes that have a decorator whose name matches the regex. */
|
|
105
|
+
haveDecoratorMatching(regex) {
|
|
106
|
+
return this.addPredicate(predicateHaveDecoratorMatching(regex));
|
|
107
|
+
}
|
|
108
|
+
/** Filter to classes declared `abstract`. */
|
|
109
|
+
areAbstract() {
|
|
110
|
+
return this.addPredicate(predicateAreAbstract());
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* After `.that()`: filter classes that have a method with the given name.
|
|
114
|
+
* After `.should()`: assert matched classes have a method with the given name.
|
|
115
|
+
*/
|
|
116
|
+
haveMethodNamed(name) {
|
|
117
|
+
if (this._phase === 'condition') {
|
|
118
|
+
return this.addCondition(conditionHaveMethodNamed(name));
|
|
119
|
+
}
|
|
120
|
+
return this.addPredicate(predicateHaveMethodNamed(name));
|
|
121
|
+
}
|
|
122
|
+
/** Filter to classes that declare at least one method whose name matches the regex. */
|
|
123
|
+
haveMethodMatching(regex) {
|
|
124
|
+
return this.addPredicate(predicateHaveMethodMatching(regex));
|
|
125
|
+
}
|
|
126
|
+
/** Filter to classes that declare a property with the given name. */
|
|
127
|
+
havePropertyNamed(name) {
|
|
128
|
+
return this.addPredicate(predicateHavePropertyNamed(name));
|
|
129
|
+
}
|
|
130
|
+
// --- Structural condition methods (plan 0004) ---
|
|
131
|
+
/** @deprecated Use `resideInFile()` after `.should()` instead. */
|
|
132
|
+
shouldResideInFile(glob) {
|
|
133
|
+
return this.addCondition(conditionResideInFile(glob));
|
|
134
|
+
}
|
|
135
|
+
/** @deprecated Use `resideInFolder()` after `.should()` instead. */
|
|
136
|
+
shouldResideInFolder(glob) {
|
|
137
|
+
return this.addCondition(conditionResideInFolder(glob));
|
|
138
|
+
}
|
|
139
|
+
/** Assert that matched classes are exported from their module. */
|
|
140
|
+
beExported() {
|
|
141
|
+
return this.addCondition(conditionBeExported());
|
|
142
|
+
}
|
|
143
|
+
/** Assert that the filtered class set is empty (no matched class may exist). */
|
|
144
|
+
notExist() {
|
|
145
|
+
return this.addCondition(conditionNotExist());
|
|
146
|
+
}
|
|
147
|
+
/** @deprecated Use `haveNameMatching()` after `.should()` instead. */
|
|
148
|
+
conditionHaveNameMatching(pattern) {
|
|
149
|
+
return this.addCondition(conditionHaveNameMatching(pattern));
|
|
150
|
+
}
|
|
151
|
+
// --- Class-specific condition methods ---
|
|
152
|
+
/** @deprecated Use `extend()` after `.should()` instead. */
|
|
153
|
+
shouldExtend(className) {
|
|
154
|
+
return this.addCondition(conditionExtend(className));
|
|
155
|
+
}
|
|
156
|
+
/** @deprecated Use `implement()` after `.should()` instead. */
|
|
157
|
+
shouldImplement(interfaceName) {
|
|
158
|
+
return this.addCondition(conditionImplement(interfaceName));
|
|
159
|
+
}
|
|
160
|
+
/** @deprecated Use `haveMethodNamed()` after `.should()` instead. */
|
|
161
|
+
shouldHaveMethodNamed(name) {
|
|
162
|
+
return this.addCondition(conditionHaveMethodNamed(name));
|
|
163
|
+
}
|
|
164
|
+
/** Assert that no matched class declares a method whose name matches the regex. */
|
|
165
|
+
shouldNotHaveMethodMatching(regex) {
|
|
166
|
+
return this.addCondition(conditionNotHaveMethodMatching(regex));
|
|
167
|
+
}
|
|
168
|
+
// --- Member property condition methods (plan 0030) ---
|
|
169
|
+
// "should" prefix: predicate havePropertyNamed(name) exists on this builder
|
|
170
|
+
/** Assert that every matched class has all of the named properties (one violation per missing name). */
|
|
171
|
+
shouldHavePropertyNamed(...names) {
|
|
172
|
+
return this.addCondition(memberHavePropertyNamed(...names));
|
|
173
|
+
}
|
|
174
|
+
/** Assert that no matched class has any of the named properties (one violation per forbidden name found). */
|
|
175
|
+
shouldNotHavePropertyNamed(...names) {
|
|
176
|
+
return this.addCondition(memberNotHavePropertyNamed(...names));
|
|
177
|
+
}
|
|
178
|
+
// No "should" prefix: no predicate collision (matches beExported, notExist, contain pattern)
|
|
179
|
+
/** Assert that every matched class has at least one property whose name matches the regex. */
|
|
180
|
+
havePropertyMatching(pattern) {
|
|
181
|
+
return this.addCondition(memberHavePropertyMatching(pattern));
|
|
182
|
+
}
|
|
183
|
+
/** Assert that no matched class has a property whose name matches the regex (one violation per match). */
|
|
184
|
+
notHavePropertyMatching(pattern) {
|
|
185
|
+
return this.addCondition(memberNotHavePropertyMatching(pattern));
|
|
186
|
+
}
|
|
187
|
+
/** Assert that every property of each matched class is `readonly` (resolves `Readonly<T>` too). */
|
|
188
|
+
haveOnlyReadonlyProperties() {
|
|
189
|
+
return this.addCondition(memberHaveOnlyReadonlyProperties());
|
|
190
|
+
}
|
|
191
|
+
/** Assert that no matched class has more than `max` properties (guards against god objects). */
|
|
192
|
+
maxProperties(max) {
|
|
193
|
+
return this.addCondition(memberMaxProperties(max));
|
|
194
|
+
}
|
|
195
|
+
// --- Parameter type condition methods (plan 0031) ---
|
|
196
|
+
/**
|
|
197
|
+
* Assert that each matched class has at least one parameter whose type
|
|
198
|
+
* satisfies the matcher, scanning constructor, method, and set-accessor
|
|
199
|
+
* parameters.
|
|
200
|
+
*/
|
|
201
|
+
acceptParameterOfType(matcher) {
|
|
202
|
+
return this.addCondition(conditionAcceptParameterOfType(matcher));
|
|
203
|
+
}
|
|
204
|
+
/**
|
|
205
|
+
* Assert that no constructor, method, or set-accessor parameter of any
|
|
206
|
+
* matched class has a type satisfying the matcher (one violation per
|
|
207
|
+
* offending parameter).
|
|
208
|
+
*/
|
|
209
|
+
notAcceptParameterOfType(matcher) {
|
|
210
|
+
return this.addCondition(conditionNotAcceptParameterOfType(matcher));
|
|
211
|
+
}
|
|
212
|
+
// --- Body analysis condition methods (plan 0011) ---
|
|
213
|
+
/**
|
|
214
|
+
* Assert that the class body contains at least one match.
|
|
215
|
+
* "Body" = all method bodies, constructor, getters, setters combined.
|
|
216
|
+
*/
|
|
217
|
+
contain(matcher) {
|
|
218
|
+
return this.addCondition(classContain(matcher));
|
|
219
|
+
}
|
|
220
|
+
/**
|
|
221
|
+
* Assert that the class body does NOT contain any match.
|
|
222
|
+
* Produces one violation per matching node found.
|
|
223
|
+
*/
|
|
224
|
+
notContain(matcher) {
|
|
225
|
+
return this.addCondition(classNotContain(matcher));
|
|
226
|
+
}
|
|
227
|
+
/**
|
|
228
|
+
* Assert: must NOT contain 'bad' AND must contain 'good'.
|
|
229
|
+
* Better violation messages than combining notContain + contain separately.
|
|
230
|
+
*/
|
|
231
|
+
useInsteadOf(bad, good) {
|
|
232
|
+
return this.addCondition(classUseInsteadOf(bad, good));
|
|
233
|
+
}
|
|
234
|
+
/**
|
|
235
|
+
* Assert that matched classes do not have empty bodies (zero members).
|
|
236
|
+
*/
|
|
237
|
+
notHaveEmptyBody() {
|
|
238
|
+
return this.addCondition(classNotHaveEmptyBody());
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
/**
|
|
242
|
+
* Entry point for class architecture rules.
|
|
243
|
+
*
|
|
244
|
+
* Returns a `ClassRuleBuilder` that operates on all `ClassDeclaration`
|
|
245
|
+
* nodes across the project's source files.
|
|
246
|
+
*
|
|
247
|
+
* @example
|
|
248
|
+
* classes(p).that().extend('BaseService').should().beExported().check()
|
|
249
|
+
*/
|
|
250
|
+
export function classes(project) {
|
|
251
|
+
return new ClassRuleBuilder(project);
|
|
252
|
+
}
|
|
253
|
+
//# sourceMappingURL=class-rule-builder.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"class-rule-builder.js","sourceRoot":"","sources":["../../src/builders/class-rule-builder.ts"],"names":[],"mappings":"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"}
|