camouf 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 +346 -0
- package/dist/cli/commands/analyze.d.ts +8 -0
- package/dist/cli/commands/analyze.d.ts.map +1 -0
- package/dist/cli/commands/analyze.js +81 -0
- package/dist/cli/commands/analyze.js.map +1 -0
- package/dist/cli/commands/init.d.ts +9 -0
- package/dist/cli/commands/init.d.ts.map +1 -0
- package/dist/cli/commands/init.js +104 -0
- package/dist/cli/commands/init.js.map +1 -0
- package/dist/cli/commands/report.d.ts +8 -0
- package/dist/cli/commands/report.d.ts.map +1 -0
- package/dist/cli/commands/report.js +63 -0
- package/dist/cli/commands/report.js.map +1 -0
- package/dist/cli/commands/validate.d.ts +9 -0
- package/dist/cli/commands/validate.d.ts.map +1 -0
- package/dist/cli/commands/validate.js +87 -0
- package/dist/cli/commands/validate.js.map +1 -0
- package/dist/cli/commands/watch.d.ts +9 -0
- package/dist/cli/commands/watch.d.ts.map +1 -0
- package/dist/cli/commands/watch.js +93 -0
- package/dist/cli/commands/watch.js.map +1 -0
- package/dist/cli/index.d.ts +9 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +48 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/version.d.ts +16 -0
- package/dist/cli/version.d.ts.map +1 -0
- package/dist/cli/version.js +16 -0
- package/dist/cli/version.js.map +1 -0
- package/dist/core/analyzer/architecture-visualizer.d.ts +25 -0
- package/dist/core/analyzer/architecture-visualizer.d.ts.map +1 -0
- package/dist/core/analyzer/architecture-visualizer.js +333 -0
- package/dist/core/analyzer/architecture-visualizer.js.map +1 -0
- package/dist/core/analyzer/dependency-analyzer.d.ts +49 -0
- package/dist/core/analyzer/dependency-analyzer.d.ts.map +1 -0
- package/dist/core/analyzer/dependency-analyzer.js +242 -0
- package/dist/core/analyzer/dependency-analyzer.js.map +1 -0
- package/dist/core/config/config-schema.d.ts +280 -0
- package/dist/core/config/config-schema.d.ts.map +1 -0
- package/dist/core/config/config-schema.js +199 -0
- package/dist/core/config/config-schema.js.map +1 -0
- package/dist/core/config/configuration-manager.d.ts +82 -0
- package/dist/core/config/configuration-manager.d.ts.map +1 -0
- package/dist/core/config/configuration-manager.js +306 -0
- package/dist/core/config/configuration-manager.js.map +1 -0
- package/dist/core/logger.d.ts +27 -0
- package/dist/core/logger.d.ts.map +1 -0
- package/dist/core/logger.js +86 -0
- package/dist/core/logger.js.map +1 -0
- package/dist/core/parsers/go-parser.d.ts +16 -0
- package/dist/core/parsers/go-parser.d.ts.map +1 -0
- package/dist/core/parsers/go-parser.js +117 -0
- package/dist/core/parsers/go-parser.js.map +1 -0
- package/dist/core/parsers/java-parser.d.ts +22 -0
- package/dist/core/parsers/java-parser.d.ts.map +1 -0
- package/dist/core/parsers/java-parser.js +114 -0
- package/dist/core/parsers/java-parser.js.map +1 -0
- package/dist/core/parsers/javascript-parser.d.ts +14 -0
- package/dist/core/parsers/javascript-parser.d.ts.map +1 -0
- package/dist/core/parsers/javascript-parser.js +19 -0
- package/dist/core/parsers/javascript-parser.js.map +1 -0
- package/dist/core/parsers/parser-registry.d.ts +45 -0
- package/dist/core/parsers/parser-registry.d.ts.map +1 -0
- package/dist/core/parsers/parser-registry.js +121 -0
- package/dist/core/parsers/parser-registry.js.map +1 -0
- package/dist/core/parsers/parser.interface.d.ts +49 -0
- package/dist/core/parsers/parser.interface.d.ts.map +1 -0
- package/dist/core/parsers/parser.interface.js +7 -0
- package/dist/core/parsers/parser.interface.js.map +1 -0
- package/dist/core/parsers/python-parser.d.ts +22 -0
- package/dist/core/parsers/python-parser.d.ts.map +1 -0
- package/dist/core/parsers/python-parser.js +136 -0
- package/dist/core/parsers/python-parser.js.map +1 -0
- package/dist/core/parsers/rust-parser.d.ts +16 -0
- package/dist/core/parsers/rust-parser.d.ts.map +1 -0
- package/dist/core/parsers/rust-parser.js +176 -0
- package/dist/core/parsers/rust-parser.js.map +1 -0
- package/dist/core/parsers/typescript-parser.d.ts +29 -0
- package/dist/core/parsers/typescript-parser.d.ts.map +1 -0
- package/dist/core/parsers/typescript-parser.js +251 -0
- package/dist/core/parsers/typescript-parser.js.map +1 -0
- package/dist/core/reporter/report-generator.d.ts +31 -0
- package/dist/core/reporter/report-generator.d.ts.map +1 -0
- package/dist/core/reporter/report-generator.js +417 -0
- package/dist/core/reporter/report-generator.js.map +1 -0
- package/dist/core/reporter/violation-reporter.d.ts +62 -0
- package/dist/core/reporter/violation-reporter.d.ts.map +1 -0
- package/dist/core/reporter/violation-reporter.js +265 -0
- package/dist/core/reporter/violation-reporter.js.map +1 -0
- package/dist/core/rules/builtin/api-versioning.rule.d.ts +28 -0
- package/dist/core/rules/builtin/api-versioning.rule.d.ts.map +1 -0
- package/dist/core/rules/builtin/api-versioning.rule.js +103 -0
- package/dist/core/rules/builtin/api-versioning.rule.js.map +1 -0
- package/dist/core/rules/builtin/circular-dependencies.rule.d.ts +26 -0
- package/dist/core/rules/builtin/circular-dependencies.rule.d.ts.map +1 -0
- package/dist/core/rules/builtin/circular-dependencies.rule.js +99 -0
- package/dist/core/rules/builtin/circular-dependencies.rule.js.map +1 -0
- package/dist/core/rules/builtin/data-flow-integrity.rule.d.ts +27 -0
- package/dist/core/rules/builtin/data-flow-integrity.rule.d.ts.map +1 -0
- package/dist/core/rules/builtin/data-flow-integrity.rule.js +111 -0
- package/dist/core/rules/builtin/data-flow-integrity.rule.js.map +1 -0
- package/dist/core/rules/builtin/ddd-boundaries.rule.d.ts +31 -0
- package/dist/core/rules/builtin/ddd-boundaries.rule.d.ts.map +1 -0
- package/dist/core/rules/builtin/ddd-boundaries.rule.js +141 -0
- package/dist/core/rules/builtin/ddd-boundaries.rule.js.map +1 -0
- package/dist/core/rules/builtin/distributed-transactions.rule.d.ts +27 -0
- package/dist/core/rules/builtin/distributed-transactions.rule.d.ts.map +1 -0
- package/dist/core/rules/builtin/distributed-transactions.rule.js +134 -0
- package/dist/core/rules/builtin/distributed-transactions.rule.js.map +1 -0
- package/dist/core/rules/builtin/index.d.ts +16 -0
- package/dist/core/rules/builtin/index.d.ts.map +1 -0
- package/dist/core/rules/builtin/index.js +16 -0
- package/dist/core/rules/builtin/index.js.map +1 -0
- package/dist/core/rules/builtin/layer-dependencies.rule.d.ts +30 -0
- package/dist/core/rules/builtin/layer-dependencies.rule.d.ts.map +1 -0
- package/dist/core/rules/builtin/layer-dependencies.rule.js +102 -0
- package/dist/core/rules/builtin/layer-dependencies.rule.js.map +1 -0
- package/dist/core/rules/builtin/performance-antipatterns.rule.d.ts +29 -0
- package/dist/core/rules/builtin/performance-antipatterns.rule.d.ts.map +1 -0
- package/dist/core/rules/builtin/performance-antipatterns.rule.js +148 -0
- package/dist/core/rules/builtin/performance-antipatterns.rule.js.map +1 -0
- package/dist/core/rules/builtin/resilience-patterns.rule.d.ts +29 -0
- package/dist/core/rules/builtin/resilience-patterns.rule.d.ts.map +1 -0
- package/dist/core/rules/builtin/resilience-patterns.rule.js +123 -0
- package/dist/core/rules/builtin/resilience-patterns.rule.js.map +1 -0
- package/dist/core/rules/builtin/security-context.rule.d.ts +32 -0
- package/dist/core/rules/builtin/security-context.rule.d.ts.map +1 -0
- package/dist/core/rules/builtin/security-context.rule.js +145 -0
- package/dist/core/rules/builtin/security-context.rule.js.map +1 -0
- package/dist/core/rules/builtin/type-safety.rule.d.ts +32 -0
- package/dist/core/rules/builtin/type-safety.rule.d.ts.map +1 -0
- package/dist/core/rules/builtin/type-safety.rule.js +175 -0
- package/dist/core/rules/builtin/type-safety.rule.js.map +1 -0
- package/dist/core/rules/rule-engine.d.ts +72 -0
- package/dist/core/rules/rule-engine.d.ts.map +1 -0
- package/dist/core/rules/rule-engine.js +225 -0
- package/dist/core/rules/rule-engine.js.map +1 -0
- package/dist/core/rules/rule.interface.d.ts +169 -0
- package/dist/core/rules/rule.interface.d.ts.map +1 -0
- package/dist/core/rules/rule.interface.js +38 -0
- package/dist/core/rules/rule.interface.js.map +1 -0
- package/dist/core/scanner/project-detector.d.ts +51 -0
- package/dist/core/scanner/project-detector.d.ts.map +1 -0
- package/dist/core/scanner/project-detector.js +310 -0
- package/dist/core/scanner/project-detector.js.map +1 -0
- package/dist/core/scanner/project-scanner.d.ts +101 -0
- package/dist/core/scanner/project-scanner.d.ts.map +1 -0
- package/dist/core/scanner/project-scanner.js +321 -0
- package/dist/core/scanner/project-scanner.js.map +1 -0
- package/dist/core/watcher/file-watcher.d.ts +48 -0
- package/dist/core/watcher/file-watcher.d.ts.map +1 -0
- package/dist/core/watcher/file-watcher.js +124 -0
- package/dist/core/watcher/file-watcher.js.map +1 -0
- package/dist/types/config.types.d.ts +163 -0
- package/dist/types/config.types.d.ts.map +1 -0
- package/dist/types/config.types.js +36 -0
- package/dist/types/config.types.js.map +1 -0
- package/dist/types/core.types.d.ts +247 -0
- package/dist/types/core.types.d.ts.map +1 -0
- package/dist/types/core.types.js +7 -0
- package/dist/types/core.types.js.map +1 -0
- package/dist/types/index.d.ts +7 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +7 -0
- package/dist/types/index.js.map +1 -0
- package/package.json +90 -0
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Data Flow Integrity Rule
|
|
3
|
+
*
|
|
4
|
+
* Validates data flow patterns and integrity constraints.
|
|
5
|
+
*/
|
|
6
|
+
import * as path from 'path';
|
|
7
|
+
export class DataFlowIntegrityRule {
|
|
8
|
+
id = 'data-flow-integrity';
|
|
9
|
+
name = 'Data Flow Integrity';
|
|
10
|
+
description = 'Validates data flow patterns and integrity constraints';
|
|
11
|
+
severity = 'warning';
|
|
12
|
+
tags = ['data-flow', 'security', 'integrity'];
|
|
13
|
+
config = {
|
|
14
|
+
enabled: true,
|
|
15
|
+
severity: 'warning',
|
|
16
|
+
trackMutations: true,
|
|
17
|
+
enforceImmutability: false,
|
|
18
|
+
sensitivePatterns: ['password', 'secret', 'token', 'key', 'credential'],
|
|
19
|
+
};
|
|
20
|
+
configure(options) {
|
|
21
|
+
this.config = { ...this.config, ...options };
|
|
22
|
+
}
|
|
23
|
+
async check(context) {
|
|
24
|
+
const violations = [];
|
|
25
|
+
for (const nodeId of context.graph.nodes()) {
|
|
26
|
+
const node = context.getNodeData(nodeId);
|
|
27
|
+
if (!node)
|
|
28
|
+
continue;
|
|
29
|
+
const filePath = node.data.relativePath;
|
|
30
|
+
const content = context.fileContents?.get(filePath);
|
|
31
|
+
if (!content)
|
|
32
|
+
continue;
|
|
33
|
+
this.checkSensitiveDataExposure(filePath, content, violations);
|
|
34
|
+
this.checkMutableOperations(filePath, content, violations);
|
|
35
|
+
this.checkDataValidation(filePath, content, violations);
|
|
36
|
+
}
|
|
37
|
+
return { violations };
|
|
38
|
+
}
|
|
39
|
+
checkSensitiveDataExposure(filePath, content, violations) {
|
|
40
|
+
const lines = content.split('\n');
|
|
41
|
+
const sensitivePatterns = this.config.sensitivePatterns || [];
|
|
42
|
+
for (let i = 0; i < lines.length; i++) {
|
|
43
|
+
const line = lines[i].toLowerCase();
|
|
44
|
+
for (const pattern of sensitivePatterns) {
|
|
45
|
+
if (line.includes(pattern)) {
|
|
46
|
+
// Check for logging exposure
|
|
47
|
+
if (/console\.(log|info|debug|warn|error)/.test(lines[i]) ||
|
|
48
|
+
/logger\.(log|info|debug|warn|error)/.test(lines[i])) {
|
|
49
|
+
violations.push(this.createViolation(filePath, `Potential sensitive data logged: ${pattern}`, i + 1, 'Remove or mask sensitive data before logging'));
|
|
50
|
+
}
|
|
51
|
+
// Check for direct assignment from user input
|
|
52
|
+
if (/req\.(body|query|params)/.test(lines[i])) {
|
|
53
|
+
violations.push(this.createViolation(filePath, `Sensitive data directly from user input: ${pattern}`, i + 1, 'Validate and sanitize user input before processing'));
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
checkMutableOperations(filePath, content, violations) {
|
|
60
|
+
if (!this.config.enforceImmutability)
|
|
61
|
+
return;
|
|
62
|
+
const lines = content.split('\n');
|
|
63
|
+
const mutationPatterns = [
|
|
64
|
+
/\.push\s*\(/,
|
|
65
|
+
/\.pop\s*\(/,
|
|
66
|
+
/\.shift\s*\(/,
|
|
67
|
+
/\.unshift\s*\(/,
|
|
68
|
+
/\.splice\s*\(/,
|
|
69
|
+
/\.sort\s*\(/,
|
|
70
|
+
/\.reverse\s*\(/,
|
|
71
|
+
];
|
|
72
|
+
for (let i = 0; i < lines.length; i++) {
|
|
73
|
+
for (const pattern of mutationPatterns) {
|
|
74
|
+
if (pattern.test(lines[i])) {
|
|
75
|
+
violations.push(this.createViolation(filePath, 'Mutable array operation detected', i + 1, 'Use immutable alternatives like spread operator, map, filter, or slice'));
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
checkDataValidation(filePath, content, violations) {
|
|
81
|
+
const lines = content.split('\n');
|
|
82
|
+
const fileName = path.basename(filePath).toLowerCase();
|
|
83
|
+
// Check for data models/entities without validation
|
|
84
|
+
if (fileName.includes('model') || fileName.includes('entity') || fileName.includes('dto')) {
|
|
85
|
+
const hasValidation = content.includes('@Valid') ||
|
|
86
|
+
content.includes('validate') ||
|
|
87
|
+
content.includes('IsNotEmpty') ||
|
|
88
|
+
content.includes('IsString') ||
|
|
89
|
+
content.includes('class-validator');
|
|
90
|
+
if (!hasValidation && content.includes('class ')) {
|
|
91
|
+
const classMatch = content.match(/class\s+(\w+)/);
|
|
92
|
+
if (classMatch) {
|
|
93
|
+
violations.push(this.createViolation(filePath, `Data class '${classMatch[1]}' without validation`, 1, 'Add validation decorators or validation logic'));
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
createViolation(file, message, line, suggestion) {
|
|
99
|
+
return {
|
|
100
|
+
id: `${this.id}-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`,
|
|
101
|
+
ruleId: this.id,
|
|
102
|
+
ruleName: this.name,
|
|
103
|
+
severity: 'warning',
|
|
104
|
+
message,
|
|
105
|
+
file,
|
|
106
|
+
line,
|
|
107
|
+
suggestion,
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
//# sourceMappingURL=data-flow-integrity.rule.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"data-flow-integrity.rule.js","sourceRoot":"","sources":["../../../../src/core/rules/builtin/data-flow-integrity.rule.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DDD Boundaries Rule
|
|
3
|
+
*
|
|
4
|
+
* Validates Domain-Driven Design boundary patterns.
|
|
5
|
+
*/
|
|
6
|
+
import { IRule, RuleContext, RuleConfig, RuleResult } from '../rule.interface.js';
|
|
7
|
+
interface DddBoundariesConfig extends RuleConfig {
|
|
8
|
+
domains?: string[];
|
|
9
|
+
allowedCrossings?: Array<{
|
|
10
|
+
from: string;
|
|
11
|
+
to: string;
|
|
12
|
+
}>;
|
|
13
|
+
enforceAggregateRoots?: boolean;
|
|
14
|
+
}
|
|
15
|
+
export declare class DddBoundariesRule implements IRule {
|
|
16
|
+
readonly id = "ddd-boundaries";
|
|
17
|
+
readonly name = "DDD Bounded Context Boundaries";
|
|
18
|
+
readonly description = "Validates Domain-Driven Design boundary patterns";
|
|
19
|
+
readonly severity: "error";
|
|
20
|
+
readonly tags: string[];
|
|
21
|
+
private config;
|
|
22
|
+
configure(options: Partial<DddBoundariesConfig>): void;
|
|
23
|
+
check(context: RuleContext): Promise<RuleResult>;
|
|
24
|
+
private extractDomain;
|
|
25
|
+
private isCrossingAllowed;
|
|
26
|
+
private checkAggregatePatterns;
|
|
27
|
+
private checkRepositoryPatterns;
|
|
28
|
+
private createViolation;
|
|
29
|
+
}
|
|
30
|
+
export {};
|
|
31
|
+
//# sourceMappingURL=ddd-boundaries.rule.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ddd-boundaries.rule.d.ts","sourceRoot":"","sources":["../../../../src/core/rules/builtin/ddd-boundaries.rule.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,KAAK,EAAE,WAAW,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAIlF,UAAU,mBAAoB,SAAQ,UAAU;IAC9C,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,gBAAgB,CAAC,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACvD,qBAAqB,CAAC,EAAE,OAAO,CAAC;CACjC;AAED,qBAAa,iBAAkB,YAAW,KAAK;IAC7C,QAAQ,CAAC,EAAE,oBAAoB;IAC/B,QAAQ,CAAC,IAAI,oCAAoC;IACjD,QAAQ,CAAC,WAAW,sDAAsD;IAC1E,QAAQ,CAAC,QAAQ,EAAG,OAAO,CAAU;IACrC,QAAQ,CAAC,IAAI,WAAyC;IAEtD,OAAO,CAAC,MAAM,CAMZ;IAEF,SAAS,CAAC,OAAO,EAAE,OAAO,CAAC,mBAAmB,CAAC,GAAG,IAAI;IAIhD,KAAK,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,UAAU,CAAC;IA6CtD,OAAO,CAAC,aAAa;IA8BrB,OAAO,CAAC,iBAAiB;IAOzB,OAAO,CAAC,sBAAsB;IAmC9B,OAAO,CAAC,uBAAuB;IA2B/B,OAAO,CAAC,eAAe;CAYxB"}
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DDD Boundaries Rule
|
|
3
|
+
*
|
|
4
|
+
* Validates Domain-Driven Design boundary patterns.
|
|
5
|
+
*/
|
|
6
|
+
import * as path from 'path';
|
|
7
|
+
export class DddBoundariesRule {
|
|
8
|
+
id = 'ddd-boundaries';
|
|
9
|
+
name = 'DDD Bounded Context Boundaries';
|
|
10
|
+
description = 'Validates Domain-Driven Design boundary patterns';
|
|
11
|
+
severity = 'error';
|
|
12
|
+
tags = ['ddd', 'architecture', 'boundaries'];
|
|
13
|
+
config = {
|
|
14
|
+
enabled: true,
|
|
15
|
+
severity: 'error',
|
|
16
|
+
domains: [],
|
|
17
|
+
allowedCrossings: [],
|
|
18
|
+
enforceAggregateRoots: true,
|
|
19
|
+
};
|
|
20
|
+
configure(options) {
|
|
21
|
+
this.config = { ...this.config, ...options };
|
|
22
|
+
}
|
|
23
|
+
async check(context) {
|
|
24
|
+
const violations = [];
|
|
25
|
+
for (const nodeId of context.graph.nodes()) {
|
|
26
|
+
const node = context.getNodeData(nodeId);
|
|
27
|
+
if (!node)
|
|
28
|
+
continue;
|
|
29
|
+
const filePath = node.data.relativePath;
|
|
30
|
+
const sourceDomain = this.extractDomain(filePath);
|
|
31
|
+
if (!sourceDomain)
|
|
32
|
+
continue;
|
|
33
|
+
// Check cross-boundary imports
|
|
34
|
+
const successors = context.graph.successors(nodeId);
|
|
35
|
+
if (successors) {
|
|
36
|
+
for (const successor of successors) {
|
|
37
|
+
const targetNode = context.getNodeData(successor);
|
|
38
|
+
if (!targetNode)
|
|
39
|
+
continue;
|
|
40
|
+
const targetPath = targetNode.data.relativePath;
|
|
41
|
+
const targetDomain = this.extractDomain(targetPath);
|
|
42
|
+
if (targetDomain && sourceDomain !== targetDomain) {
|
|
43
|
+
if (!this.isCrossingAllowed(sourceDomain, targetDomain)) {
|
|
44
|
+
violations.push(this.createViolation(filePath, `Cross-boundary dependency: ${sourceDomain} -> ${targetDomain}`, 1, 'Use domain events or anti-corruption layer for cross-domain communication'));
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
// Check aggregate root patterns
|
|
50
|
+
const content = context.fileContents?.get(filePath);
|
|
51
|
+
if (content) {
|
|
52
|
+
this.checkAggregatePatterns(filePath, content, violations);
|
|
53
|
+
this.checkRepositoryPatterns(filePath, content, violations);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
return { violations };
|
|
57
|
+
}
|
|
58
|
+
extractDomain(filePath) {
|
|
59
|
+
const normalizedPath = filePath.replace(/\\/g, '/');
|
|
60
|
+
// Look for common domain folder patterns
|
|
61
|
+
const domainPatterns = [
|
|
62
|
+
/\/domains?\/([^/]+)\//,
|
|
63
|
+
/\/bounded-contexts?\/([^/]+)\//,
|
|
64
|
+
/\/modules?\/([^/]+)\//,
|
|
65
|
+
/\/features?\/([^/]+)\//,
|
|
66
|
+
];
|
|
67
|
+
for (const pattern of domainPatterns) {
|
|
68
|
+
const match = normalizedPath.match(pattern);
|
|
69
|
+
if (match) {
|
|
70
|
+
return match[1];
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
// Check configured domains
|
|
74
|
+
if (this.config.domains?.length) {
|
|
75
|
+
for (const domain of this.config.domains) {
|
|
76
|
+
if (normalizedPath.includes(`/${domain}/`) || normalizedPath.includes(`\\${domain}\\`)) {
|
|
77
|
+
return domain;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
return null;
|
|
82
|
+
}
|
|
83
|
+
isCrossingAllowed(from, to) {
|
|
84
|
+
if (!this.config.allowedCrossings?.length)
|
|
85
|
+
return false;
|
|
86
|
+
return this.config.allowedCrossings.some(crossing => crossing.from === from && crossing.to === to);
|
|
87
|
+
}
|
|
88
|
+
checkAggregatePatterns(filePath, content, violations) {
|
|
89
|
+
if (!this.config.enforceAggregateRoots)
|
|
90
|
+
return;
|
|
91
|
+
const fileName = path.basename(filePath).toLowerCase();
|
|
92
|
+
const lines = content.split('\n');
|
|
93
|
+
// Check if it's an entity file
|
|
94
|
+
if (fileName.includes('entity') || fileName.includes('.entity')) {
|
|
95
|
+
// Check for direct repository access in entities
|
|
96
|
+
for (let i = 0; i < lines.length; i++) {
|
|
97
|
+
if (/repository/i.test(lines[i]) && /inject|@Inject/i.test(lines[i])) {
|
|
98
|
+
violations.push(this.createViolation(filePath, 'Entity should not have direct repository dependency', i + 1, 'Repositories should be accessed through aggregate roots or domain services'));
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
// Check for aggregate root markers
|
|
103
|
+
if (content.includes('AggregateRoot') || content.includes('@Aggregate')) {
|
|
104
|
+
// Verify it has proper invariants
|
|
105
|
+
if (!content.includes('validate') && !content.includes('invariant')) {
|
|
106
|
+
violations.push(this.createViolation(filePath, 'Aggregate root without invariant validation', 1, 'Add invariant validation methods to maintain consistency'));
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
checkRepositoryPatterns(filePath, content, violations) {
|
|
111
|
+
const fileName = path.basename(filePath).toLowerCase();
|
|
112
|
+
if (fileName.includes('repository')) {
|
|
113
|
+
const lines = content.split('\n');
|
|
114
|
+
// Check for business logic in repository
|
|
115
|
+
const businessLogicPatterns = [
|
|
116
|
+
/if\s*\(.*\.(status|state|is\w+)/,
|
|
117
|
+
/throw\s+new\s+(?!EntityNotFound|NotFound)/,
|
|
118
|
+
];
|
|
119
|
+
for (let i = 0; i < lines.length; i++) {
|
|
120
|
+
for (const pattern of businessLogicPatterns) {
|
|
121
|
+
if (pattern.test(lines[i])) {
|
|
122
|
+
violations.push(this.createViolation(filePath, 'Business logic detected in repository', i + 1, 'Move business logic to domain entities or services'));
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
createViolation(file, message, line, suggestion) {
|
|
129
|
+
return {
|
|
130
|
+
id: `${this.id}-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`,
|
|
131
|
+
ruleId: this.id,
|
|
132
|
+
ruleName: this.name,
|
|
133
|
+
severity: 'error',
|
|
134
|
+
message,
|
|
135
|
+
file,
|
|
136
|
+
line,
|
|
137
|
+
suggestion,
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
//# sourceMappingURL=ddd-boundaries.rule.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ddd-boundaries.rule.js","sourceRoot":"","sources":["../../../../src/core/rules/builtin/ddd-boundaries.rule.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Distributed Transactions Rule
|
|
3
|
+
*
|
|
4
|
+
* Validates distributed transaction patterns and saga implementations.
|
|
5
|
+
*/
|
|
6
|
+
import { IRule, RuleContext, RuleConfig, RuleResult } from '../rule.interface.js';
|
|
7
|
+
interface DistributedTransactionsConfig extends RuleConfig {
|
|
8
|
+
requireCompensation?: boolean;
|
|
9
|
+
maxTransactionSteps?: number;
|
|
10
|
+
sagaPatterns?: string[];
|
|
11
|
+
}
|
|
12
|
+
export declare class DistributedTransactionsRule implements IRule {
|
|
13
|
+
readonly id = "distributed-transactions";
|
|
14
|
+
readonly name = "Distributed Transactions";
|
|
15
|
+
readonly description = "Validates distributed transaction patterns and saga implementations";
|
|
16
|
+
readonly severity: "error";
|
|
17
|
+
readonly tags: string[];
|
|
18
|
+
private config;
|
|
19
|
+
configure(options: Partial<DistributedTransactionsConfig>): void;
|
|
20
|
+
check(context: RuleContext): Promise<RuleResult>;
|
|
21
|
+
private checkDistributedTransaction;
|
|
22
|
+
private checkSagaPattern;
|
|
23
|
+
private checkCompensation;
|
|
24
|
+
private createViolation;
|
|
25
|
+
}
|
|
26
|
+
export {};
|
|
27
|
+
//# sourceMappingURL=distributed-transactions.rule.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"distributed-transactions.rule.d.ts","sourceRoot":"","sources":["../../../../src/core/rules/builtin/distributed-transactions.rule.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,KAAK,EAAE,WAAW,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAIlF,UAAU,6BAA8B,SAAQ,UAAU;IACxD,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;CACzB;AAED,qBAAa,2BAA4B,YAAW,KAAK;IACvD,QAAQ,CAAC,EAAE,8BAA8B;IACzC,QAAQ,CAAC,IAAI,8BAA8B;IAC3C,QAAQ,CAAC,WAAW,yEAAyE;IAC7F,QAAQ,CAAC,QAAQ,EAAG,OAAO,CAAU;IACrC,QAAQ,CAAC,IAAI,WAA0D;IAEvE,OAAO,CAAC,MAAM,CAMZ;IAEF,SAAS,CAAC,OAAO,EAAE,OAAO,CAAC,6BAA6B,CAAC,GAAG,IAAI;IAI1D,KAAK,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,UAAU,CAAC;IAmBtD,OAAO,CAAC,2BAA2B;IAsCnC,OAAO,CAAC,gBAAgB;IAmDxB,OAAO,CAAC,iBAAiB;IAkCzB,OAAO,CAAC,eAAe;CAYxB"}
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Distributed Transactions Rule
|
|
3
|
+
*
|
|
4
|
+
* Validates distributed transaction patterns and saga implementations.
|
|
5
|
+
*/
|
|
6
|
+
import * as path from 'path';
|
|
7
|
+
export class DistributedTransactionsRule {
|
|
8
|
+
id = 'distributed-transactions';
|
|
9
|
+
name = 'Distributed Transactions';
|
|
10
|
+
description = 'Validates distributed transaction patterns and saga implementations';
|
|
11
|
+
severity = 'error';
|
|
12
|
+
tags = ['distributed', 'transactions', 'saga', 'reliability'];
|
|
13
|
+
config = {
|
|
14
|
+
enabled: true,
|
|
15
|
+
severity: 'error',
|
|
16
|
+
requireCompensation: true,
|
|
17
|
+
maxTransactionSteps: 5,
|
|
18
|
+
sagaPatterns: ['saga', 'choreography', 'orchestration'],
|
|
19
|
+
};
|
|
20
|
+
configure(options) {
|
|
21
|
+
this.config = { ...this.config, ...options };
|
|
22
|
+
}
|
|
23
|
+
async check(context) {
|
|
24
|
+
const violations = [];
|
|
25
|
+
for (const nodeId of context.graph.nodes()) {
|
|
26
|
+
const node = context.getNodeData(nodeId);
|
|
27
|
+
if (!node)
|
|
28
|
+
continue;
|
|
29
|
+
const filePath = node.data.relativePath;
|
|
30
|
+
const content = context.fileContents?.get(filePath);
|
|
31
|
+
if (!content)
|
|
32
|
+
continue;
|
|
33
|
+
this.checkDistributedTransaction(filePath, content, violations);
|
|
34
|
+
this.checkSagaPattern(filePath, content, violations);
|
|
35
|
+
this.checkCompensation(filePath, content, violations);
|
|
36
|
+
}
|
|
37
|
+
return { violations };
|
|
38
|
+
}
|
|
39
|
+
checkDistributedTransaction(filePath, content, violations) {
|
|
40
|
+
const lines = content.split('\n');
|
|
41
|
+
// Detect potential distributed transactions
|
|
42
|
+
const multiServiceCalls = [];
|
|
43
|
+
let inTransaction = false;
|
|
44
|
+
for (let i = 0; i < lines.length; i++) {
|
|
45
|
+
const line = lines[i];
|
|
46
|
+
// Detect transaction start
|
|
47
|
+
if (/@Transaction|beginTransaction|startTransaction/.test(line)) {
|
|
48
|
+
inTransaction = true;
|
|
49
|
+
}
|
|
50
|
+
// Detect service calls within transactions
|
|
51
|
+
if (inTransaction) {
|
|
52
|
+
if (/\.call\(|httpClient|fetch\(|axios\./.test(line)) {
|
|
53
|
+
multiServiceCalls.push(i + 1);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
// Detect transaction end
|
|
57
|
+
if (/commit|endTransaction/.test(line)) {
|
|
58
|
+
inTransaction = false;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
if (multiServiceCalls.length > 1) {
|
|
62
|
+
violations.push(this.createViolation(filePath, 'Multiple service calls in single transaction scope', multiServiceCalls[0], 'Use saga pattern for distributed transactions instead of single transaction scope'));
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
checkSagaPattern(filePath, content, violations) {
|
|
66
|
+
const fileName = path.basename(filePath).toLowerCase();
|
|
67
|
+
const lines = content.split('\n');
|
|
68
|
+
// Check if it's a saga file
|
|
69
|
+
const isSaga = this.config.sagaPatterns?.some(p => fileName.includes(p)) ||
|
|
70
|
+
content.includes('@Saga') ||
|
|
71
|
+
content.includes('Saga');
|
|
72
|
+
if (isSaga) {
|
|
73
|
+
// Count transaction steps
|
|
74
|
+
const stepPatterns = [
|
|
75
|
+
/step\s*\d+|Step\d+/g,
|
|
76
|
+
/execute\w+Step/g,
|
|
77
|
+
/on\w+Success|on\w+Failure/g,
|
|
78
|
+
];
|
|
79
|
+
let stepCount = 0;
|
|
80
|
+
for (const pattern of stepPatterns) {
|
|
81
|
+
const matches = content.match(pattern);
|
|
82
|
+
if (matches) {
|
|
83
|
+
stepCount += matches.length;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
const maxSteps = this.config.maxTransactionSteps || 5;
|
|
87
|
+
if (stepCount > maxSteps * 2) { // Account for success/failure handlers
|
|
88
|
+
violations.push(this.createViolation(filePath, `Saga has too many steps (${Math.floor(stepCount / 2)} estimated)`, 1, `Consider breaking down into smaller sagas (max ${maxSteps} steps)`));
|
|
89
|
+
}
|
|
90
|
+
// Check for proper error handling
|
|
91
|
+
const hasCompensation = content.includes('compensat') ||
|
|
92
|
+
content.includes('rollback') ||
|
|
93
|
+
content.includes('onFailure');
|
|
94
|
+
if (!hasCompensation && this.config.requireCompensation) {
|
|
95
|
+
violations.push(this.createViolation(filePath, 'Saga without compensation handlers', 1, 'Add compensation/rollback logic for each saga step'));
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
checkCompensation(filePath, content, violations) {
|
|
100
|
+
const lines = content.split('\n');
|
|
101
|
+
// Check for database operations without rollback
|
|
102
|
+
const dbOperations = [];
|
|
103
|
+
for (let i = 0; i < lines.length; i++) {
|
|
104
|
+
const line = lines[i];
|
|
105
|
+
if (/\.save\(|\.insert\(|\.update\(|\.delete\(|\.remove\(/.test(line)) {
|
|
106
|
+
dbOperations.push({ line: i + 1, operation: line.trim() });
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
// If multiple DB operations exist, check for transaction or compensation
|
|
110
|
+
if (dbOperations.length > 1) {
|
|
111
|
+
const hasTransactionControl = content.includes('transaction') ||
|
|
112
|
+
content.includes('@Transactional') ||
|
|
113
|
+
content.includes('beginTransaction');
|
|
114
|
+
const hasCompensation = content.includes('try') &&
|
|
115
|
+
(content.includes('catch') || content.includes('finally'));
|
|
116
|
+
if (!hasTransactionControl && !hasCompensation) {
|
|
117
|
+
violations.push(this.createViolation(filePath, 'Multiple database operations without transaction or error handling', dbOperations[0].line, 'Wrap operations in transaction or add proper error handling with compensation'));
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
createViolation(file, message, line, suggestion) {
|
|
122
|
+
return {
|
|
123
|
+
id: `${this.id}-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`,
|
|
124
|
+
ruleId: this.id,
|
|
125
|
+
ruleName: this.name,
|
|
126
|
+
severity: 'error',
|
|
127
|
+
message,
|
|
128
|
+
file,
|
|
129
|
+
line,
|
|
130
|
+
suggestion,
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
//# sourceMappingURL=distributed-transactions.rule.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"distributed-transactions.rule.js","sourceRoot":"","sources":["../../../../src/core/rules/builtin/distributed-transactions.rule.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Builtin Rules Index
|
|
3
|
+
*
|
|
4
|
+
* Exports all built-in architecture rules.
|
|
5
|
+
*/
|
|
6
|
+
export { ApiVersioningEvolutionRule } from './api-versioning.rule.js';
|
|
7
|
+
export { CircularDependenciesRule } from './circular-dependencies.rule.js';
|
|
8
|
+
export { DataFlowIntegrityRule } from './data-flow-integrity.rule.js';
|
|
9
|
+
export { DddBoundariesRule } from './ddd-boundaries.rule.js';
|
|
10
|
+
export { DistributedTransactionsRule } from './distributed-transactions.rule.js';
|
|
11
|
+
export { LayerDependenciesRule } from './layer-dependencies.rule.js';
|
|
12
|
+
export { PerformanceAntipatternsRule } from './performance-antipatterns.rule.js';
|
|
13
|
+
export { ResiliencePatternsRule } from './resilience-patterns.rule.js';
|
|
14
|
+
export { SecurityContextRule } from './security-context.rule.js';
|
|
15
|
+
export { TypeSafetyRule } from './type-safety.rule.js';
|
|
16
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/core/rules/builtin/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,0BAA0B,EAAE,MAAM,0BAA0B,CAAC;AACtE,OAAO,EAAE,wBAAwB,EAAE,MAAM,iCAAiC,CAAC;AAC3E,OAAO,EAAE,qBAAqB,EAAE,MAAM,+BAA+B,CAAC;AACtE,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAC7D,OAAO,EAAE,2BAA2B,EAAE,MAAM,oCAAoC,CAAC;AACjF,OAAO,EAAE,qBAAqB,EAAE,MAAM,8BAA8B,CAAC;AACrE,OAAO,EAAE,2BAA2B,EAAE,MAAM,oCAAoC,CAAC;AACjF,OAAO,EAAE,sBAAsB,EAAE,MAAM,+BAA+B,CAAC;AACvE,OAAO,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AACjE,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Builtin Rules Index
|
|
3
|
+
*
|
|
4
|
+
* Exports all built-in architecture rules.
|
|
5
|
+
*/
|
|
6
|
+
export { ApiVersioningEvolutionRule } from './api-versioning.rule.js';
|
|
7
|
+
export { CircularDependenciesRule } from './circular-dependencies.rule.js';
|
|
8
|
+
export { DataFlowIntegrityRule } from './data-flow-integrity.rule.js';
|
|
9
|
+
export { DddBoundariesRule } from './ddd-boundaries.rule.js';
|
|
10
|
+
export { DistributedTransactionsRule } from './distributed-transactions.rule.js';
|
|
11
|
+
export { LayerDependenciesRule } from './layer-dependencies.rule.js';
|
|
12
|
+
export { PerformanceAntipatternsRule } from './performance-antipatterns.rule.js';
|
|
13
|
+
export { ResiliencePatternsRule } from './resilience-patterns.rule.js';
|
|
14
|
+
export { SecurityContextRule } from './security-context.rule.js';
|
|
15
|
+
export { TypeSafetyRule } from './type-safety.rule.js';
|
|
16
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/core/rules/builtin/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,0BAA0B,EAAE,MAAM,0BAA0B,CAAC;AACtE,OAAO,EAAE,wBAAwB,EAAE,MAAM,iCAAiC,CAAC;AAC3E,OAAO,EAAE,qBAAqB,EAAE,MAAM,+BAA+B,CAAC;AACtE,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAC7D,OAAO,EAAE,2BAA2B,EAAE,MAAM,oCAAoC,CAAC;AACjF,OAAO,EAAE,qBAAqB,EAAE,MAAM,8BAA8B,CAAC;AACrE,OAAO,EAAE,2BAA2B,EAAE,MAAM,oCAAoC,CAAC;AACjF,OAAO,EAAE,sBAAsB,EAAE,MAAM,+BAA+B,CAAC;AACvE,OAAO,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AACjE,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Layer Dependencies Rule
|
|
3
|
+
*
|
|
4
|
+
* Validates architectural layer dependencies (e.g., presentation -> business -> data).
|
|
5
|
+
*/
|
|
6
|
+
import { IRule, RuleContext, RuleConfig, RuleResult } from '../rule.interface.js';
|
|
7
|
+
interface LayerConfig {
|
|
8
|
+
name: string;
|
|
9
|
+
patterns: string[];
|
|
10
|
+
allowedDependencies: string[];
|
|
11
|
+
}
|
|
12
|
+
interface LayerDependenciesConfig extends RuleConfig {
|
|
13
|
+
layers?: LayerConfig[];
|
|
14
|
+
strictMode?: boolean;
|
|
15
|
+
}
|
|
16
|
+
export declare class LayerDependenciesRule implements IRule {
|
|
17
|
+
readonly id = "layer-dependencies";
|
|
18
|
+
readonly name = "Layer Dependencies";
|
|
19
|
+
readonly description = "Validates architectural layer dependencies";
|
|
20
|
+
readonly severity: "error";
|
|
21
|
+
readonly tags: string[];
|
|
22
|
+
private config;
|
|
23
|
+
configure(options: Partial<LayerDependenciesConfig>): void;
|
|
24
|
+
check(context: RuleContext): Promise<RuleResult>;
|
|
25
|
+
private detectLayer;
|
|
26
|
+
private isDependencyAllowed;
|
|
27
|
+
private createViolation;
|
|
28
|
+
}
|
|
29
|
+
export {};
|
|
30
|
+
//# sourceMappingURL=layer-dependencies.rule.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"layer-dependencies.rule.d.ts","sourceRoot":"","sources":["../../../../src/core/rules/builtin/layer-dependencies.rule.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,KAAK,EAAE,WAAW,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAGlF,UAAU,WAAW;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,mBAAmB,EAAE,MAAM,EAAE,CAAC;CAC/B;AAED,UAAU,uBAAwB,SAAQ,UAAU;IAClD,MAAM,CAAC,EAAE,WAAW,EAAE,CAAC;IACvB,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAED,qBAAa,qBAAsB,YAAW,KAAK;IACjD,QAAQ,CAAC,EAAE,wBAAwB;IACnC,QAAQ,CAAC,IAAI,wBAAwB;IACrC,QAAQ,CAAC,WAAW,gDAAgD;IACpE,QAAQ,CAAC,QAAQ,EAAG,OAAO,CAAU;IACrC,QAAQ,CAAC,IAAI,WAA8C;IAE3D,OAAO,CAAC,MAAM,CA0BZ;IAEF,SAAS,CAAC,OAAO,EAAE,OAAO,CAAC,uBAAuB,CAAC,GAAG,IAAI;IAIpD,KAAK,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,UAAU,CAAC;IAsCtD,OAAO,CAAC,WAAW;IAcnB,OAAO,CAAC,mBAAmB;IAO3B,OAAO,CAAC,eAAe;CAYxB"}
|