@decaf-ts/for-postgres
Version:
template for ts projects
199 lines (198 loc) • 11 kB
TypeScript
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;
}