import { Operation, CreateOperation, UpdateOperation, DeleteOperation, BatchOperations } from "../types/change-tracker.js"; import { EntityChanges } from "./entity-changes.js"; /** * Manages and organizes the changes of an Aggregate. * * Responsibilities: * - Stores all operations (create, update, delete) * - Orders operations respecting FK dependencies * - Groups operations by entity for batch execution * - Provides query and iteration methods * - Includes relationField, parentId, parentEntity for N:N support * * @example * ```typescript * // Define an entity map for type-safe operations * type UserEntities = { * User: User; * Post: Post; * Comment: Comment; * }; * * // Getting changes with types * const changes = user.getChanges(); * * // Filtering by entity with autocompletion * const postChanges = changes.of('Post'); * postChanges.creates.forEach(post => { * console.log(post.title); * }); * ``` */ export declare class AggregateChanges> { private ops; constructor(operations?: Operation[]); /** * Adds a create operation. * * @param entity - Entity name * @param data - Entity data * @param depth - Depth in the aggregate tree * @param parentId - Parent entity ID (for FK) * @param parentEntity - Parent entity name * @param relationField - Name of the relation field in parent (e.g., 'tags', 'comments') */ addCreate(entity: string, data: T, depth: number, parentId?: string, parentEntity?: string, relationField?: string): void; /** * Adds an update operation. */ addUpdate(entity: string, id: string, data: T, changedFields: Record, depth: number): void; /** * Adds a delete operation. * * @param entity - Entity name * @param id - Entity ID * @param data - Entity data (for reference) * @param depth - Depth in the aggregate tree * @param relationField - Name of the relation field in parent (e.g., 'tags', 'comments') * @param parentId - Parent entity ID (for N:N disconnect) * @param parentEntity - Parent entity name (for N:N disconnect) */ addDelete(entity: string, id: string, data: T, depth: number, relationField?: string, parentId?: string, parentEntity?: string): void; /** * Returns all create operations, sorted by ascending depth (root → leaf). */ creates(): CreateOperation[]; /** * Returns all update operations. */ updates(): UpdateOperation[]; /** * Returns all delete operations, sorted by descending depth (leaf → root). */ deletes(): DeleteOperation[]; /** * Iterator that returns operations in the correct execution order: * 1. Deletes (leaf → root) * 2. Creates (root → leaf) * 3. Updates */ operations(): Generator; /** * Returns all operations as an array in execution order. */ toArray(): Operation[]; /** * Converts the changes into BatchOperations for optimized execution. * * Groups operations by entity and sorts by depth: * - Deletes: depth DESC (leaf → root), grouped by entity + relationField + parentId * - Creates: depth ASC (root → leaf), grouped by entity + relationField * - Updates: grouped by entity * * @example * ```typescript * const batch = changes.toBatchOperations(); * * // Run deletes * for (const del of batch.deletes) { * if (registry.isReferenceCollection(del.parentEntity, del.relationField)) { * // N:N - disconnect only * await prisma[del.parentEntity].update({ * where: { id: del.parentId }, * data: { [del.relationField]: { disconnect: del.ids.map(id => ({ id })) } } * }); * } else { * // 1:N - delete entities * await prisma[del.entity].deleteMany({ where: { id: { in: del.ids } } }); * } * } * ``` */ toBatchOperations(): BatchOperations; /** * Groups deletes by entity + relationField + parentId, sorted by descending depth. * * For N:N relations, we need to group by parentId because disconnect * operations are performed on the parent entity. */ private groupDeletes; /** * Groups creates by entity + relationField, sorted by ascending depth. * * Preserves parentEntity for N:N connect operations. */ private groupCreates; /** * Groups updates by entity. */ private groupUpdates; /** * Filters changes by entity name. * * @param entityName - Name of the entity (e.g., 'Post', 'Comment') * @returns EntityChanges containing only the operations for this entity * * @example * ```typescript * const postChanges = changes.of('Post'); * * if (postChanges.hasCreates()) { * postChanges.creates.forEach(post => { * console.log('New post:', post.title); * }); * } * ``` */ of(entityName: K): EntityChanges; /** * Filters changes by relation field. * * @param relationField - Name of the relation field (e.g., 'tags', 'comments') * @returns New AggregateChanges containing only operations for this relation * * @example * ```typescript * const tagChanges = changes.forRelation('tags'); * // Contains only creates/deletes for the 'tags' relation * ``` */ forRelation(relationField: string): AggregateChanges; /** * Checks if there are create operations. */ hasCreates(): boolean; /** * Returns a new AggregateChanges without the specified entities. * * @param input - Entity name or array of entity names * @returns New AggregateChanges containing only operations for the remaining entities * * @example * ```typescript * const changes = new AggregateChanges([...]); * const filtered = changes.without('Post'); * // Contains only operations for entities other than 'Post' * ``` */ without(input: K | K[]): AggregateChanges; /** * Checks if there are update operations. */ hasUpdates(): boolean; /** * Checks if there are delete operations. */ hasDeletes(): boolean; /** * Checks if there are any operations. */ hasChanges(): boolean; /** * Checks if there are no operations. */ isEmpty(): boolean; /** * Returns the total number of operations. */ get count(): number; /** * Returns the raw operations (for debug/testing). */ get rawOperations(): Operation[]; /** * Lists all entities that have changes. */ getAffectedEntities(): string[]; /** * Lists all relation fields that have changes. */ getAffectedRelations(): string[]; /** * Clears all operations. */ clear(): void; /** * Creates a copy of the changes. */ clone(): AggregateChanges; } //# sourceMappingURL=aggregate-changes.d.ts.map