@clickup/ent-framework
Version:
A PostgreSQL graph-database-alike library with microsharding and row-level security
215 lines • 9.16 kB
TypeScript
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