UNPKG

@clickup/ent-framework

Version:

A PostgreSQL graph-database-alike library with microsharding and row-level security

126 lines 6.93 kB
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