UNPKG

@clickup/ent-framework

Version:

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

215 lines 9.16 kB
import { inspect } from "util"; import type { Client } from "../abstract/Client"; import type { Handler } from "../abstract/Loader"; import { Loader } from "../abstract/Loader"; import type { QueryAnnotation } from "../abstract/QueryAnnotation"; import type { Shard } from "../abstract/Shard"; import { MASTER, STALE_REPLICA } from "../abstract/Shard"; import { Timeline } from "../abstract/Timeline"; import type { VCFlavor } from "./VCFlavor"; /** * Guest VC: has minimum permissions. Typically if the user is not logged in, * this VC is used. */ export declare const GUEST_ID = "guest"; /** * Temporary "omniscient" VC. Any Ent can be loaded with it, but this VC is * replaced with lower-pri VC as soon as possible. E.g. when some Ent is loaded * with omni VC, its ent.vc is assigned to either this Ent's "owner" VC * (accessible via VC pointing field) or, if not detected, to guest VC. */ export declare const OMNI_ID = "omni"; /** * VC - Viewer Context. * * VC is set per HTTP request (or per worker job) in each Ent and represents the * person who is about to run some database operation. It can represent a user, * or a guest, or a bot observing that Ent. * * Depending on the Ent's Configuration object and privacy rules, it may allow * the user to load/insert/update/etc. or to traverse to related objects. */ export declare class VC { /** Trace information to quickly find all the requests done by this VC in * debug logs. Trace is inherited once VC is derived. */ private readonly trace; /** A principal (typically user ID) represented by this VC. */ readonly principal: string; /** Allows to set VC to always use either a master or a replica DB. E.g. if * freshness=MASTER, then all the timeline data is ignored, and all the * requests are sent to master. */ readonly freshness: null | typeof MASTER | typeof STALE_REPLICA; /** Replication WAL position per Shard & Ent. Used to make decisions, * should a request be sent to a replica or to the master. */ private timelines; /** Sticky objects attached to the VC (and inherited when deriving). */ private flavors; /** The heartbeat callback is called before each primitive operation. It * plays the similar role as AbortController: when called, it may throw * sometimes (signalled externally). Delay callback can also be passed since * it's pretty common use case to wait for some time and be aborted on a * heartbeat exception. */ readonly heartbeater: { readonly heartbeat: () => Promise<void>; readonly delay: (ms: number) => Promise<void>; }; /** If true, it's the initial "root" VC which is not yet derived to any * user's VC. */ private isRoot; /** If nonzero, VC#cache() will return the values which will be auto-removed * when VC#cache() hasn't been called for more than this time. */ private cachesExpirationMs; private annotationCache?; private caches; private instanceNumber; /** * Please please don't call this method except one or two core places. The * idea is that we create an "origin" VC once and then derive all other VCs * from it (possibly upgrading or downgrading permissions, controlling * master/replica read policy etc.). It's also good to trace the entire chain * of calls and reasons, why some object was accessed. */ static createGuestPleaseDoNotUseCreationPointsMustBeLimited({ trace, cachesExpirationMs, }?: { trace?: string; cachesExpirationMs?: number; }): VC; /** * This is to show VCs in console.log() and inspect() nicely. */ [inspect.custom](): string; /** * Some IDs are cached in VC (e.g. is this ID readable? is it writable? is * this VC an admin VC?). Also, people may define their own VC-local caches. */ cache<TInstance>(Class: { new (vc: VC): TInstance; }): TInstance; /** * Same as the above overload, but allows to use a custom creating function. * This is useful when e.g. cached values are async-created. */ cache<TInstance>(tag: symbol, creator: (vc: VC) => TInstance): TInstance; /** * Returns a cached instance of Loader whose actual code is defined in * HandlerClass. In case there is no such Loader yet, creates it. */ loader<TLoadArgs extends unknown[], TReturn>(HandlerClass: { new (vc: VC): Handler<TLoadArgs, TReturn>; $loader?: symbol; }): Loader<TLoadArgs, TReturn>; /** * Returns Shard+schemaName timeline which tracks replica staleness for the * particular schema name (most likely, table). */ timeline(shard: Shard<Client>, schemaName: string): Timeline; /** * Serializes Shard timelines (master WAL positions) to a string format. The * method always returns a value which is compatible to * deserializeTimelines() input. */ serializeTimelines(): string | undefined; /** * Restores all replication timelines in the VC based on the serialized info * provided. Returns the new VC derived from the current one, but with empty * caches. * * This method has a side effect of changing the timelines of the current VC * (and actually all parent VCs), because it reflects the changes in the * global DB state as seen by the current VC's principal. It restores * previously serialized timelines to the existing VC and all its parent VCs * which share the same principal. (The latter happens, because * `this.timelines` map is passed by reference to all derived VCs starting * from the one which sets principal; see `new VC(...)` clauses all around and * toLowerInternal() logic.) The timelines are merged according to WAL * positions (larger WAL positions win). */ deserializeTimelines(...dataStrs: ReadonlyArray<string | undefined>): VC; /** * Returns a new VC derived from the current one, but with empty cache. */ withEmptyCache(): VC; /** * Returns a new VC derived from the current one, but with master freshness. * Master freshness is inherited by ent.vc after an Ent is loaded. */ withTransitiveMasterFreshness(): VC; /** * Returns a new VC derived from the current one, but which forces an Ent to * be loaded always from replica. Freshness is NOT inherited by Ents (not * transitive): e.g. if an Ent is loaded with STALE_REPLICA freshness, its * ent.vc will have the DEFAULT freshness. * * Also, if an Ent is inserted with a VC of STALE_REPLICA freshness, its VC * won't remember it, so next immediate reads will go to a replica and not to * the master. */ withOneTimeStaleReplica(): VC; /** * Creates a new VC with default freshness (i.e. not sticky to master or * replica, auto-detected on request). Generally, it's not a good idea to use * this derivation since we lose some bit of internal knowledge from the past * history of the VC, but for e.g. tests or benchmarks, it's fine. */ withDefaultFreshness(): VC; /** * Returns a new VC derived from the current one adding some more flavors to * it. If no flavors were added, returns the same VC (`this`). */ withFlavor(prepend: "prepend", ...flavors: Array<VCFlavor | undefined>): this; withFlavor(...flavors: Array<VCFlavor | undefined>): this; /** * Derives the VC with new trace ID. */ withNewTrace(trace: string | undefined): VC; /** * Derives the VC with the provided heartbeater injected. */ withHeartbeater(heartbeater: VC["heartbeater"]): VC; /** * Creates a new VC upgraded to omni permissions. This VC will not * be placed to some Ent's ent.vc property; instead, it will be * automatically downgraded to either the owning VC of this Ent or * to a guest VC (see Ent.ts). */ toOmniDangerous(): VC; /** * Creates a new VC downgraded to guest permissions. */ toGuest(): VC; /** * Checks if it's an omni VC. */ isOmni(): boolean; /** * Checks if it's a guest VC. */ isGuest(): boolean; /** * Checks if it's a regular user (i.e. owning) VC. */ isLoggedIn(): boolean; /** * Returns VC's flavor of the particular type. */ flavor<TFlavor extends VCFlavor>(flavor: new (...args: never[]) => TFlavor): TFlavor | null; /** * Used for debugging purposes. */ toString(withInstanceNumber?: boolean): string; /** * Returns a debug annotation of this VC. */ toAnnotation(): QueryAnnotation; /** * Used internally by Ent framework to lower permissions of an injected VC. * For guest, principal === null. * - freshness is always reset to default one it VC is demoted * - isRoot is changed to false once a root VC is switched to a per-user VC */ toLowerInternal(principal: string | null): VC; /** * Private constructor disallows inheritance and manual object creation. */ private constructor(); } //# sourceMappingURL=VC.d.ts.map