import { AggregateExpression, BaseEntity, CompositeKey, DatabaseProviderBase, EntityPermissionType, RunViewResult, UserInfo } from '@memberjunction/core';
import { MJUserViewEntityExtended } from '@memberjunction/core-entities';
import { PubSubEngine } from 'type-graphql';
import { RunViewGenericParams, UserPayload } from '../types.js';
import { RunDynamicViewInput, RunViewByIDInput, RunViewByNameInput } from './RunViewResolver.js';
import { DeleteOptionsInput } from './DeleteOptionsInput.js';
import { MJEvent } from '@memberjunction/global';
export declare class ResolverBase {
    private static _emit;
    private static _cloudeventsHeaders;
    private static _eventSubscriptionKey;
    private get EventSubscriptions();
    /**
     * Maps field names to their GraphQL-safe CodeNames and handles encryption for API responses.
     *
     * For encrypted fields coming from raw SQL queries (not entity objects):
     * - AllowDecryptInAPI=true: Decrypt the value before sending to client
     * - AllowDecryptInAPI=false + SendEncryptedValue=true: Keep encrypted ciphertext
     * - AllowDecryptInAPI=false + SendEncryptedValue=false: Replace with sentinel
     *
     * @param entityName - The entity name
     * @param dataObject - The data object with field values
     * @param contextUser - Optional user context for decryption (required for encrypted fields)
     * @returns The processed data object
     */
    protected MapFieldNamesToCodeNames(entityName: string, dataObject: any, contextUser?: UserInfo): Promise<any>;
    /**
     * Reverse-maps GraphQL-safe field names back to entity CodeNames in a mutation input object.
     * For example, `_mj__integration_SyncStatus` is mapped back to `__mj_integration_SyncStatus`.
     * Also reverse-maps keys inside the `OldValues___` array if present.
     * This is the inverse of MapFieldNamesToCodeNames and must be called before passing
     * GraphQL input to entity SetMany() or field lookups.
     */
    protected ReverseMapInputFieldNames(input: Record<string, unknown>): Record<string, unknown>;
    protected ArrayMapFieldNamesToCodeNames(entityName: string, dataObjectArray: any[], contextUser?: UserInfo): Promise<any[]>;
    /**
     * Filters encrypted field values before sending to the API client.
     *
     * For each encrypted field in the entity:
     * - If AllowDecryptInAPI is true: value passes through unchanged (already decrypted by data provider)
     * - If AllowDecryptInAPI is false and SendEncryptedValue is true: re-encrypt and send ciphertext
     * - If AllowDecryptInAPI is false and SendEncryptedValue is false: replace with sentinel value
     *
     * @param entityName - Name of the entity
     * @param dataObject - The data object containing field values
     * @param encryptionEngine - Optional encryption engine for re-encryption (lazy loaded if needed)
     * @param contextUser - User context for encryption operations
     * @returns The filtered data object
     */
    protected FilterEncryptedFieldsForAPI(entityName: string, dataObject: Record<string, unknown>, contextUser: UserInfo): Promise<Record<string, unknown>>;
    /**
     * Filters encrypted fields for an array of data objects
     */
    protected ArrayFilterEncryptedFieldsForAPI(entityName: string, dataObjectArray: Record<string, unknown>[], contextUser: UserInfo): Promise<Record<string, unknown>[]>;
    protected findBy<T = any>(provider: DatabaseProviderBase, entity: string, params: any, contextUser: UserInfo): Promise<Array<T>>;
    RunViewByNameGeneric(viewInput: RunViewByNameInput, provider: DatabaseProviderBase, userPayload: UserPayload, pubSub: PubSubEngine): Promise<RunViewResult<any>>;
    RunViewByIDGeneric(viewInput: RunViewByIDInput, provider: DatabaseProviderBase, userPayload: UserPayload, pubSub: PubSubEngine): Promise<RunViewResult<any>>;
    RunDynamicViewGeneric(viewInput: RunDynamicViewInput, provider: DatabaseProviderBase, userPayload: UserPayload, pubSub: PubSubEngine): Promise<RunViewResult<any>>;
    RunViewsGeneric(viewInputs: (RunViewByNameInput & RunViewByIDInput & RunDynamicViewInput)[], provider: DatabaseProviderBase, userPayload: UserPayload): Promise<RunViewResult[]>;
    private static _priorEmittedData;
    protected EmitCloudEvent({ component, event, eventCode, args }: MJEvent): Promise<void>;
    protected CheckUserReadPermissions(entityName: string, userPayload: UserPayload | null): void;
    /**
     * Checks API key scope authorization. Only performs check if request
     * was authenticated via API key (apiKeyHash present in userPayload).
     * For OAuth/JWT auth, this is a no-op.
     *
     * @param scopePath - The scope path (e.g., 'entity:read', 'agent:execute')
     * @param resource - The resource name (e.g., entity name, agent name)
     * @param userPayload - The user payload from context
     * @throws AuthorizationError if API key lacks required scope
     */
    protected CheckAPIKeyScopeAuthorization(scopePath: string, resource: string, userPayload: UserPayload): Promise<void>;
    /**
     * Optimized RunViewGenericInternal implementation with:
     * - Field filtering at source (Fix #7)
     * - Improved error handling (Fix #9)
     */
    protected RunViewGenericInternal(provider: DatabaseProviderBase, viewInfo: MJUserViewEntityExtended, extraFilter: string, orderBy: string, userSearchString: string, excludeUserViewRunID: string | undefined, overrideExcludeFilter: string | undefined, saveViewResults: boolean | undefined, fields: string[] | undefined, ignoreMaxRows: boolean | undefined, excludeDataFromAllPriorViewRuns: boolean | undefined, forceAuditLog: boolean | undefined, auditLogDescription: string | undefined, resultType: string | undefined, userPayload: UserPayload | null, maxRows: number | undefined, startRow: number | undefined, aggregates?: AggregateExpression[]): Promise<RunViewResult<any>>;
    /**
     * Optimized implementation that:
     * 1. Fetches user info only once (fixes N+1 query)
     * 2. Processes views in parallel for independent operations
     * 3. Implements structured error logging
     */
    protected RunViewsGenericInternal(params: RunViewGenericParams[]): Promise<RunViewResult[]>;
    protected createRecordAccessAuditLogRecord(provider: DatabaseProviderBase, userPayload: UserPayload, entityName: string, recordId: any): Promise<any>;
    protected getRowLevelSecurityWhereClause(provider: DatabaseProviderBase, entityName: string, userPayload: UserPayload, type: EntityPermissionType, returnPrefix: string): string;
    protected createAuditLogRecord(provider: DatabaseProviderBase, userPayload: UserPayload, authorizationName: string | null, auditLogTypeName: string, status: string, details: string | null, entityId: string, recordId: any | null): Promise<any>;
    protected safeFirstArrayElement<T = any>(arr: T[]): T;
    protected packageSPParam(paramValue: any, quoteString: string): string;
    protected GetUserFromEmail(email: string): UserInfo | undefined;
    protected GetUserFromPayload(userPayload: UserPayload): UserInfo | undefined;
    get MJCoreSchema(): string;
    /**
     * Publishes a CACHE_INVALIDATION event to connected browser clients after a successful
     * entity save or delete. Includes the originSessionId so the originating browser can
     * skip redundant re-fetches (it already handled the event locally).
     */
    protected PublishCacheInvalidation(entityObject: BaseEntity, action: 'save' | 'delete', userPayload: UserPayload): void;
    protected ListenForEntityMessages(entityObject: BaseEntity, pubSub: PubSubEngine, userPayload: UserPayload): void;
    protected CreateRecord(entityName: string, input: any, provider: DatabaseProviderBase, userPayload: UserPayload, pubSub: PubSubEngine): Promise<any>;
    protected BeforeCreate(provider: DatabaseProviderBase, input: any): Promise<boolean>;
    protected AfterCreate(provider: DatabaseProviderBase, input: any): Promise<void>;
    protected UpdateRecord(entityName: string, input: any, provider: DatabaseProviderBase, userPayload: UserPayload, pubSub: PubSubEngine): Promise<any>;
    /**
     * This routine compares the OldValues property in the input object to the values in the DB that we just loaded. If there are differences, we need to check to see if the client
     * is trying to update any of those fields (e.g. overlap). If there is overlap, we throw an error. If there is no overlap, we can proceed with the update even if the DB Values
     * and the ClientOldValues are not 100% the same, so long as there is no overlap in the specific FIELDS that are different.
     *
     * ASSUMES: input object has an OldValues___ property that is an array of Key/Value pairs that represent the old values of the record that the client is trying to update.
     */
    protected TestAndSetClientOldValuesToDBValues(input: any, clientNewValues: any, entityObject: BaseEntity, contextUser: UserInfo): Promise<void>;
    protected DeleteRecord(entityName: string, key: CompositeKey, options: DeleteOptionsInput, provider: DatabaseProviderBase, userPayload: UserPayload, pubSub: PubSubEngine): Promise<any>;
    protected BeforeDelete(provider: DatabaseProviderBase, key: CompositeKey): Promise<boolean>;
    protected AfterDelete(provider: DatabaseProviderBase, key: CompositeKey): Promise<void>;
    protected BeforeUpdate(provider: DatabaseProviderBase, input: any): Promise<boolean>;
    protected AfterUpdate(provider: DatabaseProviderBase, input: any): Promise<void>;
}
//# sourceMappingURL=ResolverBase.d.ts.map