pg-promise
Version:
PostgreSQL interface for Node.js
729 lines (557 loc) • 24.7 kB
TypeScript
/*
* Copyright (c) 2015-present, Vitaly Tomilov
*
* See the LICENSE file at the top-level directory of this distribution
* for licensing information.
*
* Removal or modification of this copyright notice is prohibited.
*/
import * as pg from './pg-subset';
import * as pgMinify from 'pg-minify';
import * as spexLib from 'spex';
// internal namespace for "txMode" property:
declare namespace _txMode {
// Transaction Isolation Level;
// API: https://vitaly-t.github.io/pg-promise/txMode.html#.isolationLevel
enum isolationLevel {
none = 0,
serializable = 1,
repeatableRead = 2,
readCommitted = 3
}
// TransactionMode class;
// API: https://vitaly-t.github.io/pg-promise/txMode.TransactionMode.html
class TransactionMode {
constructor(options?: { tiLevel?: isolationLevel, readOnly?: boolean, deferrable?: boolean })
begin(cap?: boolean): string
}
}
// Main protocol of the library;
// API: https://vitaly-t.github.io/pg-promise/module-pg-promise.html
declare namespace pgPromise {
interface ISpex {
batch: typeof spexLib.batch
page: typeof spexLib.page
sequence: typeof spexLib.sequence
errors: {
BatchError: spexLib.errors.BatchError,
PageError: spexLib.errors.PageError,
SequenceError: spexLib.errors.SequenceError
}
}
interface IQueryFileOptions {
debug?: boolean
minify?: boolean | 'after'
compress?: boolean
params?: any
noWarnings?: boolean
}
interface IFormattingOptions {
capSQL?: boolean
partial?: boolean
def?: any
}
interface ILostContext<C extends pg.IClient = pg.IClient> {
cn: string
dc: any
start: Date
client: C
}
interface IConnectionOptions<C extends pg.IClient = pg.IClient> {
direct?: boolean
onLost?(err: any, e: ILostContext<C>): void
}
interface IPreparedStatement {
name?: string
text?: string | QueryFile
values?: any[]
binary?: boolean
rowMode?: 'array' | null | void
rows?: number
types?: pg.ITypes
}
interface IParameterizedQuery {
text?: string | QueryFile
values?: any[]
binary?: boolean
rowMode?: void | 'array'
types?: pg.ITypes;
}
interface IPreparedParsed {
name: string
text: string
values: any[]
binary: boolean
rowMode: void | 'array'
rows: number
}
interface IParameterizedParsed {
text: string
values: any[]
binary: boolean
rowMode: void | 'array'
}
interface IColumnDescriptor<T> {
source: T
name: string
value: any
exists: boolean
}
interface IColumnConfig<T> {
name: string
prop?: string
mod?: FormattingFilter
cast?: string
cnd?: boolean
def?: any
init?(col: IColumnDescriptor<T>): any
skip?(col: IColumnDescriptor<T>): boolean
}
interface IColumnSetOptions {
table?: string | ITable | TableName
inherit?: boolean
duplicate?: 'error' | 'skip' | 'replace'
}
interface ITable {
schema?: string
table: string
}
type FormattingFilter = '^' | '~' | '#' | ':raw' | ':alias' | ':name' | ':json' | ':csv' | ':list' | ':value';
type QueryColumns<T> = Column<T> | ColumnSet<T> | Array<string | IColumnConfig<T> | Column<T>>;
type QueryParam =
string
| QueryFile
| IPreparedStatement
| IParameterizedQuery
| PreparedStatement
| ParameterizedQuery
| ((values?: any) => QueryParam);
type ValidSchema = string | string[] | null | void;
// helpers.TableName class;
// API: https://vitaly-t.github.io/pg-promise/helpers.TableName.html
class TableName {
constructor(table: string | ITable)
// these are all read-only:
readonly name: string;
readonly table: string;
readonly schema: string;
toString(): string
}
// helpers.Column class;
// API: https://vitaly-t.github.io/pg-promise/helpers.Column.html
class Column<T = unknown> {
constructor(col: string | IColumnConfig<T>);
// these are all read-only:
readonly name: string;
readonly prop: string;
readonly mod: FormattingFilter;
readonly cast: string;
readonly cnd: boolean;
readonly def: any;
readonly castText: string;
readonly escapedName: string;
readonly variable: string;
readonly init: (col: IColumnDescriptor<T>) => any
readonly skip: (col: IColumnDescriptor<T>) => boolean
toString(level?: number): string
}
// helpers.Column class;
// API: https://vitaly-t.github.io/pg-promise/helpers.ColumnSet.html
class ColumnSet<T = unknown> {
constructor(columns: Column<T>, options?: IColumnSetOptions)
constructor(columns: Array<string | IColumnConfig<T> | Column<T>>, options?: IColumnSetOptions)
constructor(columns: object, options?: IColumnSetOptions)
readonly columns: Column<T>[];
readonly names: string;
readonly table: TableName;
readonly variables: string;
assign(source?: { source?: object, prefix?: string }): string
assignColumns(options?: {
from?: string,
to?: string,
skip?: string | string[] | ((c: Column<T>) => boolean)
}): string
extend<K extends string>(columns: K[], opts?: {
skip?: boolean
}): ColumnSet<T & Record<K, unknown>>
extend<S>(columns: Column<S> | ColumnSet<S> | Array<IColumnConfig<S> | Column<S>>, opts?: {
skip?: boolean
}): ColumnSet<T & S>
merge<K extends string>(columns: K[]): ColumnSet<T & Record<K, unknown>>
merge<S>(columns: Column<S> | ColumnSet<S> | Array<IColumnConfig<S> | Column<S>>): ColumnSet<T & S>
prepare(obj: object): object
toString(level?: number): string
}
const minify: typeof pgMinify;
// Query Result Mask;
// API: https://vitaly-t.github.io/pg-promise/global.html#queryResult
enum queryResult {
one = 1,
many = 2,
none = 4,
any = 6
}
// PreparedStatement class;
// API: https://vitaly-t.github.io/pg-promise/PreparedStatement.html
class PreparedStatement {
constructor(options?: IPreparedStatement)
// standard properties:
name: string;
text: string | QueryFile;
values: any[];
// advanced properties:
binary: boolean;
rowMode: void | 'array';
rows: number;
types: pg.ITypes;
parse(): IPreparedParsed | errors.PreparedStatementError
toString(level?: number): string
}
// ParameterizedQuery class;
// API: https://vitaly-t.github.io/pg-promise/ParameterizedQuery.html
class ParameterizedQuery {
constructor(options?: string | QueryFile | IParameterizedQuery)
// standard properties:
text: string | QueryFile;
values: any[];
// advanced properties:
binary: boolean;
rowMode: void | 'array';
types: pg.ITypes;
parse(): IParameterizedParsed | errors.ParameterizedQueryError
toString(level?: number): string
}
// QueryFile class;
// API: https://vitaly-t.github.io/pg-promise/QueryFile.html
class QueryFile {
constructor(file: string, options?: IQueryFileOptions)
readonly error: Error;
readonly file: string;
readonly options: any;
prepare(): void
toString(level?: number): string
}
const txMode: typeof _txMode;
const utils: IUtils;
const as: IFormatting;
// Database full protocol;
// API: https://vitaly-t.github.io/pg-promise/Database.html
//
// We export this interface only to be able to help IntelliSense cast extension types correctly,
// which doesn't always work, depending on the version of IntelliSense being used.
interface IDatabase<Ext, C extends pg.IClient = pg.IClient> extends IBaseProtocol<Ext> {
connect(options?: IConnectionOptions<C>): Promise<IConnected<Ext, C>>
/////////////////////////////////////////////////////////////////////////////
// Hidden, read-only properties, for integrating with third-party libraries:
readonly $config: ILibConfig<Ext, C>
readonly $cn: string | pg.IConnectionParameters<C>
readonly $dc: any
readonly $pool: pg.IPool
}
interface IResultExt<T = unknown> extends pg.IResult<T> {
// Property 'duration' exists only in the following context:
// - for single-query events 'receive'
// - for method Database.result
duration?: number
}
// Post-initialization interface;
// API: https://vitaly-t.github.io/pg-promise/module-pg-promise.html
interface IMain<Ext = {}, C extends pg.IClient = pg.IClient> {
<T = Ext, C extends pg.IClient = pg.IClient>(cn: string | pg.IConnectionParameters<C>, dc?: any): IDatabase<T, C> & T
readonly PreparedStatement: typeof PreparedStatement
readonly ParameterizedQuery: typeof ParameterizedQuery
readonly QueryFile: typeof QueryFile
readonly queryResult: typeof queryResult
readonly minify: typeof pgMinify
readonly spex: ISpex
readonly errors: typeof errors
readonly utils: IUtils
readonly txMode: typeof txMode
readonly helpers: IHelpers
readonly as: IFormatting
readonly pg: typeof pg
end(): void
}
// Additional methods available inside tasks + transactions;
// API: https://vitaly-t.github.io/pg-promise/Task.html
interface ITask<Ext> extends IBaseProtocol<Ext>, ISpex {
readonly ctx: ITaskContext
}
interface ITaskIfOptions<Ext = {}> {
cnd?: boolean | ((t: ITask<Ext> & Ext) => boolean)
tag?: any
}
interface ITxIfOptions<Ext = {}> extends ITaskIfOptions<Ext> {
mode?: _txMode.TransactionMode | null
reusable?: boolean | ((t: ITask<Ext> & Ext) => boolean)
}
// Base database protocol
// API: https://vitaly-t.github.io/pg-promise/Database.html
interface IBaseProtocol<Ext> {
// API: https://vitaly-t.github.io/pg-promise/Database.html#query
query<T = any>(query: QueryParam, values?: any, qrm?: queryResult): Promise<T>
// result-specific methods;
// API: https://vitaly-t.github.io/pg-promise/Database.html#none
none(query: QueryParam, values?: any): Promise<null>
// API: https://vitaly-t.github.io/pg-promise/Database.html#one
one<T = any>(query: QueryParam, values?: any, cb?: (value: any) => T, thisArg?: any): Promise<T>
// API: https://vitaly-t.github.io/pg-promise/Database.html#oneOrNone
oneOrNone<T = any>(query: QueryParam, values?: any, cb?: (value: any) => T, thisArg?: any): Promise<T | null>
// API: https://vitaly-t.github.io/pg-promise/Database.html#many
many<T = any>(query: QueryParam, values?: any): Promise<T[]>
// API: https://vitaly-t.github.io/pg-promise/Database.html#manyOrNone
manyOrNone<T = any>(query: QueryParam, values?: any): Promise<T[]>
// API: https://vitaly-t.github.io/pg-promise/Database.html#any
any<T = any>(query: QueryParam, values?: any): Promise<T[]>
// API: https://vitaly-t.github.io/pg-promise/Database.html#result
result<T, R = IResultExt<T>>(query: QueryParam, values?: any, cb?: (value: IResultExt<T>) => R, thisArg?: any): Promise<R>
// API: https://vitaly-t.github.io/pg-promise/Database.html#multiResult
multiResult(query: QueryParam, values?: any): Promise<pg.IResult[]>
// API: https://vitaly-t.github.io/pg-promise/Database.html#multi
multi<T = any>(query: QueryParam, values?: any): Promise<Array<T[]>>
// API: https://vitaly-t.github.io/pg-promise/Database.html#stream
stream(qs: NodeJS.ReadableStream, init: (stream: NodeJS.ReadableStream) => void): Promise<{
processed: number,
duration: number
}>
// API: https://vitaly-t.github.io/pg-promise/Database.html#func
func<T = any>(funcName: string, values?: any, qrm?: queryResult): Promise<T>
// API: https://vitaly-t.github.io/pg-promise/Database.html#proc
proc<T = any>(procName: string, values?: any, cb?: (value: any) => T, thisArg?: any): Promise<T | null>
// API: https://vitaly-t.github.io/pg-promise/Database.html#map
map<T = any>(query: QueryParam, values: any, cb: (row: any, index: number, data: any[]) => T, thisArg?: any): Promise<T[]>
// API: https://vitaly-t.github.io/pg-promise/Database.html#each
each<T = any>(query: QueryParam, values: any, cb: (row: any, index: number, data: any[]) => void, thisArg?: any): Promise<T[]>
// Tasks;
// API: https://vitaly-t.github.io/pg-promise/Database.html#task
task<T>(cb: (t: ITask<Ext> & Ext) => T | Promise<T>): Promise<T>
task<T>(tag: string | number, cb: (t: ITask<Ext> & Ext) => T | Promise<T>): Promise<T>
task<T>(options: { tag?: any }, cb: (t: ITask<Ext> & Ext) => T | Promise<T>): Promise<T>
// Conditional Tasks;
// API: https://vitaly-t.github.io/pg-promise/Database.html#taskIf
taskIf<T>(cb: (t: ITask<Ext> & Ext) => T | Promise<T>): Promise<T>
taskIf<T>(tag: string | number, cb: (t: ITask<Ext> & Ext) => T | Promise<T>): Promise<T>
taskIf<T>(options: ITaskIfOptions<Ext>, cb: (t: ITask<Ext> & Ext) => T | Promise<T>): Promise<T>
// Transactions;
// API: https://vitaly-t.github.io/pg-promise/Database.html#tx
tx<T>(cb: (t: ITask<Ext> & Ext) => T | Promise<T>): Promise<T>
tx<T>(tag: string | number, cb: (t: ITask<Ext> & Ext) => T | Promise<T>): Promise<T>
tx<T>(options: {
tag?: any,
mode?: _txMode.TransactionMode | null
}, cb: (t: ITask<Ext> & Ext) => T | Promise<T>): Promise<T>
// Conditional Transactions;
// API: https://vitaly-t.github.io/pg-promise/Database.html#txIf
txIf<T>(cb: (t: ITask<Ext> & Ext) => T | Promise<T>): Promise<T>
txIf<T>(tag: string | number, cb: (t: ITask<Ext> & Ext) => T | Promise<T>): Promise<T>
txIf<T>(options: ITxIfOptions<Ext>, cb: (t: ITask<Ext> & Ext) => T | Promise<T>): Promise<T>
}
// Database object in connected state;
// API: https://vitaly-t.github.io/pg-promise/Database.html#connect
interface IConnected<Ext, C extends pg.IClient> extends IBaseProtocol<Ext>, ISpex {
readonly client: C
// Note that for normal connections (working with the pool), method `done` accepts `kill`
// flag to terminate the connection within the pool, so it can be auto-recreated;
// And in this case the method returns nothing / void.
// But for direct connections (connect({direct: true})), `kill` flag is ignored, because
// the connection is always closed physically, which may take time, and so in this case
// the method returns a Promise to indicate when the connection finished closing.
done(kill?: boolean): void | Promise<void>;
// Repeated calls are not allowed and will throw an error.
}
// Event context extension for tasks + transactions;
// See: https://vitaly-t.github.io/pg-promise/global.html#TaskContext
interface ITaskContext {
// these are set at the beginning of each task/transaction:
readonly context: any
readonly parent: ITaskContext | null
readonly connected: boolean
readonly inTransaction: boolean
readonly level: number
readonly useCount: number
readonly isTX: boolean
readonly start: Date
readonly tag: any
readonly dc: any
// these are set at the end of each task/transaction:
readonly finish?: Date
readonly duration?: number
readonly success?: boolean
readonly result?: any
// this exists only inside transactions (isTX = true):
readonly txLevel?: number
// Version of PostgreSQL Server to which we are connected;
// This property is not available with Native Bindings!
readonly serverVersion: string
}
// Generic Event Context interface;
// See: https://vitaly-t.github.io/pg-promise/global.html#EventContext
interface IEventContext<C extends pg.IClient = pg.IClient> {
client: C
cn: any
dc: any
query: any
params: any,
values: any,
queryFilePath?: string,
ctx: ITaskContext
}
// Errors namespace
// API: https://vitaly-t.github.io/pg-promise/errors.html
namespace errors {
// QueryResultError interface;
// API: https://vitaly-t.github.io/pg-promise/errors.QueryResultError.html
class QueryResultError extends Error {
// standard error properties:
name: string;
message: string;
stack: string;
// extended properties:
result: pg.IResult;
received: number;
code: queryResultErrorCode;
query: string;
values: any;
// API: https://vitaly-t.github.io/pg-promise/errors.QueryResultError.html#toString
toString(): string
}
// QueryFileError interface;
// API: https://vitaly-t.github.io/pg-promise/errors.QueryFileError.html
class QueryFileError extends Error {
// standard error properties:
name: string;
message: string;
stack: string;
// extended properties:
file: string;
options: IQueryFileOptions;
error: pgMinify.SQLParsingError;
toString(level?: number): string
}
// PreparedStatementError interface;
// API: https://vitaly-t.github.io/pg-promise/errors.PreparedStatementError.html
class PreparedStatementError extends Error {
// standard error properties:
name: string;
message: string;
stack: string;
// extended properties:
error: QueryFileError;
toString(level?: number): string
}
// ParameterizedQueryError interface;
// API: https://vitaly-t.github.io/pg-promise/errors.ParameterizedQueryError.html
class ParameterizedQueryError extends Error {
// standard error properties:
name: string;
message: string;
stack: string;
// extended properties:
error: QueryFileError;
toString(level?: number): string
}
// Query Result Error Code;
// API: https://vitaly-t.github.io/pg-promise/errors.html#.queryResultErrorCode
enum queryResultErrorCode {
noData = 0,
notEmpty = 1,
multiple = 2
}
}
// Library's Initialization Options
// API: https://vitaly-t.github.io/pg-promise/module-pg-promise.html
interface IInitOptions<Ext = {}, C extends pg.IClient = pg.IClient> {
noWarnings?: boolean
pgFormatting?: boolean
pgNative?: boolean
capSQL?: boolean
schema?: ValidSchema | ((dc: any) => ValidSchema)
connect?(e: { client: C, dc: any, useCount: number }): void
disconnect?(e: { client: C, dc: any }): void
query?(e: IEventContext<C>): void
// NOTE: The result is undefined when data comes from QueryStream, i.e. via method Database.stream
receive?(e: { data: any[], result: IResultExt | void, ctx: IEventContext<C> }): void
task?(e: IEventContext<C>): void
transact?(e: IEventContext<C>): void
error?(err: any, e: IEventContext<C>): void
extend?(obj: IDatabase<Ext, C> & Ext, dc: any): void
}
// API: https://vitaly-t.github.io/pg-promise/Database.html#$config
interface ILibConfig<Ext, C extends pg.IClient = pg.IClient> {
version: string
promise: IGenericPromise
options: IInitOptions<Ext, C>
pgp: IMain<Ext, C>
$npm: any
}
// Custom-Type Formatting object
// API: https://github.com/vitaly-t/pg-promise#custom-type-formatting
interface ICTFObject {
toPostgres(a: any): any
}
// Query formatting namespace;
// API: https://vitaly-t.github.io/pg-promise/formatting.html
interface IFormatting {
ctf: { toPostgres: symbol, rawType: symbol }
alias(name: string | (() => string)): string
array(arr: any[] | (() => any[]), options?: { capSQL?: boolean }): string
bool(value: any | (() => any)): string
buffer(obj: object | (() => object), raw?: boolean): string
csv(values: any | (() => any)): string
date(d: Date | (() => Date), raw?: boolean): string
format(query: string | QueryFile | ICTFObject, values?: any, options?: IFormattingOptions): string
func(func: (cc: any) => any, raw?: boolean, cc?: any): string
json(data: any | (() => any), raw?: boolean): string
name(name: any | (() => any)): string
number(value: number | bigint | (() => number | bigint)): string
text(value: any | (() => any), raw?: boolean): string
value(value: any | (() => any)): string
}
interface ITaskArguments<T> extends IArguments {
options: { tag?: any, cnd?: any, mode?: _txMode.TransactionMode | null } & T
cb(): any
}
// General-purpose functions
// API: https://vitaly-t.github.io/pg-promise/utils.html
interface IUtils {
camelize(text: string): string
camelizeVar(text: string): string
enumSql(dir: string, options?: {
recursive?: boolean,
ignoreErrors?: boolean
}, cb?: (file: string, name: string, path: string) => any): any
taskArgs<T = {}>(args: IArguments): ITaskArguments<T>
}
// Query Formatting Helpers
// API: https://vitaly-t.github.io/pg-promise/helpers.html
interface IHelpers {
concat(queries: Array<string | QueryFile | {
query: string | QueryFile,
values?: any,
options?: IFormattingOptions
}>): string
insert(data: object | object[], columns?: QueryColumns<any> | null, table?: string | ITable | TableName): string
update(data: object | object[], columns?: QueryColumns<any> | null, table?: string | ITable | TableName, options?: {
tableAlias?: string,
valueAlias?: string,
emptyUpdate?: any
}): any
values(data: object | object[], columns?: QueryColumns<any> | null): string
sets(data: object, columns?: QueryColumns<any> | null): string
Column: typeof Column
ColumnSet: typeof ColumnSet
TableName: typeof TableName
_TN(path: TemplateStringsArray, ...args: Array<any>): ITable
_TN(path: string): ITable
}
interface IGenericPromise {
(cb: (resolve: (value?: any) => void, reject: (reason?: any) => void) => void): Promise<any>
resolve(value?: any): void
reject(reason?: any): void
all(iterable: any): Promise<any>
}
}
// Default library interface (before initialization)
// API: https://vitaly-t.github.io/pg-promise/module-pg-promise.html
declare function pgPromise<Ext = {}, C extends pg.IClient = pg.IClient>(options?: pgPromise.IInitOptions<Ext, C>): pgPromise.IMain<Ext, C>
export = pgPromise;