@samiyev/guardian
Version:
Research-backed code quality guardian for AI-assisted development. Detects hardcodes, secrets, circular deps, framework leaks, entity exposure, and 9 architecture violations. Enforces Clean Architecture/DDD principles. Works with GitHub Copilot, Cursor, W
113 lines (108 loc) • 3.5 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.AggregateBoundaryViolation = void 0;
const ValueObject_1 = require("./ValueObject");
const Messages_1 = require("../constants/Messages");
/**
* Represents an aggregate boundary violation in the codebase
*
* Aggregate boundary violations occur when an entity from one aggregate
* directly references an entity from another aggregate, violating DDD principles:
* - Aggregates should reference each other only by ID or Value Objects
* - Direct entity references create tight coupling between aggregates
* - Changes to one aggregate should not require changes to another
*
* @example
* ```typescript
* // Bad: Direct entity reference across aggregates
* const violation = AggregateBoundaryViolation.create(
* 'order',
* 'user',
* 'User',
* '../user/User',
* 'src/domain/aggregates/order/Order.ts',
* 5
* )
*
* console.log(violation.getMessage())
* // "Order aggregate should not directly reference User entity from User aggregate"
* ```
*/
class AggregateBoundaryViolation extends ValueObject_1.ValueObject {
constructor(props) {
super(props);
}
static create(fromAggregate, toAggregate, entityName, importPath, filePath, line) {
return new AggregateBoundaryViolation({
fromAggregate,
toAggregate,
entityName,
importPath,
filePath,
line,
});
}
get fromAggregate() {
return this.props.fromAggregate;
}
get toAggregate() {
return this.props.toAggregate;
}
get entityName() {
return this.props.entityName;
}
get importPath() {
return this.props.importPath;
}
get filePath() {
return this.props.filePath;
}
get line() {
return this.props.line;
}
getMessage() {
return `${this.capitalizeFirst(this.props.fromAggregate)} aggregate should not directly reference ${this.props.entityName} entity from ${this.capitalizeFirst(this.props.toAggregate)} aggregate`;
}
getSuggestion() {
const suggestions = [
Messages_1.AGGREGATE_VIOLATION_MESSAGES.USE_ID_REFERENCE,
Messages_1.AGGREGATE_VIOLATION_MESSAGES.USE_VALUE_OBJECT,
Messages_1.AGGREGATE_VIOLATION_MESSAGES.AVOID_DIRECT_REFERENCE,
Messages_1.AGGREGATE_VIOLATION_MESSAGES.MAINTAIN_INDEPENDENCE,
];
return suggestions.join("\n");
}
getExampleFix() {
return `
// ❌ Bad: Direct entity reference across aggregates
// domain/aggregates/order/Order.ts
import { User } from '../user/User'
class Order {
constructor(private user: User) {}
}
// ✅ Good: Reference by ID
// domain/aggregates/order/Order.ts
import { UserId } from '../user/value-objects/UserId'
class Order {
constructor(private userId: UserId) {}
}
// ✅ Good: Use Value Object for needed data
// domain/aggregates/order/value-objects/CustomerInfo.ts
class CustomerInfo {
constructor(
readonly customerId: string,
readonly customerName: string,
readonly customerEmail: string
) {}
}
// domain/aggregates/order/Order.ts
class Order {
constructor(private customerInfo: CustomerInfo) {}
}`;
}
capitalizeFirst(str) {
return str.charAt(0).toUpperCase() + str.slice(1);
}
}
exports.AggregateBoundaryViolation = AggregateBoundaryViolation;
//# sourceMappingURL=AggregateBoundaryViolation.js.map