import { Result } from '../../../utils/src/index.ts'; import { DomainSeederConfig, SeedableAggregate } from './shared-seeder-types.js'; /** * Sequence generator function type */ export type SequenceGenerator = (index: number, previous?: T) => T; /** * Value object generator function type */ export type ValueObjectGenerator = (index?: number) => T | Promise; /** * Aggregate factory configuration options */ export interface AggregateFactoryConfig { /** Enable automatic event generation during aggregate creation */ generateEvents?: boolean; /** Validate business rules after aggregate creation */ validateBusinessRules?: boolean; /** Maximum number of retry attempts for constraint violations */ maxRetryAttempts?: number; /** Custom constraint validation function */ constraintValidator?: (aggregate: any) => Promise; } /** * Template for aggregate creation with predefined patterns */ export interface AggregateTemplate { name: string; description?: string; defaults: Partial; sequences?: { [K in keyof T]?: SequenceGenerator; }; valueObjects?: { [K in keyof T]?: ValueObjectGenerator; }; postProcessors?: Array<(aggregate: T) => Promise>; } /** * Factory implementation for creating DDD aggregates with business rule compliance. * * This factory provides a composable way to create aggregates with: * - Default values for common scenarios * - Sequence generation for unique fields * - Value object generation with proper validation * - Template-based creation for reusable patterns * - Batch generation with performance optimizations */ export declare class AggregateFactory { private readonly AggregateClass; private readonly config; private readonly defaults; private readonly sequences; private readonly valueObjects; private readonly templates; private readonly postProcessors; private sequenceCounters; /** * Creates a new AggregateFactory for the specified aggregate type. * * @param AggregateClass Constructor function for the aggregate * @param seederConfig Optional seeder configuration * @param factoryConfig Optional factory-specific configuration */ constructor(AggregateClass: new (...args: any[]) => T, seederConfig?: DomainSeederConfig, factoryConfig?: AggregateFactoryConfig); /** * Sets default values for aggregate properties. * * @param defaults Object containing default property values * @returns Factory instance for method chaining * * @example * ```typescript * const factory = new AggregateFactory(UserAggregate) * .withDefaults({ * status: 'active', * role: 'user', * emailVerified: false * }); * ``` */ withDefaults(defaults: Partial): this; /** * Adds a sequence generator for a specific property. * * @param property Property name to generate sequence values for * @param generator Function that generates sequential values * @returns Factory instance for method chaining * * @example * ```typescript * const factory = new AggregateFactory(UserAggregate) * .withSequence('email', n => `user${n}@example.com`) * .withSequence('username', n => `user_${String(n).padStart(4, '0')}`); * ``` */ withSequence(property: K, generator: SequenceGenerator): this; /** * Adds a value object generator for a specific property. * * @param property Property name to generate value objects for * @param generator Function that creates value objects * @returns Factory instance for method chaining * * @example * ```typescript * const factory = new AggregateFactory(UserAggregate) * .withValueObject('age', () => AgeVO.create(faker.number.int({ min: 18, max: 80 }))) * .withValueObject('email', () => EmailVO.create(faker.internet.email())) * .withValueObject('address', () => AddressVO.create({ * street: faker.location.streetAddress(), * city: faker.location.city(), * zipCode: faker.location.zipCode() * })); * ``` */ withValueObject(property: K, generator: ValueObjectGenerator): this; /** * Adds a post-processor function that modifies aggregates after creation. * * @param processor Async function that processes the aggregate * @returns Factory instance for method chaining * * @example * ```typescript * const factory = new AggregateFactory(UserAggregate) * .withPostProcessor(async (user) => { * // Add realistic interaction history * user.recordActivity('account_created'); * return user; * }) * .withPostProcessor(async (user) => { * // Set up initial preferences * user.updatePreferences({ notifications: true }); * return user; * }); * ``` */ withPostProcessor(processor: (aggregate: T) => Promise): this; /** * Registers a reusable template for aggregate creation. * * @param template Template configuration with predefined patterns * @returns Factory instance for method chaining * * @example * ```typescript * const adminTemplate: AggregateTemplate = { * name: 'admin-user', * description: 'Administrative user with full permissions', * defaults: { role: 'admin', status: 'active', emailVerified: true }, * sequences: { * email: n => `admin${n}@company.com` * }, * valueObjects: { * permissions: () => PermissionsVO.create(['read', 'write', 'admin']) * } * }; * * const factory = new AggregateFactory(UserAggregate) * .withTemplate(adminTemplate); * ``` */ withTemplate(template: AggregateTemplate): this; /** * Creates a single aggregate instance with applied rules and generators. * * @param overrides Optional property overrides for this instance * @param templateName Optional template to use for creation * @returns Promise resolving to created aggregate or error * * @example * ```typescript * // Basic creation with overrides * const user = await factory.create({ name: 'John Doe', age: 30 }); * * // Template-based creation * const admin = await factory.create({}, 'admin-user'); * ``` */ create(overrides?: Partial, templateName?: string): Promise>; /** * Creates multiple aggregate instances efficiently. * * @param count Number of aggregates to create * @param overrideGenerator Optional function to generate per-instance overrides * @param templateName Optional template to use for all instances * @returns Promise resolving to array of created aggregates or error * * @example * ```typescript * // Create 100 users with sequential emails * const users = await factory.createMany(100); * * // Create with per-instance overrides * const variedUsers = await factory.createMany(50, (index) => ({ * department: index < 25 ? 'Engineering' : 'Marketing', * level: Math.floor(index / 10) + 1 * })); * ``` */ createMany(count: number, overrideGenerator?: (index: number) => Partial, templateName?: string): Promise>; /** * Resets all sequence counters to their initial values. */ resetSequences(): void; /** * Gets the current value of a sequence counter. * * @param property Property name to get counter for * @returns Current counter value or 0 if not found */ getSequenceCounter(property: string): number; /** * Lists all registered templates. * * @returns Array of template names and descriptions */ getTemplates(): Array<{ name: string; description?: string; }>; /** * Builds aggregate data by merging defaults, sequences, value objects, and overrides. */ private buildAggregateData; /** * Applies sequence generators to aggregate data. */ private applySequences; /** * Applies value object generators to aggregate data. */ private applyValueObjects; /** * Gets and increments a sequence counter. */ private getAndIncrementCounter; /** * Generates a new EntityId using appropriate factory method. */ private generateEntityId; }