import { SessionService } from '../data-store/session.service';
import { CommandModel, CommandModuleOptions, DataListEntity, DataModel, DetailKey, ICommandOptions } from '../interfaces';
import { CommandService } from './command.service';
import { DataService } from './data.service';
export interface IMergeOptions<TItem extends {
    id: string;
}> {
    /** * Set true to merge pending async commands into the result.
     * If false/undefined -> acts as a simple passthrough.
     */
    latestFlg?: boolean;
    /**
     * Optional: Extract version from the query result item (e.g. RDS row).
     * If the provided version is >= session.version, the DynamoDB Data Table
     * check is skipped to reduce latency.
     */
    getVersion?: (item: TItem) => number | undefined;
    /**
     * Transform a CommandModel into the same shape as a TItem returned by the query.
     * The `existing` parameter is provided for update cases to merge unchanged fields.
     */
    transformCommand: (cmd: CommandModel, existing?: TItem) => TItem;
    /**
     * Optional filter applied AFTER transformCommand for "create-new" rows.
     * Prevents newly created items from appearing in lists where they don't match the current search criteria.
     */
    matchesFilter?: (item: TItem) => boolean;
}
export declare class Repository {
    private readonly options;
    private readonly dataService;
    private readonly commandService;
    private readonly sessionService;
    private readonly logger;
    private readonly moduleTableName;
    constructor(options: CommandModuleOptions, dataService: DataService, commandService: CommandService, sessionService: SessionService);
    /**
     * Get a single data item, merging a pending async command when a session exists.
     */
    getItem(key: DetailKey, options: ICommandOptions): Promise<DataModel>;
    /**
     * List items from the DynamoDB data table with an optional merge of pending async commands.
     *
     * When `mergeOptions.latestFlg` is true, the result is augmented with any
     * pending writes the current user has not yet seen reflected in the data table:
     *
     * - **update** — the existing item is replaced in-place, preserving its
     *   position in the list.
     * - **delete** — the item is removed from the result.
     * - **create-new** — the item is prepended to the top of the list, sorted by
     *   `updatedAt` descending when there are multiple pending creates.
     *
     * > **Sort-order note**: Prepended create-new items are not integrated into
     * > the caller's sort order (e.g. by `name` or `code`). They will appear
     * > at the top of the result until the async DynamoDB Stream sync completes and
     * > the next read returns fully sorted data. This is intentional — the
     * > guarantee is visibility, not sort position.
     */
    listItemsByPk(pk: string, opts?: {
        sk?: {
            skExpression: string;
            skAttributeValues: Record<string, string>;
            skAttributeNames?: Record<string, string>;
        };
        startFromSk?: string;
        limit?: number;
        order?: 'asc' | 'desc';
    }, mergeOptions?: {
        latestFlg?: boolean;
    }, options?: ICommandOptions): Promise<DataListEntity>;
    /**
     * List items from an external source (e.g., RDS/Elasticsearch) with an
     * optional merge of pending async commands.
     *
     * When `mergeOptions.latestFlg` is true, the result is augmented with any
     * pending writes the current user has not yet seen reflected in the query
     * source:
     *
     * - **update** — the existing item is replaced in-place via `transformCommand`,
     *   preserving its position. `existing` is passed to the transformer so join
     *   data (e.g. related RDS rows) can be carried over.
     * - **delete** — the item is removed and `total` is decremented.
     * - **create-new** — the item is transformed, optionally filtered by
     *   `matchesFilter`, and prepended to the top of the result sorted by
     *   `updatedAt` descending. `total` is incremented.
     *
     * > **Sort-order note**: Prepended create-new items are not integrated into
     * > the caller's sort order (e.g. by `name` or `code`). They will appear
     * > at the top of the result until the async Stream → RDS sync completes and
     * > the next read returns fully sorted data. This is intentional — the
     * > guarantee is visibility, not sort position.
     *
     * > **Pagination note**: `total` reflects the adjusted count after merge.
     * > However, prepended items sit outside the RDS `LIMIT`/`OFFSET` window, so
     * > on page 2+ the caller may see a one-item overlap or gap until sync
     * > completes. For most UX patterns (redirect-after-write, optimistic UI)
     * > this is not noticeable.
     */
    listItems<TItem extends {
        id: string;
    }>(query: () => Promise<{
        total: number;
        items: TItem[];
    }>, mergeOptions?: IMergeOptions<TItem>, options?: ICommandOptions): Promise<{
        total: number;
        items: TItem[];
    }>;
}
