/** * Unique constraint checking utilities for CRUD operations. * * Handles both single-field constraints (e.g., "email") and compound constraints * (e.g., ["userId", "settingKey"]). All constraints are normalized to arrays internally. */ /** * Unique fields configuration as declared in collection config. * Can be single field names or arrays of field names for compound constraints. * * Example: ["email", ["userId", "settingKey"]] */ export type UniqueFieldsConfig = ReadonlyArray>; /** * Normalized constraints where all entries are arrays of field names. * * Example: [["email"], ["userId", "settingKey"]] */ export type NormalizedConstraints = ReadonlyArray>; /** * Normalize unique fields configuration to a consistent array-of-arrays format. * * Converts: * ["email", ["userId", "settingKey"]] * To: * [["email"], ["userId", "settingKey"]] * * This allows a single code path to handle both single and compound constraints. * * @param uniqueFields - Configuration from CollectionConfig.uniqueFields * @returns Normalized constraints where each constraint is an array of field names */ export declare const normalizeConstraints: (uniqueFields: UniqueFieldsConfig | undefined) => NormalizedConstraints; import { Effect } from "effect"; import { UniqueConstraintError, ValidationError } from "../../errors/crud-errors.js"; type HasId = { readonly id: string; }; /** * Check for unique constraint violations when creating or updating an entity. * * For each normalized constraint (array of field names): * 1. Extract the values for all fields in the constraint from the entity * 2. Skip if any field value is null or undefined (nulls are not unique-checked) * 3. Check if any existing entity (excluding the same ID) has matching values for ALL fields * 4. Fail-fast on first violation with UniqueConstraintError * * @param entity - The entity being created or updated * @param existingMap - Current state of the collection * @param constraints - Normalized constraints (array of field name arrays) * @param collectionName - Name of the collection for error messages * @returns Effect that succeeds with void or fails with UniqueConstraintError */ export declare const checkUniqueConstraints: (entity: T, existingMap: ReadonlyMap, constraints: NormalizedConstraints, collectionName: string) => Effect.Effect; /** * Check for unique constraint violations when creating multiple entities in a batch. * * This function performs two types of checks: * 1. Each entity against the existing map (same as checkUniqueConstraints) * 2. Each entity against other entities in the batch (inter-batch check) * * The inter-batch check ensures that if entities at index 3 and 7 both have * email: "alice@example.com", entity 7 fails (the later one in the batch). * * @param entities - The entities being created in the batch * @param existingMap - Current state of the collection * @param constraints - Normalized constraints (array of field name arrays) * @param collectionName - Name of the collection for error messages * @returns Effect that succeeds with void or fails with UniqueConstraintError */ export declare const checkBatchUniqueConstraints: (entities: ReadonlyArray, existingMap: ReadonlyMap, constraints: NormalizedConstraints, collectionName: string) => Effect.Effect; /** * Check a single entity against unique constraints, including a batch index of * previously-checked entities. Used by createMany with skipDuplicates. * * @param entity - The entity being checked * @param entityRecord - The entity as a record for field access * @param existingMap - Current state of the collection * @param constraints - Normalized constraints * @param collectionName - Name of the collection for error messages * @param batchIndex - Map of constraint keys to entity IDs from prior entities in the batch * @returns Effect that succeeds with void or fails with UniqueConstraintError */ export declare const checkEntityUniqueConstraints: (entity: T, entityRecord: Record, existingMap: ReadonlyMap, constraints: NormalizedConstraints, collectionName: string, batchIndex: Map) => Effect.Effect; /** * Add an entity's unique constraint values to the batch index. * Called after an entity passes unique constraint checks. * * @param entity - The entity to add * @param entityRecord - The entity as a record for field access * @param constraints - Normalized constraints * @param batchIndex - Map to populate with constraint keys -> entity IDs */ export declare const addEntityToBatchIndex: (entity: T, entityRecord: Record, constraints: NormalizedConstraints, batchIndex: Map) => void; /** * Validate that an upsert where clause targets a declared unique field or id. * * The where clause must fully cover at least one declared constraint: * - `{ id: "..." }` — always valid (id is implicitly unique) * - `{ email: "..." }` — valid if `[["email"]]` is in constraints * - `{ userId: "u1", settingKey: "theme" }` — valid if `[["userId", "settingKey"]]` is in constraints * - Extra fields beyond the constraint are allowed (for additional filtering) * * If no constraint is fully covered by the where clause, fail with ValidationError * listing the valid unique fields. * * @param where - The where clause object from upsert * @param constraints - Normalized constraints (array of field name arrays) * @param collectionName - Name of the collection for error messages * @returns Effect that succeeds with void or fails with ValidationError */ export declare const validateUpsertWhere: (where: Readonly>, constraints: NormalizedConstraints, collectionName: string) => Effect.Effect; export {}; //# sourceMappingURL=unique-check.d.ts.map