UNPKG

@decaf-ts/db-decorators

Version:

Agnostic database decorators and repository

171 lines (170 loc) 7.27 kB
import { ContextArgs } from "./utils"; import { Contextual } from "../interfaces/Contextual"; import { OperationKeys } from "../operations/constants"; import { Constructor, Model } from "@decaf-ts/decorator-validation"; import { RepositoryFlags } from "./types"; /** * @description Factory type for creating context instances. * @summary Defines a function type that creates context instances with specific repository flags. * @template F - The repository flags type extending RepositoryFlags * @typedef {Function} ContextFactory * @memberOf module:db-decorators */ export type ContextFactory<F extends RepositoryFlags> = <C extends Context<F>>(arg: Omit<F, "timestamp">) => C; /** * @description Default factory for creating context instances. * @summary A factory function that creates new Context instances with the provided repository flags. * It automatically adds a timestamp to the context and returns a properly typed context instance. * @const DefaultContextFactory * @memberOf module:db-decorators */ export declare const DefaultContextFactory: ContextFactory<any>; /** * @description A context management class for handling repository operations. * @summary The Context class provides a mechanism for managing repository operations with flags, * parent-child relationships, and state accumulation. It allows for hierarchical context chains * and maintains operation-specific configurations while supporting type safety through generics. * * @template F - Type extending RepositoryFlags that defines the context configuration * * @param {ObjectAccumulator<F>} cache - The internal cache storing accumulated values * * @class * * @example * ```typescript * // Creating a new context with repository flags * const context = new Context<RepositoryFlags>(); * * // Accumulating values * const enrichedContext = context.accumulate({ * writeOperation: true, * affectedTables: ['users'], * operation: OperationKeys.CREATE * }); * * // Accessing values * const isWrite = enrichedContext.get('writeOperation'); // true * const tables = enrichedContext.get('affectedTables'); // ['users'] * ``` * * @mermaid * sequenceDiagram * participant C as Client * participant Ctx as Context * participant Cache as ObjectAccumulator * * C->>Ctx: new Context() * Ctx->>Cache: create cache * * C->>Ctx: accumulate(value) * Ctx->>Cache: accumulate(value) * Cache-->>Ctx: updated cache * Ctx-->>C: updated context * * C->>Ctx: get(key) * Ctx->>Cache: get(key) * alt Key exists in cache * Cache-->>Ctx: value * else Key not found * Ctx->>Ctx: check parent context * alt Parent exists * Ctx->>Parent: get(key) * Parent-->>Ctx: value * else No parent * Ctx-->>C: throw error * end * end * Ctx-->>C: requested value */ export declare class Context<F extends RepositoryFlags> { constructor(); static factory: ContextFactory<any>; private readonly cache; /** * @description Accumulates new values into the context. * @summary Merges the provided value object with the existing context state, * creating a new immutable cache state. * * @template F - current accumulator type * @template V - Type extending object for the values to accumulate * @param {V} value - The object containing values to accumulate * @returns A new context instance with accumulated values */ accumulate<V extends object>(value: V): Context<F & V>; get timestamp(): Date; /** * @description Retrieves a value from the context by key. * @summary Attempts to get a value from the current context's cache. * If not found, traverses up the parent context chain. * * @template K - Type extending keyof F for the key to retrieve * @template F - Accumulator type * @param {K} key - The key to retrieve from the context * @returns The value associated with the key * @throws {Error} If the key is not found in the context chain */ get<K extends keyof F>(key: K): F[K]; /** * @description Creates a child context * @summary Generates a new context instance with current context as parent * * @template M - Type extending Model * @param {OperationKeys} operation - The operation type * @param {Constructor<M>} [model] - Optional model constructor * @returns {C} New child context instance */ child<M extends Model, C extends Context<F>>(operation: OperationKeys, model?: Constructor<M>): C; /** * @description Creates a child context from another context * @summary Generates a new context instance with parent reference * * @template F - Type extending Repository Flags * @template C - Type extending Context<F> * @param {C} context - The parent context * @param {Partial<F>} [overrides] - Optional flag overrides * @returns {C} New child context instance */ static childFrom<F extends RepositoryFlags, C extends Context<F>>(context: C, overrides?: Partial<F>): C; /** * @description Creates a new context from operation parameters * @summary Generates a context instance for specific operation * * @template F - Type extending Repository Flags * @template M - Type extending Model * @param {OperationKeys.DELETE} operation - The operation type * @param {Partial<F>} overrides - Flag overrides * @param {Constructor<M>} model - The model constructor * @param {any} args - Operation arguments * @returns {Promise<C>} Promise resolving to new context */ static from<M extends Model, F extends RepositoryFlags, C extends Context<F>>(operation: OperationKeys.CREATE | OperationKeys.READ | OperationKeys.UPDATE | OperationKeys.DELETE, overrides: Partial<F>, model: Constructor<M>, ...args: any[]): Promise<C>; /** * @description Prepares arguments for context operations * @summary Creates a context args object with the specified operation parameters * * @template F - Type extending {@link RepositoryFlags} * @template M - Type extending {@link Model} * @param {OperationKeys.DELETE} operation - The operation type * @param {Constructor<M>} model - The model constructor * @param {any[]} args - Operation arguments * @param {Contextual<F>} [contextual] - Optional contextual object * @param {Partial<F>} [overrides] - Optional flag overrides * @returns {Promise<ContextArgs>} Promise resolving to context arguments * * @mermaid * sequenceDiagram * participant C as Context * participant M as Model * participant A as Args * * C->>C: Receive operation request * C->>M: Validate model constructor * C->>C: Create child context * C->>A: Process operation args * A->>C: Return context args * C->>C: Apply overrides * C->>C: Return final context */ static args<M extends Model, C extends Context<F>, F extends RepositoryFlags>(operation: OperationKeys.CREATE | OperationKeys.READ | OperationKeys.UPDATE | OperationKeys.DELETE, model: Constructor<M>, args: any[], contextual?: Contextual<F>, overrides?: Partial<F>): Promise<ContextArgs<F, C>>; }