slonik
Version:
A Node.js PostgreSQL client with strict types, detailed logging and assertions.
251 lines • 13.3 kB
TypeScript
import { type ConnectionPoolClient } from './factories/createConnectionPool';
import { type DriverFactory, type DriverNotice, type DriverStream, type DriverTypeParser } from '@slonik/driver';
import { type SlonikError } from '@slonik/errors';
import { type PrimitiveValueExpression, type QuerySqlToken, type SqlToken } from '@slonik/sql-tag';
import type EventEmitter from 'node:events';
import { type ConnectionOptions as TlsConnectionOptions } from 'node:tls';
import { type Logger } from 'roarr';
import { type StrictEventEmitter } from 'strict-event-emitter-types';
import { type z, type ZodTypeAny } from 'zod';
export type ClientConfiguration = {
/**
* Dictates whether to capture stack trace before executing query. Middlewares access stack trace through query execution context. (Default: true)
*/
readonly captureStackTrace: boolean;
/**
* Number of times to retry establishing a new connection. (Default: 3)
*/
readonly connectionRetryLimit: number;
/**
* Timeout (in milliseconds) after which an error is raised if connection cannot cannot be established. (Default: 5000)
*/
readonly connectionTimeout: 'DISABLE_TIMEOUT' | number;
/**
* Connection URI, e.g. `postgres://user:password@localhost/database`.
*/
readonly connectionUri: string;
/**
* Allow using connections that are not associated with the transaction. (Default: false)
*/
readonly dangerouslyAllowForeignConnections: boolean;
/**
* Overrides the default DriverFactory. (Default: "pg" driver factory)
*/
readonly driverFactory?: DriverFactory;
/**
* Timeout (in milliseconds) that kicks in after a connection with an active query is requested to end. This is the amount of time that is allowed for query to complete before terminating it. (Default: 5000)
*/
readonly gracefulTerminationTimeout: number;
/**
* Timeout (in milliseconds) after which idle clients are closed. Use 'DISABLE_TIMEOUT' constant to disable the timeout. (Default: 60000)
*/
readonly idleInTransactionSessionTimeout: 'DISABLE_TIMEOUT' | number;
/**
* Timeout (in milliseconds) after which idle clients are closed. Use 'DISABLE_TIMEOUT' constant to disable the timeout. (Default: 5000)
*/
readonly idleTimeout: 'DISABLE_TIMEOUT' | number;
/**
* An array of [Slonik interceptors](https://github.com/gajus/slonik#slonik-interceptors).
*/
readonly interceptors: readonly Interceptor[];
/**
* Do not allow more than this many connections. (Default: 10)
*/
readonly maximumPoolSize?: number;
/**
* Ensure that at least this many connections are available in the pool. (Default: 0)
*/
readonly minimumPoolSize?: number;
/**
* Number of times a query failing with Transaction Rollback class error, that doesn't belong to a transaction, is retried. (Default: 5)
*/
readonly queryRetryLimit: number;
/**
* Routine that's invoked to reset the connection.
* The default routine invokes `DISCARD ALL`.
*/
readonly resetConnection?: (basicConnection: BasicConnection) => Promise<void>;
/**
* tls.connect options *
*/
readonly ssl?: TlsConnectionOptions;
/**
* Timeout (in milliseconds) after which database is instructed to abort the query. Use 'DISABLE_TIMEOUT' constant to disable the timeout. (Default: 60000)
*/
readonly statementTimeout: 'DISABLE_TIMEOUT' | number;
/**
* Number of times a transaction failing with Transaction Rollback class error is retried. (Default: 5)
*/
readonly transactionRetryLimit: number;
/**
* An array of [Slonik type parsers](https://github.com/gajus/slonik#slonik-type-parsers).
*/
readonly typeParsers: readonly DriverTypeParser[];
};
export type ClientConfigurationInput = Partial<ClientConfiguration>;
export type CommonQueryMethods = {
readonly any: QueryAnyFunction;
readonly anyFirst: QueryAnyFirstFunction;
readonly exists: QueryExistsFunction;
readonly many: QueryManyFunction;
readonly manyFirst: QueryManyFirstFunction;
readonly maybeOne: QueryMaybeOneFunction;
readonly maybeOneFirst: QueryMaybeOneFirstFunction;
readonly one: QueryOneFunction;
readonly oneFirst: QueryOneFirstFunction;
readonly query: QueryFunction;
readonly stream: StreamFunction;
readonly transaction: <T>(handler: TransactionFunction<T>, transactionRetryLimit?: number) => Promise<T>;
};
export type Connection = 'EXPLICIT' | 'IMPLICIT_QUERY' | 'IMPLICIT_TRANSACTION';
/**
* @see https://www.postgresql.org/docs/current/libpq-connect.html#LIBPQ-PARAMKEYWORDS
*/
export type ConnectionOptions = {
applicationName?: string;
databaseName?: string;
host?: string;
options?: string;
password?: string;
port?: number;
sslMode?: 'disable' | 'no-verify' | 'require';
username?: string;
};
export type ConnectionRoutine<T> = (connection: DatabasePoolConnection) => Promise<T>;
export type DatabaseConnection = DatabasePool | DatabasePoolConnection;
export type DatabasePool = CommonQueryMethods & DatabasePoolEventEmitter & {
readonly configuration: ClientConfiguration;
readonly connect: <T>(connectionRoutine: ConnectionRoutine<T>) => Promise<T>;
readonly end: () => Promise<void>;
readonly state: () => PoolState;
};
export type DatabasePoolConnection = CommonQueryMethods;
export type DatabasePoolEventEmitter = StrictEventEmitter<EventEmitter, {
error: (error: SlonikError) => void;
}>;
export type DatabaseTransactionConnection = CommonQueryMethods;
export type Field = {
readonly dataTypeId: number;
readonly name: string;
};
export type IdentifierNormalizer = (identifierName: string) => string;
export type Interceptor = {
readonly afterPoolConnection?: (connectionContext: ConnectionContext, connection: DatabasePoolConnection) => MaybePromise<null>;
readonly afterQueryExecution?: (queryContext: QueryContext, query: Query, result: QueryResult<QueryResultRow>) => MaybePromise<null>;
readonly beforePoolConnection?: (connectionContext: PoolContext) => MaybePromise<DatabasePool | null | undefined>;
readonly beforePoolConnectionRelease?: (connectionContext: ConnectionContext, connection: DatabasePoolConnection) => MaybePromise<null>;
readonly beforeQueryExecution?: (queryContext: QueryContext, query: Query) => MaybePromise<null | QueryResult<QueryResultRow>>;
readonly beforeQueryResult?: (queryContext: QueryContext, query: Query, result: QueryResult<QueryResultRow>) => MaybePromise<null>;
readonly beforeTransformQuery?: (queryContext: QueryContext, query: Query) => MaybePromise<null>;
readonly queryExecutionError?: (queryContext: QueryContext, query: Query, error: SlonikError, notices: readonly DriverNotice[]) => MaybePromise<null>;
readonly transformQuery?: (queryContext: QueryContext, query: Query) => Query;
readonly transformRow?: (queryContext: QueryContext, query: Query, row: QueryResultRow, fields: readonly Field[]) => MaybePromise<QueryResultRow>;
};
export type InternalNestedTransactionFunction = <T>(log: Logger, connection: ConnectionPoolClient, clientConfiguration: ClientConfiguration, handler: TransactionFunction<T>, transactionDepth: number, transactionRetryLimit?: number) => Promise<T>;
export type InternalQueryMethod<R = any> = (log: Logger, connection: ConnectionPoolClient, clientConfiguration: ClientConfiguration, slonikSql: QuerySqlToken, uid?: QueryId) => R;
export type InternalStreamFunction = <T>(log: Logger, connection: ConnectionPoolClient, clientConfiguration: ClientConfiguration, slonikSql: QuerySqlToken, streamHandler: StreamHandler<T>, uid?: QueryId) => Promise<StreamResult>;
export type InternalTransactionFunction = <T>(log: Logger, connection: ConnectionPoolClient, clientConfiguration: ClientConfiguration, handler: TransactionFunction<T>, transactionRetryLimit?: number) => Promise<T>;
export type MaybePromise<T> = Promise<T> | T;
/**
* @property log Instance of Roarr logger with bound connection context parameters.
* @property poolId Unique connection pool ID.
* @property query The query that is initiating the connection.
*/
export type PoolContext = {
readonly log: Logger;
readonly poolId: string;
readonly query: null | QuerySqlToken;
};
export type Query = {
readonly sql: string;
readonly values: readonly PrimitiveValueExpression[];
};
/**
* @property connectionId Unique connection ID.
* @property log Instance of Roarr logger with bound query context parameters.
* @property originalQuery A copy of the query before `transformQuery` middleware.
* @property poolId Unique connection pool ID.
* @property queryId Unique query ID.
* @property queryInputTime `process.hrtime.bigint()` for when query was received.
* @property resultParser A Zod function that parses the query result.
* @property sandbox Object used by interceptors to assign interceptor-specific, query-specific context.
* @property transactionId Unique transaction ID.
*/
export type QueryContext = {
readonly connectionId: string;
readonly log: Logger;
readonly originalQuery: Query;
readonly poolId: string;
readonly queryId: QueryId;
readonly queryInputTime: bigint | number;
readonly resultParser?: ZodTypeAny;
readonly sandbox: Record<string, unknown>;
readonly stackTrace: null | readonly CallSite[];
readonly transactionId: null | string;
};
export type QueryFunction = <T extends ZodTypeAny>(sql: QuerySqlToken<T>, values?: PrimitiveValueExpression[]) => Promise<QueryResult<z.infer<T>>>;
export type QueryId = string;
export type QueryResult<T> = {
readonly command: 'COPY' | 'DELETE' | 'INSERT' | 'SELECT' | 'UPDATE';
readonly fields: readonly Field[];
readonly notices: readonly DriverNotice[];
readonly rowCount: number;
readonly rows: readonly T[];
readonly type: 'QueryResult';
};
export type QueryResultRow = Record<string, PrimitiveValueExpression>;
export type QueryResultRowColumn = PrimitiveValueExpression;
export type StreamHandler<T> = (stream: DriverStream<T>) => void;
export type StreamResult = {
readonly notices: readonly DriverNotice[];
readonly type: 'StreamResult';
};
/**
* "string" type covers all type name identifiers – the literal values are added only to assist developer
* experience with auto suggestions for commonly used type name identifiers.
*/
export type TypeNameIdentifier = 'bool' | 'bytea' | 'float4' | 'float8' | 'int2' | 'int4' | 'int8' | 'json' | 'text' | 'timestamptz' | 'uuid' | string;
export type ValueExpression = PrimitiveValueExpression | SqlToken;
type BasicConnection = {
readonly query: (query: string) => Promise<void>;
};
type CallSite = {
readonly columnNumber: null | number;
readonly fileName: null | string;
readonly functionName: null | string;
readonly lineNumber: null | number;
};
/**
* @property connectionId Unique connection ID.
* @property log Instance of Roarr logger with bound connection context parameters.
* @property poolId Unique connection pool ID.
*/
type ConnectionContext = {
readonly connectionId: string;
readonly connectionType: Connection;
readonly log: Logger;
readonly poolId: string;
};
type PoolState = {
readonly acquiredConnections: number;
readonly idleConnections: number;
readonly pendingConnections: number;
readonly pendingDestroyConnections: number;
readonly pendingReleaseConnections: number;
readonly state: PoolStateName;
readonly waitingClients: number;
};
type PoolStateName = 'ACTIVE' | 'ENDED' | 'ENDING';
type QueryAnyFirstFunction = <T extends ZodTypeAny>(sql: QuerySqlToken<T>, values?: PrimitiveValueExpression[]) => Promise<ReadonlyArray<z.infer<T>[keyof z.infer<T>]>>;
type QueryAnyFunction = <T extends ZodTypeAny>(sql: QuerySqlToken<T>, values?: PrimitiveValueExpression[]) => Promise<ReadonlyArray<z.infer<T>>>;
type QueryExistsFunction = <T extends ZodTypeAny>(sql: QuerySqlToken<T>, values?: PrimitiveValueExpression[]) => Promise<boolean>;
type QueryManyFirstFunction = <T extends ZodTypeAny>(sql: QuerySqlToken<T>, values?: PrimitiveValueExpression[]) => Promise<ReadonlyArray<z.infer<T>[keyof z.infer<T>]>>;
type QueryManyFunction = <T extends ZodTypeAny>(sql: QuerySqlToken<T>, values?: PrimitiveValueExpression[]) => Promise<ReadonlyArray<z.infer<T>>>;
type QueryMaybeOneFirstFunction = <T extends ZodTypeAny>(sql: QuerySqlToken<T>, values?: PrimitiveValueExpression[]) => Promise<null | z.infer<T>[keyof z.infer<T>]>;
type QueryMaybeOneFunction = <T extends ZodTypeAny>(sql: QuerySqlToken<T>, values?: PrimitiveValueExpression[]) => Promise<null | z.infer<T>>;
type QueryOneFirstFunction = <T extends ZodTypeAny>(sql: QuerySqlToken<T>, values?: PrimitiveValueExpression[]) => Promise<z.infer<T>[keyof z.infer<T>]>;
type QueryOneFunction = <T extends ZodTypeAny>(sql: QuerySqlToken<T>, values?: PrimitiveValueExpression[]) => Promise<z.infer<T>>;
type StreamFunction = <T extends ZodTypeAny>(sql: QuerySqlToken<T>, streamHandler: StreamHandler<z.infer<T>>) => Promise<StreamResult>;
type TransactionFunction<T> = (connection: DatabaseTransactionConnection) => Promise<T>;
export type { Logger } from 'roarr';
//# sourceMappingURL=types.d.ts.map