@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,167 @@
|
|
|
1
|
+
import picomatch from 'picomatch';
|
|
2
|
+
/**
|
|
3
|
+
* Helper to create a per-element condition for ArchFunction.
|
|
4
|
+
*/
|
|
5
|
+
function functionCondition(description, predicate, messageFn) {
|
|
6
|
+
return {
|
|
7
|
+
description,
|
|
8
|
+
evaluate(elements, context) {
|
|
9
|
+
const violations = [];
|
|
10
|
+
for (const fn of elements) {
|
|
11
|
+
if (!predicate(fn)) {
|
|
12
|
+
violations.push({
|
|
13
|
+
rule: context.rule,
|
|
14
|
+
element: fn.getName() ?? '<anonymous>',
|
|
15
|
+
file: fn.getSourceFile().getFilePath(),
|
|
16
|
+
line: fn.getStartLineNumber(),
|
|
17
|
+
message: messageFn(fn),
|
|
18
|
+
because: context.because,
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
return violations;
|
|
23
|
+
},
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* The predicate set must be empty — no functions should match.
|
|
28
|
+
*
|
|
29
|
+
* If ANY functions exist after predicate filtering, each one
|
|
30
|
+
* becomes a violation.
|
|
31
|
+
*
|
|
32
|
+
* @example
|
|
33
|
+
* functions(project)
|
|
34
|
+
* .that().haveNameMatching(/^parse\w+Order$/)
|
|
35
|
+
* .should(notExist())
|
|
36
|
+
* .because('use shared parseOrder() utility instead')
|
|
37
|
+
*/
|
|
38
|
+
export function notExist() {
|
|
39
|
+
return {
|
|
40
|
+
description: 'not exist',
|
|
41
|
+
evaluate(elements, context) {
|
|
42
|
+
return elements.map((fn) => ({
|
|
43
|
+
rule: context.rule,
|
|
44
|
+
element: fn.getName() ?? '<anonymous>',
|
|
45
|
+
file: fn.getSourceFile().getFilePath(),
|
|
46
|
+
line: fn.getStartLineNumber(),
|
|
47
|
+
message: `${fn.getName() ?? '<anonymous>'} should not exist`,
|
|
48
|
+
because: context.because,
|
|
49
|
+
}));
|
|
50
|
+
},
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Functions must be exported from their module.
|
|
55
|
+
*/
|
|
56
|
+
export function beExported() {
|
|
57
|
+
return functionCondition('be exported', (fn) => fn.isExported(), (fn) => `${fn.getName() ?? '<anonymous>'} is not exported`);
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Functions must be async.
|
|
61
|
+
*/
|
|
62
|
+
export function beAsync() {
|
|
63
|
+
return functionCondition('be async', (fn) => fn.isAsync(), (fn) => `${fn.getName() ?? '<anonymous>'} is not async`);
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Functions must have a name matching the given pattern.
|
|
67
|
+
*/
|
|
68
|
+
export function haveNameMatching(pattern) {
|
|
69
|
+
return functionCondition(`have name matching ${String(pattern)}`, (fn) => {
|
|
70
|
+
const name = fn.getName();
|
|
71
|
+
return name !== undefined && pattern.test(name);
|
|
72
|
+
}, (fn) => `${fn.getName() ?? '<anonymous>'} does not have a name matching ${String(pattern)}`);
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Assert that at least one parameter of the function has a type matching
|
|
76
|
+
* the given matcher.
|
|
77
|
+
*
|
|
78
|
+
* Passes when at least one parameter satisfies `matcher`.
|
|
79
|
+
* Reports one violation per function that has no matching parameter.
|
|
80
|
+
*
|
|
81
|
+
* **Scope note:** This operates on the function's own parameter list only.
|
|
82
|
+
* Unlike the class-level counterpart, it does NOT scan set accessors
|
|
83
|
+
* because `collectFunctions()` excludes them.
|
|
84
|
+
*/
|
|
85
|
+
export function acceptParameterOfType(matcher) {
|
|
86
|
+
return functionCondition('accept parameter of matching type', (fn) => fn.getParameters().some((p) => matcher(p.getType())), (fn) => `${fn.getName() ?? '<anonymous>'} has no parameter with matching type`);
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Assert that NO parameter of the function has a type matching the given
|
|
90
|
+
* matcher.
|
|
91
|
+
*
|
|
92
|
+
* Reports one violation **per parameter** whose type satisfies `matcher`,
|
|
93
|
+
* with actionable messages including the parameter name and type.
|
|
94
|
+
*
|
|
95
|
+
* **Scope note:** This operates on the function's own parameter list only.
|
|
96
|
+
* Unlike the class-level counterpart, it does NOT scan set accessors
|
|
97
|
+
* because `collectFunctions()` excludes them.
|
|
98
|
+
*/
|
|
99
|
+
export function notAcceptParameterOfType(matcher) {
|
|
100
|
+
return {
|
|
101
|
+
description: 'not accept parameter of matching type',
|
|
102
|
+
evaluate(elements, context) {
|
|
103
|
+
const violations = [];
|
|
104
|
+
for (const fn of elements) {
|
|
105
|
+
const fnName = fn.getName() ?? '<anonymous>';
|
|
106
|
+
for (const param of fn.getParameters()) {
|
|
107
|
+
if (matcher(param.getType())) {
|
|
108
|
+
const paramName = param.getName();
|
|
109
|
+
const typeText = param.getType().getText();
|
|
110
|
+
violations.push({
|
|
111
|
+
rule: context.rule,
|
|
112
|
+
element: fnName,
|
|
113
|
+
file: fn.getSourceFile().getFilePath(),
|
|
114
|
+
line: fn.getStartLineNumber(),
|
|
115
|
+
message: `${fnName} parameter "${paramName}" has type "${typeText}"`,
|
|
116
|
+
because: context.because,
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
return violations;
|
|
122
|
+
},
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Functions must have a return type that satisfies the given TypeMatcher.
|
|
127
|
+
*
|
|
128
|
+
* Unlike the `haveReturnType` predicate (which filters with RegExp),
|
|
129
|
+
* this is a condition (assertion in `.should()`) that uses TypeMatcher
|
|
130
|
+
* for composability with `isString()`, `matching()`, `not()`, `exactly()`, etc.
|
|
131
|
+
*
|
|
132
|
+
* @example
|
|
133
|
+
* functions(project)
|
|
134
|
+
* .that().haveNameMatching(/^list/)
|
|
135
|
+
* .should().haveReturnTypeMatching(matching(/Collection/))
|
|
136
|
+
* .check()
|
|
137
|
+
*/
|
|
138
|
+
export function haveReturnTypeMatching(matcher) {
|
|
139
|
+
return functionCondition('have return type matching the expected type constraint', (fn) => matcher(fn.getReturnType()), (fn) => `${fn.getName() ?? '<anonymous>'} has return type '${fn.getReturnType().getText()}' which does not match the expected type constraint`);
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* Functions must reside in a file matching the glob.
|
|
143
|
+
* ArchFunction is not a ts-morph Node, so the generic structural condition
|
|
144
|
+
* cannot be used — this is the ArchFunction-specific equivalent.
|
|
145
|
+
*/
|
|
146
|
+
export function resideInFile(glob) {
|
|
147
|
+
const isMatch = picomatch(glob);
|
|
148
|
+
return functionCondition(`reside in file matching '${glob}'`, (fn) => isMatch(fn.getSourceFile().getFilePath()), (fn) => `${fn.getName() ?? '<anonymous>'} resides in '${fn.getSourceFile().getFilePath()}' which does not match '${glob}'`);
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* Functions must reside in a folder matching the glob.
|
|
152
|
+
* ArchFunction is not a ts-morph Node, so the generic structural condition
|
|
153
|
+
* cannot be used — this is the ArchFunction-specific equivalent.
|
|
154
|
+
*/
|
|
155
|
+
export function resideInFolder(glob) {
|
|
156
|
+
const isMatch = picomatch(glob);
|
|
157
|
+
return functionCondition(`reside in folder matching '${glob}'`, (fn) => {
|
|
158
|
+
const filePath = fn.getSourceFile().getFilePath();
|
|
159
|
+
const folder = filePath.substring(0, filePath.lastIndexOf('/'));
|
|
160
|
+
return isMatch(folder);
|
|
161
|
+
}, (fn) => {
|
|
162
|
+
const filePath = fn.getSourceFile().getFilePath();
|
|
163
|
+
const folder = filePath.substring(0, filePath.lastIndexOf('/'));
|
|
164
|
+
return `${fn.getName() ?? '<anonymous>'} resides in folder '${folder}' which does not match '${glob}'`;
|
|
165
|
+
});
|
|
166
|
+
}
|
|
167
|
+
//# sourceMappingURL=function.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"function.js","sourceRoot":"","sources":["../../src/conditions/function.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { Node } from 'ts-morph';
|
|
2
|
+
import type { Condition } from '@nielspeter/eess';
|
|
3
|
+
/**
|
|
4
|
+
* Create a condition that checks each element individually.
|
|
5
|
+
*
|
|
6
|
+
* The predicate function returns true if the element satisfies the condition.
|
|
7
|
+
* Elements that return false produce a violation using the message function.
|
|
8
|
+
*
|
|
9
|
+
* @param description - Human-readable condition description
|
|
10
|
+
* @param predicate - Returns true if element satisfies the condition
|
|
11
|
+
* @param messageFn - Produces a violation message for a failing element
|
|
12
|
+
*/
|
|
13
|
+
export declare function elementCondition<T extends Node>(description: string, predicate: (element: T) => boolean, messageFn: (element: T) => string): Condition<T>;
|
|
14
|
+
//# sourceMappingURL=helpers.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../../src/conditions/helpers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,UAAU,CAAA;AACpC,OAAO,KAAK,EAAE,SAAS,EAAoB,MAAM,kBAAkB,CAAA;AAInE;;;;;;;;;GASG;AACH,wBAAgB,gBAAgB,CAAC,CAAC,SAAS,IAAI,EAC7C,WAAW,EAAE,MAAM,EACnB,SAAS,EAAE,CAAC,OAAO,EAAE,CAAC,KAAK,OAAO,EAClC,SAAS,EAAE,CAAC,OAAO,EAAE,CAAC,KAAK,MAAM,GAChC,SAAS,CAAC,CAAC,CAAC,CAad"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { createViolation } from '../core/violation.js';
|
|
2
|
+
/**
|
|
3
|
+
* Create a condition that checks each element individually.
|
|
4
|
+
*
|
|
5
|
+
* The predicate function returns true if the element satisfies the condition.
|
|
6
|
+
* Elements that return false produce a violation using the message function.
|
|
7
|
+
*
|
|
8
|
+
* @param description - Human-readable condition description
|
|
9
|
+
* @param predicate - Returns true if element satisfies the condition
|
|
10
|
+
* @param messageFn - Produces a violation message for a failing element
|
|
11
|
+
*/
|
|
12
|
+
export function elementCondition(description, predicate, messageFn) {
|
|
13
|
+
return {
|
|
14
|
+
description,
|
|
15
|
+
evaluate(elements, context) {
|
|
16
|
+
const violations = [];
|
|
17
|
+
for (const element of elements) {
|
|
18
|
+
if (!predicate(element)) {
|
|
19
|
+
violations.push(createViolation(element, messageFn(element), context));
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
return violations;
|
|
23
|
+
},
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
//# sourceMappingURL=helpers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"helpers.js","sourceRoot":"","sources":["../../src/conditions/helpers.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAA;AAEtD;;;;;;;;;GASG;AACH,MAAM,UAAU,gBAAgB,CAC9B,WAAmB,EACnB,SAAkC,EAClC,SAAiC;IAEjC,OAAO;QACL,WAAW;QACX,QAAQ,CAAC,QAAa,EAAE,OAAyB;YAC/C,MAAM,UAAU,GAAoB,EAAE,CAAA;YACtC,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;gBAC/B,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,EAAE,CAAC;oBACxB,UAAU,CAAC,IAAI,CAAC,eAAe,CAAC,OAAO,EAAE,SAAS,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC,CAAC,CAAA;gBACxE,CAAC;YACH,CAAC;YACD,OAAO,UAAU,CAAA;QACnB,CAAC;KACF,CAAA;AACH,CAAC"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import type { Condition } from '@nielspeter/eess';
|
|
2
|
+
import type { ArchJsxElement } from '../models/arch-jsx-element.js';
|
|
3
|
+
/**
|
|
4
|
+
* The filtered JSX element set must be empty — no elements should match the predicates.
|
|
5
|
+
*
|
|
6
|
+
* @example
|
|
7
|
+
* jsxElements(p).that().areHtmlElements('button').should().notExist().check()
|
|
8
|
+
*/
|
|
9
|
+
export declare function notExist(): Condition<ArchJsxElement>;
|
|
10
|
+
/**
|
|
11
|
+
* Every matched element must have the named attribute.
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* jsxElements(p).that().areHtmlElements('img').should().haveAttribute('alt').check()
|
|
15
|
+
*/
|
|
16
|
+
export declare function haveAttribute(name: string): Condition<ArchJsxElement>;
|
|
17
|
+
/**
|
|
18
|
+
* No matched element may have the named attribute.
|
|
19
|
+
*
|
|
20
|
+
* @example
|
|
21
|
+
* jsxElements(p).should().notHaveAttribute('style').check()
|
|
22
|
+
*/
|
|
23
|
+
export declare function notHaveAttribute(name: string): Condition<ArchJsxElement>;
|
|
24
|
+
/**
|
|
25
|
+
* Every matched element must have the named attribute with a value matching
|
|
26
|
+
* the given string or regex.
|
|
27
|
+
*
|
|
28
|
+
* @example
|
|
29
|
+
* jsxElements(p).that().areHtmlElements('input').should().haveAttributeMatching('type', 'text').check()
|
|
30
|
+
*/
|
|
31
|
+
export declare function haveAttributeMatching(name: string, value: string | RegExp): Condition<ArchJsxElement>;
|
|
32
|
+
/**
|
|
33
|
+
* No matched element may have the named attribute matching the given value.
|
|
34
|
+
* Elements without the attribute pass.
|
|
35
|
+
*
|
|
36
|
+
* @example
|
|
37
|
+
* jsxElements(p).should().notHaveAttributeMatching('className', /hidden/).check()
|
|
38
|
+
*/
|
|
39
|
+
export declare function notHaveAttributeMatching(name: string, value: string | RegExp): Condition<ArchJsxElement>;
|
|
40
|
+
//# sourceMappingURL=jsx.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"jsx.d.ts","sourceRoot":"","sources":["../../src/conditions/jsx.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAoB,MAAM,kBAAkB,CAAA;AAGnE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAA;AAyBnE;;;;;GAKG;AACH,wBAAgB,QAAQ,IAAI,SAAS,CAAC,cAAc,CAAC,CASpD;AAED;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,CAAC,cAAc,CAAC,CAmBrE;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,CAAC,cAAc,CAAC,CAmBxE;AAED;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CACnC,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,MAAM,GAAG,MAAM,GACrB,SAAS,CAAC,cAAc,CAAC,CAuC3B;AAED;;;;;;GAMG;AACH,wBAAgB,wBAAwB,CACtC,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,MAAM,GAAG,MAAM,GACrB,SAAS,CAAC,cAAc,CAAC,CAuB3B"}
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
import { createViolation } from '../core/violation.js';
|
|
2
|
+
/**
|
|
3
|
+
* Create a violation from an ArchJsxElement.
|
|
4
|
+
*
|
|
5
|
+
* Delegates to the core createViolation() to get code frames, suggestions,
|
|
6
|
+
* and docs links. Overrides the element name with the JSX tag name.
|
|
7
|
+
*/
|
|
8
|
+
function createJsxViolation(element, message, context) {
|
|
9
|
+
const violation = createViolation(element.getNode(), message, {
|
|
10
|
+
rule: context.rule,
|
|
11
|
+
because: context.because,
|
|
12
|
+
suggestion: context.suggestion,
|
|
13
|
+
ruleId: context.ruleId,
|
|
14
|
+
docs: context.docs,
|
|
15
|
+
});
|
|
16
|
+
// Override element name with the JSX tag name (core helper walks ancestors
|
|
17
|
+
// which produces meaningless output for JSX nodes inside components)
|
|
18
|
+
return { ...violation, element: `<${element.getName()}>` };
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* The filtered JSX element set must be empty — no elements should match the predicates.
|
|
22
|
+
*
|
|
23
|
+
* @example
|
|
24
|
+
* jsxElements(p).that().areHtmlElements('button').should().notExist().check()
|
|
25
|
+
*/
|
|
26
|
+
export function notExist() {
|
|
27
|
+
return {
|
|
28
|
+
description: 'not exist',
|
|
29
|
+
evaluate(elements, context) {
|
|
30
|
+
return elements.map((el) => createJsxViolation(el, `<${el.getName()}> should not exist`, context));
|
|
31
|
+
},
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Every matched element must have the named attribute.
|
|
36
|
+
*
|
|
37
|
+
* @example
|
|
38
|
+
* jsxElements(p).that().areHtmlElements('img').should().haveAttribute('alt').check()
|
|
39
|
+
*/
|
|
40
|
+
export function haveAttribute(name) {
|
|
41
|
+
return {
|
|
42
|
+
description: `have attribute "${name}"`,
|
|
43
|
+
evaluate(elements, context) {
|
|
44
|
+
const violations = [];
|
|
45
|
+
for (const el of elements) {
|
|
46
|
+
if (!el.hasAttribute(name)) {
|
|
47
|
+
violations.push(createJsxViolation(el, `<${el.getName()}> is missing required attribute "${name}"`, context));
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
return violations;
|
|
51
|
+
},
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* No matched element may have the named attribute.
|
|
56
|
+
*
|
|
57
|
+
* @example
|
|
58
|
+
* jsxElements(p).should().notHaveAttribute('style').check()
|
|
59
|
+
*/
|
|
60
|
+
export function notHaveAttribute(name) {
|
|
61
|
+
return {
|
|
62
|
+
description: `not have attribute "${name}"`,
|
|
63
|
+
evaluate(elements, context) {
|
|
64
|
+
const violations = [];
|
|
65
|
+
for (const el of elements) {
|
|
66
|
+
if (el.hasAttribute(name)) {
|
|
67
|
+
violations.push(createJsxViolation(el, `<${el.getName()}> should not have attribute "${name}"`, context));
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
return violations;
|
|
71
|
+
},
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Every matched element must have the named attribute with a value matching
|
|
76
|
+
* the given string or regex.
|
|
77
|
+
*
|
|
78
|
+
* @example
|
|
79
|
+
* jsxElements(p).that().areHtmlElements('input').should().haveAttributeMatching('type', 'text').check()
|
|
80
|
+
*/
|
|
81
|
+
export function haveAttributeMatching(name, value) {
|
|
82
|
+
const valueDesc = typeof value === 'string' ? `"${value}"` : String(value);
|
|
83
|
+
return {
|
|
84
|
+
description: `have attribute "${name}" matching ${valueDesc}`,
|
|
85
|
+
evaluate(elements, context) {
|
|
86
|
+
const violations = [];
|
|
87
|
+
for (const el of elements) {
|
|
88
|
+
if (!el.hasAttribute(name)) {
|
|
89
|
+
violations.push(createJsxViolation(el, `<${el.getName()}> is missing attribute "${name}"`, context));
|
|
90
|
+
continue;
|
|
91
|
+
}
|
|
92
|
+
const attrValue = el.getAttribute(name);
|
|
93
|
+
if (attrValue === undefined) {
|
|
94
|
+
// Attribute is present but valueless (e.g. <input disabled />)
|
|
95
|
+
violations.push(createJsxViolation(el, `<${el.getName()}> attribute "${name}" is valueless, expected a value matching ${valueDesc}`, context));
|
|
96
|
+
continue;
|
|
97
|
+
}
|
|
98
|
+
const matches = typeof value === 'string' ? attrValue === value : value.test(attrValue);
|
|
99
|
+
if (!matches) {
|
|
100
|
+
violations.push(createJsxViolation(el, `<${el.getName()}> attribute "${name}" value "${attrValue}" does not match ${valueDesc}`, context));
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
return violations;
|
|
104
|
+
},
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* No matched element may have the named attribute matching the given value.
|
|
109
|
+
* Elements without the attribute pass.
|
|
110
|
+
*
|
|
111
|
+
* @example
|
|
112
|
+
* jsxElements(p).should().notHaveAttributeMatching('className', /hidden/).check()
|
|
113
|
+
*/
|
|
114
|
+
export function notHaveAttributeMatching(name, value) {
|
|
115
|
+
const valueDesc = typeof value === 'string' ? `"${value}"` : String(value);
|
|
116
|
+
return {
|
|
117
|
+
description: `not have attribute "${name}" matching ${valueDesc}`,
|
|
118
|
+
evaluate(elements, context) {
|
|
119
|
+
const violations = [];
|
|
120
|
+
for (const el of elements) {
|
|
121
|
+
const attrValue = el.getAttribute(name);
|
|
122
|
+
if (attrValue === undefined)
|
|
123
|
+
continue; // absent = pass
|
|
124
|
+
const matches = typeof value === 'string' ? attrValue === value : value.test(attrValue);
|
|
125
|
+
if (matches) {
|
|
126
|
+
violations.push(createJsxViolation(el, `<${el.getName()}> should not have attribute "${name}" matching ${valueDesc}`, context));
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
return violations;
|
|
130
|
+
},
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
//# sourceMappingURL=jsx.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"jsx.js","sourceRoot":"","sources":["../../src/conditions/jsx.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { type InterfaceDeclaration, type TypeAliasDeclaration, type ClassDeclaration } from 'ts-morph';
|
|
2
|
+
import type { Condition } from '@nielspeter/eess';
|
|
3
|
+
export type PropertyBearingNode = InterfaceDeclaration | TypeAliasDeclaration | ClassDeclaration;
|
|
4
|
+
/**
|
|
5
|
+
* Assert that all named properties exist on the element.
|
|
6
|
+
* Every name must be present — violation per missing name.
|
|
7
|
+
*
|
|
8
|
+
* @param names At least one property name required. Throws if called with zero arguments.
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* types(p).that().haveNameMatching(/Config$/)
|
|
12
|
+
* .should().havePropertyNamed('version', 'name')
|
|
13
|
+
* .check()
|
|
14
|
+
*/
|
|
15
|
+
export declare function havePropertyNamed(...names: string[]): Condition<PropertyBearingNode>;
|
|
16
|
+
/**
|
|
17
|
+
* Assert that none of the named properties exist on the element.
|
|
18
|
+
* Violation per element per forbidden name found.
|
|
19
|
+
*
|
|
20
|
+
* @param names At least one property name required. Throws if called with zero arguments.
|
|
21
|
+
*
|
|
22
|
+
* @example
|
|
23
|
+
* types(p).that().resideInFolder('src/api')
|
|
24
|
+
* .should().notHavePropertyNamed('offset', 'pageSize', 'page', 'size')
|
|
25
|
+
* .because('use skip/limit for pagination')
|
|
26
|
+
* .check()
|
|
27
|
+
*/
|
|
28
|
+
export declare function notHavePropertyNamed(...names: string[]): Condition<PropertyBearingNode>;
|
|
29
|
+
/**
|
|
30
|
+
* Assert at least one property name matches the regex.
|
|
31
|
+
* Semantics: EXISTS — violation if *no* property name matches.
|
|
32
|
+
*
|
|
33
|
+
* Note: this checks for existence of at least one match, unlike
|
|
34
|
+
* `havePropertyNamed(...names)` which requires ALL names to exist.
|
|
35
|
+
*
|
|
36
|
+
* @example
|
|
37
|
+
* types(p).that().haveNameMatching(/Entity$/)
|
|
38
|
+
* .should().havePropertyMatching(/^id$/)
|
|
39
|
+
* .check()
|
|
40
|
+
*/
|
|
41
|
+
export declare function havePropertyMatching(pattern: RegExp): Condition<PropertyBearingNode>;
|
|
42
|
+
/**
|
|
43
|
+
* Assert no property name matches the regex.
|
|
44
|
+
* Violation per matching property found.
|
|
45
|
+
*
|
|
46
|
+
* @example
|
|
47
|
+
* types(p).should().notHavePropertyMatching(/^(data|info|stuff|item)$/).check()
|
|
48
|
+
*/
|
|
49
|
+
export declare function notHavePropertyMatching(pattern: RegExp): Condition<PropertyBearingNode>;
|
|
50
|
+
/**
|
|
51
|
+
* Assert all properties are readonly.
|
|
52
|
+
*
|
|
53
|
+
* Checks direct declarations for explicit `readonly` keyword, and
|
|
54
|
+
* falls back to TypeScript compiler's CheckFlags for mapped types
|
|
55
|
+
* like Readonly<T>.
|
|
56
|
+
*
|
|
57
|
+
* @example
|
|
58
|
+
* types(p).that().resideInFolder('src/state')
|
|
59
|
+
* .should().haveOnlyReadonlyProperties()
|
|
60
|
+
* .because('state objects must be immutable')
|
|
61
|
+
* .check()
|
|
62
|
+
*/
|
|
63
|
+
export declare function haveOnlyReadonlyProperties(): Condition<PropertyBearingNode>;
|
|
64
|
+
/**
|
|
65
|
+
* Assert property count does not exceed the maximum.
|
|
66
|
+
* Detects god objects / oversized DTOs.
|
|
67
|
+
*
|
|
68
|
+
* @example
|
|
69
|
+
* types(p).should().maxProperties(15)
|
|
70
|
+
* .because('large interfaces indicate a missing abstraction')
|
|
71
|
+
* .check()
|
|
72
|
+
*/
|
|
73
|
+
export declare function maxProperties(max: number): Condition<PropertyBearingNode>;
|
|
74
|
+
//# sourceMappingURL=members.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"members.d.ts","sourceRoot":"","sources":["../../src/conditions/members.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,oBAAoB,EACzB,KAAK,oBAAoB,EACzB,KAAK,gBAAgB,EAEtB,MAAM,UAAU,CAAA;AACjB,OAAO,KAAK,EAAE,SAAS,EAAoB,MAAM,kBAAkB,CAAA;AAOnE,MAAM,MAAM,mBAAmB,GAAG,oBAAoB,GAAG,oBAAoB,GAAG,gBAAgB,CAAA;AA0DhG;;;;;;;;;;GAUG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,KAAK,EAAE,MAAM,EAAE,GAAG,SAAS,CAAC,mBAAmB,CAAC,CA2BpF;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,oBAAoB,CAAC,GAAG,KAAK,EAAE,MAAM,EAAE,GAAG,SAAS,CAAC,mBAAmB,CAAC,CA2BvF;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,MAAM,GAAG,SAAS,CAAC,mBAAmB,CAAC,CAWpF;AAED;;;;;;GAMG;AACH,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,MAAM,GAAG,SAAS,CAAC,mBAAmB,CAAC,CAwBvF;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,0BAA0B,IAAI,SAAS,CAAC,mBAAmB,CAAC,CAsB3E;AAED;;;;;;;;GAQG;AACH,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,CAAC,mBAAmB,CAAC,CAoBzE"}
|