UNPKG

@decaf-ts/for-postgres

Version:
199 lines (198 loc) 11 kB
import { Adapter, Sequence, type SequenceOptions, Repository, RelationsMetadata } from "@decaf-ts/core"; import { BaseError, Context, OperationKeys } from "@decaf-ts/db-decorators"; import "reflect-metadata"; import { type Constructor, Model } from "@decaf-ts/decorator-validation"; import { PostgresStatement } from "./query"; import { Pool, PoolConfig } from "pg"; import { PostgresFlags, type PostgresQuery, PostgresTableSpec } from "./types"; import { PostgresRepository } from "./PostgresRepository"; import { PostgresDispatch } from "./PostgresDispatch"; export declare function createdByOnPostgresCreateUpdate<M extends Model, R extends PostgresRepository<M>, V extends RelationsMetadata>(this: R, context: Context<PostgresFlags>, data: V, key: keyof M, model: M): Promise<void>; /** * @description Abstract adapter for Postgres database operations * @summary Provides a base implementation for Postgres database operations, including CRUD operations, sequence management, and error handling * @template Y - The scope type * @template F - The repository flags type * @template C - The context type * @param {Y} scope - The scope for the adapter * @param {string} flavour - The flavour of the adapter * @param {string} [alias] - Optional alias for the adapter * @class PostgresAdapter */ export declare class PostgresAdapter extends Adapter<Pool, PostgresQuery, PostgresFlags, Context<PostgresFlags>> { constructor(pool: Pool, alias?: string); protected flags<M extends Model>(operation: OperationKeys, model: Constructor<M>, flags: Partial<PostgresFlags>): Promise<PostgresFlags>; protected Dispatch(): PostgresDispatch; repository<M extends Model>(): Constructor<Repository<M, PostgresQuery, PostgresAdapter, PostgresFlags, Context<PostgresFlags>>>; /** * @description Creates a new Postgres statement for querying * @summary Factory method that creates a new PostgresStatement instance for building queries * @template M - The model type * @return {PostgresStatement<M, any>} A new PostgresStatement instance */ Statement<M extends Model>(): PostgresStatement<M, any>; /** * @description Creates a new PostgreSQL sequence * @summary Factory method that creates a new PostgreSQLSequence instance for managing sequences * @param {SequenceOptions} options - The options for the sequence * @return {Promise<Sequence>} A promise that resolves to a new Sequence instance */ Sequence(options: SequenceOptions): Promise<Sequence>; /** * @description Initializes the adapter by creating indexes for all managed models * @summary Sets up the necessary database indexes for all models managed by this adapter * @return {Promise<void>} A promise that resolves when initialization is complete */ initialize(): Promise<void>; /** * @description Creates indexes for the given models * @summary Abstract method that must be implemented to create database indexes for the specified models * @template M - The model type * @param {...Constructor<M>} models - The model constructors to create indexes for * @return {Promise<void>} A promise that resolves when all indexes are created */ protected index<M extends Model>(...models: Constructor<M>[]): Promise<void>; /** * @description Executes a raw SQL query against the database * @summary Abstract method that must be implemented to execute raw SQL queries * @template R - The result type * @param {PostgresQuery} q - The query to execute * @param {boolean} rowsOnly - Whether to return only the rows or the full response * @return {Promise<R>} A promise that resolves to the query result */ raw<R>(q: PostgresQuery, rowsOnly: boolean): Promise<R>; prepare<M extends Model>(model: M, pk: keyof M): { record: Record<string, any>; id: string; transient?: Record<string, any>; }; revert<M extends Model>(obj: Record<string, any>, clazz: string | Constructor<M>, pk: keyof M, id: string | number | bigint, transient?: Record<string, any>): M; /** * @description Creates a new record in the database * @summary Abstract method that must be implemented to create a new record * @param {string} tableName - The name of the table * @param {string|number} id - The ID of the record * @param {Record<string, any>} model - The model to create * @param {...any[]} args - Additional arguments * @return {Promise<Record<string, any>>} A promise that resolves to the created record */ create(tableName: string, id: string | number, model: Record<string, any>, ...args: any[]): Promise<Record<string, any>>; /** * @description Reads a record from the database * @summary Abstract method that must be implemented to read a record * @param {string} tableName - The name of the table * @param {string|number} id - The ID of the record * @param {string} pk - primary key colum * @return {Promise<Record<string, any>>} A promise that resolves to the read record */ read(tableName: string, id: string | number, pk: string): Promise<Record<string, any>>; /** * @description Updates a record in the database * @summary Abstract method that must be implemented to update a record * @param {string} tableName - The name of the table * @param {string|number} id - The ID of the record * @param {Record<string, any>} model - The model to update * @param {string} pk - Additional arguments * @return A promise that resolves to the updated record */ update(tableName: string, id: string | number, model: Record<string, any>, ...args: any[]): Promise<Record<string, any>>; /** * @description Deletes a record from the database * @summary Abstract method that must be implemented to delete a record * @param {string} tableName - The name of the table * @param {string|number} id - The ID of the record * @param {string} pk - Additional arguments * @return A promise that resolves to the deleted record */ delete(tableName: string, id: string | number, pk: string, ...args: any[]): Promise<Record<string, any>>; createAll(tableName: string, id: (string | number)[], model: Record<string, any>[], ...args: any[]): Promise<Record<string, any>[]>; readAll(tableName: string, id: (string | number | bigint)[], pk: string, ...args: any[]): Promise<Record<string, any>[]>; updateAll(tableName: string, ids: string[] | number[], model: Record<string, any>[], pk: string, ...args: any[]): Promise<Record<string, any>[]>; deleteAll(tableName: string, ids: (string | number | bigint)[], pk: string, ...args: any[]): Promise<Record<string, any>[]>; /** * @description Parses an error and converts it to a BaseError * @summary Converts various error types to appropriate BaseError subtypes * @param {Error|string} err - The error to parse * @param {string} [reason] - Optional reason for the error * @return {BaseError} The parsed error as a BaseError */ parseError(err: Error | string, reason?: string): BaseError; /** * @description Checks if an attribute is reserved * @summary Determines if an attribute name is reserved in PostgreSQL * @param {string} attr - The attribute name to check * @return {boolean} True if the attribute is reserved, false otherwise */ protected isReserved(attr: string): boolean; /** * @description Static method to parse an error and convert it to a BaseError * @summary Converts various error types to appropriate BaseError subtypes based on PostgreSQL error codes and messages * @param {Error|string} err - The error to parse * @param {string} [reason] - Optional reason for the error * @return {BaseError} The parsed error as a BaseError * @mermaid * sequenceDiagram * participant Caller * participant parseError * participant ErrorTypes * * Caller->>parseError: err, reason * Note over parseError: Check if err is already a BaseError * alt err is BaseError * parseError-->>Caller: return err * else err is string * Note over parseError: Extract code from string * alt code matches "duplicate key|already exists" * parseError->>ErrorTypes: new ConflictError(code) * ErrorTypes-->>Caller: ConflictError * else code matches "does not exist|not found" * parseError->>ErrorTypes: new NotFoundError(code) * ErrorTypes-->>Caller: NotFoundError * end * else err has code property * Note over parseError: Extract code and reason * else * Note over parseError: Use err.message as code * end * * Note over parseError: Switch on PostgreSQL error code * alt code is 23505 (unique_violation) * parseError->>ErrorTypes: new ConflictError(reason) * ErrorTypes-->>Caller: ConflictError * else code is 23503 (foreign_key_violation) * parseError->>ErrorTypes: new ConflictError(reason) * ErrorTypes-->>Caller: ConflictError * else code is 42P01 (undefined_table) * parseError->>ErrorTypes: new NotFoundError(reason) * ErrorTypes-->>Caller: NotFoundError * else code is 42703 (undefined_column) * parseError->>ErrorTypes: new NotFoundError(reason) * ErrorTypes-->>Caller: NotFoundError * else code is 42P07 (duplicate_table) * parseError->>ErrorTypes: new ConflictError(reason) * ErrorTypes-->>Caller: ConflictError * else code is 42P16 (invalid_table_definition) * parseError->>ErrorTypes: new IndexError(err) * ErrorTypes-->>Caller: IndexError * else code matches "ECONNREFUSED" * parseError->>ErrorTypes: new ConnectionError(err) * ErrorTypes-->>Caller: ConnectionError * else * parseError->>ErrorTypes: new InternalError(err) * ErrorTypes-->>Caller: InternalError * end */ protected static parseError(err: Error | string, reason?: string): BaseError; static connect(config: PoolConfig): Promise<Pool>; static createDatabase(pool: Pool, dbName: string): Promise<void>; static createNotifyFunction(pool: Pool, user: string): Promise<void>; static deleteDatabase(pool: Pool, dbName: string, user?: string): Promise<void>; static createUser(pool: Pool, dbName: string, user: string, password: string): Promise<void>; static deleteUser(pool: Pool, user: string, admin: string): Promise<void>; private static parseTypeToPostgres; private static parseValidationToPostgres; private static parseRelationsToPostgres; static createTable<M extends Model>(pool: Pool, model: Constructor<M>): Promise<Record<string, PostgresTableSpec>>; static getCurrentUser(pool: Pool): Promise<string>; static decoration(): void; }