import type { Client } from "../../abstract/Client";
import type { OmitNew } from "../../internal/misc";
import type { CountInput, ExistsInput, InsertInput, LoadByInput, Order, SelectByInput, Table, UniqueKey, Where } from "../../types";
import { ID } from "../../types";
import type { UpdateOriginalInput } from "../types";
import type { VC } from "../VC";
import type { ConfigClass, ConfigInstance } from "./ConfigMixin";
export interface PrimitiveInstance<TTable extends Table> extends ConfigInstance {
    /**
     * VC of this Ent.
     */
    readonly vc: VC;
    /**
     * For simplicity, every Ent has an ID field name hardcoded to "id".
     */
    readonly [ID]: string;
    /**
     * Updates the object in the DB, but doesn't update the Ent itself (since it's
     * immutable).
     * - This method can work with CAS; see $cas property of the passed object.
     * - If a special value "skip-if-someone-else-changed-updating-ent-props" is
     *   passed to $cas, then the list of props for CAS is brought from the input,
     *   and the values of these props are brought from the Ent itself (i.e. from
     *   `this`).
     * - If a special value, a list of field names, is passed to $cas, then it
     *   works like described above, but the list of prop names is brought from
     *   that list of field names.
     * - Returns false if there is no such object in the DB, or if CAS check
     *   didn't succeed.
     * - Returns true if the object was found and updated.
     */
    updateOriginal(input: UpdateOriginalInput<TTable>): Promise<boolean>;
    /**
     * Deletes the object in the DB. Returns true if the object was found. Keeps
     * the current object untouched (since it's immutable).
     */
    deleteOriginal(): Promise<boolean>;
}
export type PrimitiveClass<TTable extends Table, TUniqueKey extends UniqueKey<TTable>, TClient extends Client> = OmitNew<ConfigClass<TTable, TUniqueKey, TClient>> & {
    /**
     * Runs INSERT mutation for the Ent.
     * - The Shard is inferred from the input fields using SHARD_AFFINITY.
     * - Returns ID of the newly inserted row.
     * - Returns null if the Ent violates unique key constraints.
     * - If the Ent has some triggers set up, this will be translated into two
     *   schema operations: idGen() and insert(), and before-triggers will run in
     *   between having the ID known in advance.
     */
    insertIfNotExists: (vc: VC, input: InsertInput<TTable>) => Promise<string | null>;
    /**
     * Inserts an Ent or updates an existing one if unique key matches.
     * - Don't use upsert() too often, because upsert may still delete IDs even if
     *   the object was updated, not inserted (there is no good ways to solve this
     *   in some DB engines like relational DBs so far).
     * - Upsert can't work if some triggers are defined for the Ent, because we
     *   don't know Ent ID in advance (whether the upsert succeeds or skips on
     *   duplication).
     */
    upsert: (vc: VC, input: InsertInput<TTable>) => Promise<string>;
    /**
     * Loads an Ent by its ID. Returns null if no such Ent exists. Try to use
     * loadX() instead as much as you can.
     */
    loadNullable: <TEnt extends PrimitiveInstance<TTable>>(this: new () => TEnt, vc: VC, id: string) => Promise<TEnt | null>;
    /**
     * Loads an Ent by its unique key. Returns null if no such Ent exists. Notice
     * that the key must be REALLY unique, otherwise the database may return
     * multiple items, and the API will break. Don't try to use this method with
     * non-unique keys!
     */
    loadByNullable: <TEnt extends PrimitiveInstance<TTable>>(this: new () => TEnt, vc: VC, input: LoadByInput<TTable, TUniqueKey>) => Promise<TEnt | null>;
    /**
     * Selects the list of Ents by their unique key prefix. The query can span
     * multiple Shards if their locations can be inferred from inverses related to
     * the fields mentioned in the query. Ordering of the results is not
     * guaranteed.
     */
    selectBy: <TEnt extends PrimitiveInstance<TTable>>(this: new () => TEnt, vc: VC, input: SelectByInput<TTable, TUniqueKey>) => Promise<TEnt[]>;
    /**
     * Selects the list of Ents by some predicate.
     * - The query can span multiple Shards if their locations can be inferred
     *   from inverses related to the fields mentioned in the query.
     * - In multi-Shard case, ordering of results is not guaranteed.
     * - In multi-Shard case, it may return more results than requested by limit
     *   (basically, limit is applied to each Shard individually). The caller has
     *   then freedom to reorder & slice the results as they wish.
     */
    select: <TEnt extends PrimitiveInstance<TTable>>(this: new () => TEnt, vc: VC, where: Where<TTable>, limit: number, order?: Order<TTable>, custom?: {}) => Promise<TEnt[]>;
    /**
     * Same as select(), but returns data in chunks.
     * - Uses multiple select() queries under the hood.
     * - The query can span multiple Shards if their locations can be inferred
     *   from inverses related to the fields mentioned in the query.
     * - Ents in each chunk always belong to the same Shard and are ordered by ID
     *   (there is no support for custom ordering). Make sure you have the right
     *   index in the database.
     */
    selectChunked: <TEnt extends PrimitiveInstance<TTable>>(this: new () => TEnt, vc: VC, where: Where<TTable>, chunkSize: number, limit: number, custom?: {}) => AsyncIterableIterator<TEnt[]>;
    /**
     * Returns count of Ents matching a predicate. The query can span multiple
     * Shards if their locations can be inferred from inverses related to the
     * fields mentioned in the query.
     */
    count: (vc: VC, where: CountInput<TTable>) => Promise<number>;
    /**
     * A more optimal approach than count() when we basically just need to know
     * whether we have "0 or not 0" rows.
     */
    exists: (vc: VC, where: ExistsInput<TTable>) => Promise<boolean>;
    /**
     * TS requires us to have a public constructor to infer instance types in
     * various places. We make this constructor throw if it's called.
     *
     * KLUDGE here: it should've been PrimitiveInstance<TTable> & Row<TTable>. But
     * unfortunately if we do so, TS disallows inheritance from PrimitiveClass and
     * thus breaks the chain of mixins. So we add Row<TTable> only at the very
     * late stage, in the latest mixin in the chain and not here.
     */
    new (): PrimitiveInstance<TTable>;
};
/**
 * Modifies the passed class adding support for the minimal number of basic Ent
 * operations. Internally, uses Schema abstractions to run them.
 */
export declare function PrimitiveMixin<TTable extends Table, TUniqueKey extends UniqueKey<TTable>, TClient extends Client>(Base: ConfigClass<TTable, TUniqueKey, TClient>): PrimitiveClass<TTable, TUniqueKey, TClient>;
//# sourceMappingURL=PrimitiveMixin.d.ts.map