import { Transaction } from '../utils/db.js';
import type { QueryOptions as BaseQueryOptions, ServiceParams as BaseServiceParams, OperationOptions, ReadResult } from '../types/index.js';
export type QueryOptions = BaseQueryOptions;
export type ServiceParams = BaseServiceParams;
export type { ReadResult, OperationOptions };
/**
 * ItemsService - Core CRUD service for all collections
 *
 * Provides:
 * - Read operations with filters, sorting, pagination, includes
 * - Create/Update/Delete operations with relation handling
 * - Permission enforcement and field-level security
 * - Multi-tenancy support
 * - Lifecycle hooks integration
 * - Soft-delete handling
 */
export declare class ItemsService {
    private collection;
    private accountability?;
    private tenant?;
    private table;
    private primaryKey;
    private isMultiTenant;
    constructor(collection: string, params?: ServiceParams);
    /**
     * Get primary key column from table (with type safety)
     */
    private getPrimaryKeyColumn;
    /**
     * Parse ID to correct type (string or number)
     * SECURITY: Rejects objects to prevent empty WHERE clause attacks
     */
    private parseId;
    /**
     * Extract all table names involved in a query (including relations)
     * This is CRITICAL for proper cache invalidation
     */
    private extractAllTables;
    /**
     * Get all involved tables from processed includes
     * Used for cache invalidation tracking
     */
    private getInvolvedTables;
    /**
     * Generate cache key from query parameters
     */
    private generateCacheKey;
    /**
     * Execute query with cache wrapper
     * Checks cache before querying, stores results after query
     */
    private executeWithCache;
    /**
     * Invalidate cache for this collection and all related tables
     * Called after any mutation (create, update, delete)
     */
    private invalidateCache;
    /**
     * Get role ID from accountability
     * The auth middleware should always set role.id from the database
     */
    private getRoleId;
    /**
     * Check if user is administrator
     */
    private isAdministrator;
    /**
     * Deduplicate joins by alias — removes duplicate join entries in-place.
     */
    private deduplicateJoins;
    /**
     * Apply tenant context to query filter
     */
    private enforceTenantContextFilter;
    /**
     * Validate and enforce tenant context on data
     */
    private validateAndEnforceTenantContext;
    /**
     * Helper to apply nested joins recursively
     */
    private applyNestedJoins;
    /**
     * Filter relational field attributes based on permission allowed fields
     *
     * When a user has permission to access only specific relational fields like:
     *   - members.id
     *   - members.fullName
     *
     * And they request "members.*", this method ensures only the allowed fields
     * are included in the query, not all fields from the related table.
     *
     * @param processedIncludes - The expanded includes from expandFieldsWithIncludes
     * @param allowedFields - The allowed fields from permissions (e.g., ['id', 'name', 'members.id', 'members.fullName'])
     * @param parentPath - The current path prefix for nested relations
     */
    private filterIncludesByAllowedFields;
    /**
     * Build complete query with filters, sorts, pagination, includes
     */
    private buildQuery;
    /**
     * Sanitize records by removing auto-added fields that user didn't request
     * This includes both main collection fields and nested relation fields
     *
     * @param records - Records to sanitize
     * @param userRequestedFields - Expanded direct fields requested by user (before auto-adding primary key)
     * @param userRequestedIncludes - ProcessedIncludes containing relation field info
     */
    private sanitizeAutoAddedFields;
    /**
     * Privilege/security-sensitive fields. A non-admin may write these ONLY when the
     * field is named EXPLICITLY in the permission's `fields` — never when it is merely
     * swept in by a "*" wildcard. This kills accidental mass-assignment from a broad
     * grant while still letting an admin deliberately delegate (e.g. a "user-manager"
     * role with fields:["*","role_Id"]).
     *  - role_Id / tenant_Id  : authorization scope — setting them is privilege escalation
     *  - userCreated_Id / userUpdated_Id : ownership/audit trail
     *  - emailVerified        : trust flag gating credential login
     * `hidden` schema fields are added dynamically and follow the same opt-in rule.
     * NOTE: filename/storage/isPublic are intentionally NOT here — legitimate file
     * metadata; handled at the storage layer (path confinement) and asset-access layer.
     */
    private static readonly PROTECTED_WRITE_FIELDS;
    /**
     * Fields that are NEVER client-writable via the data API, even when explicitly
     * named in a permission. `password` must go through the auth flow (hashing,
     * validation, session revocation), so a raw write here is always wrong.
     */
    private static readonly NEVER_WRITABLE_FIELDS;
    /**
     * The opt-in privilege fields for this collection: the static list plus every
     * `hidden` schema field. Hidden flags live on the JSON schema *definition*, not
     * the runtime Drizzle table, so read them from getSchemaDefinition() (fieldUtils
     * inspects the Drizzle table and can't see `hidden`).
     */
    private getProtectedWriteFields;
    /**
     * Apply field-level permissions
     */
    private applyFieldPermissions;
    /**
     * Validate nested/relational field data against allowed sub-fields
     * Handles both single object and array of objects for nested relations
     */
    private validateNestedFieldPermissions;
    /**
     * Get default values from permissions
     */
    private getDefaultValues;
    /**
     * Read with two-query approach for HasMany sorting
     */
    private readWithHasManyHandling;
    /**
     * Check if we need two-query approach for sorting by HasMany relations
     */
    private needsHasManyHandling;
    /**
     * Resolve whether the COUNT query should run for this request.
     *
     * Precedence:
     *  1. Explicit `query.count` (true/false) always wins.
     *  2. Otherwise fall back to env `COUNT_BY_DEFAULT` (defaults to `true`).
     *
     * Returns `false` only when the count is explicitly disabled or the
     * deployment default is off — in which case `totalCount` will be `null`.
     */
    private shouldComputeCount;
    /**
     * Read records by query
     */
    readByQuery(query?: QueryOptions, bypassPermissions?: boolean, transaction?: Transaction, options?: {
        includeHidden?: boolean;
    }): Promise<ReadResult>;
    /**
     * Execute aggregate query
     */
    private executeAggregateQuery;
    /**
     * Read a single record by ID
     */
    readOne(id: string | number, query?: QueryOptions, bypassPermissions?: boolean, transaction?: Transaction, options?: {
        includeHidden?: boolean;
    }): Promise<any>;
    /**
     * Create a new record
     * Uses createOneCore for the transactional logic and executes after hooks after commit
     */
    createOne(data: Record<string, any>, options?: OperationOptions): Promise<string | number>;
    /**
     * Internal method to perform core create logic without after hooks
     * Used by both createOne and createMany to separate transactional data operations
     * from after hooks that may have side effects (emails, third-party calls)
     *
     * @param data - Item data to create
     * @param transaction - Transaction to use
     * @param options - Operation options
     * @returns Object containing item ID, document, modified data, and related tables for cache invalidation
     */
    private createOneCore;
    /**
     * Create multiple records with transactional safety
     *
     * This method ensures that:
     * 1. All items are created within a single transaction
     * 2. If any creation fails, all previous creations are rolled back
     * 3. After hooks (which may have external side effects like emails, API calls)
     *    are only executed AFTER the transaction is successfully committed
     *
     * This prevents situations where:
     * - Emails are sent for items that were later rolled back
     * - Third-party systems are notified about changes that didn't persist
     *
     * @param items - Array of items to create
     * @param options - Operation options
     * @returns Array of created item IDs
     */
    createMany(items: Record<string, any>[], options?: OperationOptions): Promise<(string | number)[]>;
    /**
     * Internal method to perform core update logic without after hooks
     * Used by both updateOne and updateMany to separate transactional data operations
     * from after hooks that may have side effects (emails, third-party calls)
     *
     * @param id - Item ID to update
     * @param data - Item data to update
     * @param transaction - Transaction to use
     * @param options - Operation options
     * @returns Object containing update info for after hooks execution
     */
    private updateOneCore;
    /**
     * Update multiple records with transactional safety
     *
     * This method ensures that:
     * 1. All items are updated within a single transaction
     * 2. If any update fails, all previous updates are rolled back
     * 3. After hooks (which may have external side effects like emails, API calls)
     *    are only executed AFTER the transaction is successfully committed
     *
     * @param updates - Array of objects with id and data to update
     * @param options - Operation options
     * @returns Array of updated item IDs
     */
    updateMany(updates: {
        id: string | number;
        data?: Record<string, any>;
        [key: string]: any;
    }[], options?: OperationOptions): Promise<(string | number)[]>;
    /**
     * Update a record by ID
     * Uses updateOneCore for the transactional logic and executes after hooks after commit
     */
    updateOne(id: string | number, data: Record<string, any>, options?: OperationOptions): Promise<string | number>;
    /**
     * Internal method to perform core delete logic without after hooks
     * Used by both deleteOne and deleteMany to separate transactional data operations
     * from after hooks that may have side effects (emails, third-party calls)
     *
     * @param id - Item ID to delete
     * @param transaction - Transaction to use
     * @param options - Operation options
     * @returns Object containing delete info for after hooks execution
     */
    private deleteOneCore;
    /**
     * Delete multiple records with transactional safety
     *
     * This method ensures that:
     * 1. All items are deleted within a single transaction
     * 2. If any deletion fails, all previous deletions are rolled back
     * 3. After hooks (which may have external side effects like emails, API calls)
     *    are only executed AFTER the transaction is successfully committed
     *
     * @param ids - Array of item IDs to delete
     * @param options - Operation options
     * @returns Array of deleted item IDs
     */
    deleteMany(ids: (string | number)[], options?: OperationOptions): Promise<(string | number)[]>;
    /**
     * Delete a record by ID
     * Uses deleteOneCore for the transactional logic and executes after hooks after commit
     */
    deleteOne(id: string | number, options?: OperationOptions): Promise<string | number>;
    /**
     * Alias for readByQuery
     */
    list(query?: QueryOptions, bypassPermissions?: boolean, transaction?: Transaction): Promise<ReadResult>;
    /**
     * Alias for readOne
     */
    read(id: string | number, query?: QueryOptions, bypassPermissions?: boolean, transaction?: Transaction): Promise<any>;
    /**
     * Alias for createOne
     */
    create(data: Record<string, any>, options?: OperationOptions): Promise<string | number>;
    /**
     * Alias for updateOne
     */
    update(id: string | number, data: Record<string, any>, options?: OperationOptions): Promise<string | number>;
    /**
     * Alias for deleteOne
     */
    delete(id: string | number, options?: OperationOptions): Promise<string | number>;
    /**
     * Restore a soft-deleted record
     * Only works for collections with paranoid mode enabled
     */
    restore(id: string | number, options?: OperationOptions): Promise<string | number>;
    /**
     * Create an audit log entry for create/update/delete operations
     * @param action - The action performed (create, update, delete)
     * @param entityId - The ID of the entity
     * @param changes - The changes made (before and after states)
     * @param transaction - Optional transaction to use
     */
    private createAuditLog;
    /**
     * Convert date string fields to Date objects for DateTime/Timestamp fields
     * This is needed because Drizzle expects Date objects for timestamp columns
     * Note: Date type (date-only) and Time types expect strings, not Date objects
     */
    private convertDateFields;
}
export default ItemsService;
//# sourceMappingURL=ItemsService.d.ts.map