From 8c6a31ea9751ba2465633a28132ce549ff1a7f60 Mon Sep 17 00:00:00 2001 From: Hem Brahmbhatt Date: Thu, 12 Apr 2018 19:20:04 +0100 Subject: [PATCH] Added definition for pg@7.x.x (#2064) * copied pg definition for v6.x.x to v7.x.x * added support for connectionTimeoutMillis and statement_timeout --- .../npm/pg_v7.x.x/flow_v0.28.x-/pg_v7.x.x.js | 296 ++++++++++++++++++ definitions/npm/pg_v7.x.x/test_pg_v7.x.x.js | 212 +++++++++++++ 2 files changed, 508 insertions(+) create mode 100644 definitions/npm/pg_v7.x.x/flow_v0.28.x-/pg_v7.x.x.js create mode 100644 definitions/npm/pg_v7.x.x/test_pg_v7.x.x.js diff --git a/definitions/npm/pg_v7.x.x/flow_v0.28.x-/pg_v7.x.x.js b/definitions/npm/pg_v7.x.x/flow_v0.28.x-/pg_v7.x.x.js new file mode 100644 index 0000000000..992e3de019 --- /dev/null +++ b/definitions/npm/pg_v7.x.x/flow_v0.28.x-/pg_v7.x.x.js @@ -0,0 +1,296 @@ +declare module pg { + // Note: Currently There are some issues in Function overloading. + // https://github.com/facebook/flow/issues/2423 + // So i temporarily remove the + // `((event: string, listener: Function) => EventEmitter );` + // from all overloading for EventEmitter.on(). + + // `any` types exised in this file, cause of currently `mixed` did not work well + // in Function Overloading. + + // `Function` types exised in this file, cause of they come from another + // untyped npm lib. + + /* Cause of > + /* + * PgPoolConfig's properties are passed unchanged to both + * the node-postgres Client constructor and the node-pool constructor + * allowing you to fully configure the behavior of both + * node-pool (https://github.com/coopernurse/node-pool) + */ + declare type PgPoolConfig = { + // node-pool ---------------- + name: string, + create: Function, + destroy: Function, + max: number, + min: number, + refreshIdle: boolean, + idleTimeoutMillis: number, + connectionTimeoutMillis: number, + reapIntervalMillis: number, + returnToHead: boolean, + priorityRange: number, + validate: Function, + validateAsync: Function, + log: Function, + + // node-postgres Client ------ + //database user's name + user: string, + //name of database to connect + database: string, + //database user's password + password: string, + //database port + port: number, + // database host. defaults to localhost + host?: string, + // whether to try SSL/TLS to connect to server. default value: false + ssl?: boolean, + // name displayed in the pg_stat_activity view and included in CSV log entries + // default value: process.env.PGAPPNAME + application_name?: string, + // fallback value for the application_name configuration parameter + // default value: false + fallback_application_name?: string, + // max milliseconds any query using this connection will execute for before timing out in error. false=unlimited + // default value: false + statement_timeout?: boolean | number, + // pg-pool + Client: mixed, + Promise: mixed, + onCreate: Function, + }; + + /* + * Not extends from Client, cause some of Client's functions(ex: connect and end) + * should not be used by PoolClient (which returned from Pool.connect). + */ + declare type PoolClient = { + release(error?: mixed): void, + + query: + ( (query: QueryConfig|string, callback?: QueryCallback) => Query ) & + ( (text: string, values: Array, callback?: QueryCallback) => Query ), + + on: + ((event: 'drain', listener: () => void) => events$EventEmitter )& + ((event: 'error', listener: (err: PG_ERROR) => void) => events$EventEmitter )& + ((event: 'notification', listener: (message: any) => void) => events$EventEmitter )& + ((event: 'notice', listener: (message: any) => void) => events$EventEmitter )& + ((event: 'end', listener: () => void) => events$EventEmitter ), + } + + declare type PoolConnectCallback = (error: PG_ERROR|null, + client: PoolClient|null, done: DoneCallback) => void; + declare type DoneCallback = (error?: mixed) => void; + // https://github.com/facebook/flow/blob/master/lib/node.js#L581 + // on() returns a events$EventEmitter + declare class Pool extends events$EventEmitter { + constructor(options: $Shape, Client?: Class): void; + connect(cb?: PoolConnectCallback): Promise; + take(cb?: PoolConnectCallback): Promise; + end(cb?: DoneCallback): Promise; + + // Note: not like the pg's Client, the Pool.query return a Promise, + // not a Thenable Query which Client returned. + // And there is a flow(<0.34) issue here, when Array, + // the overloading will not work + query: + ( (query: QueryConfig|string, callback?: QueryCallback) => Promise ) & + ( (text: string, values: Array, callback?: QueryCallback) => Promise); + + /* flow issue: https://github.com/facebook/flow/issues/2423 + * When this fixed, this overloading can be used. + */ + /* + on: + ((event: 'connect', listener: (client: PoolClient) => void) => events$EventEmitter )& + ((event: 'acquire', listener: (client: PoolClient) => void) => events$EventEmitter )& + ((event: "error", listener: (err: PG_ERROR) => void) => events$EventEmitter )& + ((event: string, listener: Function) => events$EventEmitter); + */ + } + + // <<------------- copy from 'pg-pool' ------------------------------ + + + // error + declare type PG_ERROR = { + name: string, + length: number, + severity: string, + code: string, + detail: string|void, + hint: string|void, + position: string|void, + internalPosition: string|void, + internalQuery: string|void, + where: string|void, + schema: string|void, + table: string|void, + column: string|void, + dataType: string|void, + constraint: string|void, + file: string|void, + line: string|void, + routine: string|void + }; + + declare type ClientConfig = { + //database user's name + user?: string, + //name of database to connect + database?: string, + //database user's password + password?: string, + //database port + port?: number, + // database host. defaults to localhost + host?: string, + // whether to try SSL/TLS to connect to server. default value: false + ssl?: boolean, + // name displayed in the pg_stat_activity view and included in CSV log entries + // default value: process.env.PGAPPNAME + application_name?: string, + // fallback value for the application_name configuration parameter + // default value: false + fallback_application_name?: string, + } + + declare type Row = { + [key: string]: mixed, + }; + declare type ResultSet = { + command: string, + rowCount: number, + oid: number, + rows: Array, + }; + declare type ResultBuilder = { + command: string, + rowCount: number, + oid: number, + rows: Array, + addRow: (row: Row) => void, + }; + declare type QueryConfig = { + name?: string, + text: string, + values?: any[], + }; + + declare type QueryCallback = (err: PG_ERROR|null, result: ResultSet|void) => void; + declare type ClientConnectCallback = (err: PG_ERROR|null, client: Client|void) => void; + + /* + * lib/query.js + * Query extends from EventEmitter in source code. + * but in Flow there is no multiple extends. + * And in Flow await is a `declare function $await(p: Promise | T): T;` + * seems can not resolve a Thenable's value type directly + * so `Query extends Promise` to make thing temporarily work. + * like this: + * const q = client.query('select * from some'); + * q.on('row',cb); // Event + * const result = await q; // or await + * + * ToDo: should find a better way. + */ + declare class Query extends Promise { + then( onFulfill?: (value: ResultSet) => Promise | U, + onReject?: (error: PG_ERROR) => Promise | U + ): Promise; + // Because then and catch return a Promise, + // .then.catch will lose catch's type information PG_ERROR. + catch( onReject?: (error: PG_ERROR) => ?Promise | U ): Promise; + + on : + ((event: 'row', listener: (row: Row, result: ResultBuilder) => void) => events$EventEmitter )& + ((event: 'end', listener: (result: ResultBuilder) => void) => events$EventEmitter )& + ((event: 'error', listener: (err: PG_ERROR) => void) => events$EventEmitter ); + } + + /* + * lib/client.js + * Note: not extends from EventEmitter, for This Type returned by on(). + * Flow's EventEmitter force return a EventEmitter in on(). + * ToDo: Not sure in on() if return events$EventEmitter or this will be more suitable + * return this will restrict event to given literial when chain on().on().on(). + * return a events$EventEmitter will fallback to raw EventEmitter, when chains + */ + declare class Client { + constructor(config?: string | ClientConfig): void; + connect(callback?: ClientConnectCallback):void; + end(): void; + + escapeLiteral(str: string): string; + escapeIdentifier(str: string): string; + + query: + ( (query: QueryConfig|string, callback?: QueryCallback) => Query ) & + ( (text: string, values: Array, callback?: QueryCallback) => Query ); + + on: + ((event: 'drain', listener: () => void) => this )& + ((event: 'error', listener: (err: PG_ERROR) => void) => this )& + ((event: 'notification', listener: (message: any) => void) => this )& + ((event: 'notice', listener: (message: any) => void) => this )& + ((event: 'end', listener: () => void) => this ); + } + + /* + * require('pg-types') + */ + declare type TypeParserText = (value: string) => any; + declare type TypeParserBinary = (value: Buffer) => any; + declare type Types = { + getTypeParser: + ((oid: number, format?: 'text') => TypeParserText )& + ((oid: number, format: 'binary') => TypeParserBinary ); + + setTypeParser: + ((oid: number, format?: 'text', parseFn: TypeParserText) => void )& + ((oid: number, format: 'binary', parseFn: TypeParserBinary) => void)& + ((oid: number, parseFn: TypeParserText) => void), + } + + /* + * lib/index.js ( class PG) + */ + declare class PG extends events$EventEmitter { + types: Types; + Client: Class; + Pool: Class; + Connection: mixed; //Connection is used internally by the Client. + constructor(client: Client): void; + native: { // native binding, have the same capability like PG + types: Types; + Client: Class; + Pool: Class; + Connection: mixed; + }; + // The end(),connect(),cancel() in PG is abandoned ? + } + + // These class are not exposed by pg. + declare type PoolType = Pool; + declare type PGType = PG; + declare type QueryType = Query; + // module export, keep same structure with index.js + declare module.exports: PG; +} diff --git a/definitions/npm/pg_v7.x.x/test_pg_v7.x.x.js b/definitions/npm/pg_v7.x.x/test_pg_v7.x.x.js new file mode 100644 index 0000000000..f28bf24ed0 --- /dev/null +++ b/definitions/npm/pg_v7.x.x/test_pg_v7.x.x.js @@ -0,0 +1,212 @@ +// @flow +import pg from 'pg'; +import type { + ResultSet, + ResultBuilder, + QueryType, + PG_ERROR, + Client, + Row, + DoneCallback, + PoolClient, + Pool, + PGType +} from 'pg'; + +pg.types.setTypeParser(1184, v => v); +pg.types.setTypeParser(1184, 'text', (v: string) => v); +// $ExpectError +pg.types.setTypeParser(1184, 'binary', (v: string) => v) +pg.types.setTypeParser(1184, 'binary', (v: Buffer) => v) +// $ExpectError +pg.types.setTypeParser(1184, (v: Buffer) => v) + +// There are two common ways to use node-postgres. +function test_pg() { + // 1. interact with your server via a pool of clients + function test_pool(pool: Pool) { + // 1.1 you can run queries directly against the pool + const rq: Promise = pool.query('select * from table;'); + // $ExpectError + const rqw: Promise = pool.query('select * from table;'); + const rq2: Promise = pool.query('Parameterized Queries',[1], + (err, result) => { + const _err: PG_ERROR|null = err; + // $ExpectError + const _err_w: number = err; + const _result: ResultSet|void = result; + // $ExpectError + const _result_w: number = result; + }); + // $ExpectError + const rq2_w: Promise = pool.query('Parameterized Queries',1); + + // 1.2 the pool also supports checking out a client for + // multiple operations, such as a transaction + const rc: Promise = pool.connect( (err, client, done) => { + const _err: PG_ERROR|null = err; + // $ExpectError + const _err_w: number = err; + const _client: PoolClient|null = client; + // $ExpectError + const _client_w: number = client; + const _done: DoneCallback = done; + // $ExpectError + const _done_w: number = done; + }); + // $ExpectError + const rc_w: number = pool.connect(); + + const rt: Promise = pool.take( (err, client, done) => { + const _err: PG_ERROR|null = err; + // $ExpectError + const _err_w: number = err; + const _client: PoolClient|null = client; + // $ExpectError + const _client_w: number = client; + const _done: DoneCallback = done; + // $ExpectError + const _done_w: number = done; + }); + // $ExpectError + const rt_w: number = pool.take(); + + const re: Promise = pool.end( err => { + // $ExpectError + const _err_w: string = err; // ?:mixed + }); + // $ExpectError + const re_w: Promise = pool.end(); + + // Note: There is a slight different between pool.query and client.query. + // client.query return a Query, pool.query return Promise + // class Query extends Promise + function test_PoolClient(client: PoolClient) { + const rr: void = client.release('any msg'); + const rr1: void = client.release(); + // $ExpectError + const rr_w: null = client.release(); + const rq: QueryType = client.query('select * from table;'); + // $ExpectError + const rqw: Promise = pool.query('select * from table;'); + rq.on('row', (row, result) => { + const _row: Row = row; + const _result: ResultBuilder = result; + // $ExpectError + const _row_w: number = row; + // $ExpectError + const _result_w: number = result; + }); + rq.on('end', (result) => { + const reselt: ResultBuilder = result; + }); + rq.on('error', (err) => { + const _err: PG_ERROR = err; + // $ExpectError + const _err_w: number = err; + }); + // $ExpectError + rq.on('wrong', ()=>{}); + + + const rq2: Promise = client.query('Parameterized Queries',[1], + (err, result) => { + const _err: PG_ERROR|null = err; + // $ExpectError + const _err_w: number = err; + const _result: ResultSet|void = result; + // $ExpectError + const _result_w: number = result; + }); + // $ExpectError + const rq2_w: Promise = client.query('Parameterized Queries',1); + } + } + + // 2. instantiate a client directly. + function test_client() { + const client = new pg.Client(); + client.connect((err, client) => { + const _err: PG_ERROR|null = err; + const _client: Client|void = client; + if (_client) { + const rq: QueryType = _client.query('select * from table;'); + const rq2: Promise = _client.query('Parameterized Queries',[1], + (err, result) => { + const _err: PG_ERROR|null = err; + // $ExpectError + const _err_w: number = err; + const _result: ResultSet|void = result; + // $ExpectError + const _result_w: number = result; + }); + // $ExpectError + const rq2_w: Promise = _client.query('Parameterized Queries',1); + + _client.on('drain', _ => { + const a: void = _; + }); + // $ExpectError + _client.on('drain',1); + _client.on('error', err => { + const _err: PG_ERROR = err; + }); + // $ExpectError + _client.on('error',1); + _client.on('notification', msg => { + }); + // $ExpectError + _client.on('notification',1); + _client.on('notice', msg => { + }); + // $ExpectError + _client.on('notice',1); + _client.on('end', _ => { + const a: void = _; + }); + // $ExpectError + _client.on('end',1); + } + }); + } +} + +// Simple example usage. +const pool = new pg.Pool({ + user: 'testuser', + password: 'testuser', + host: 'localhost', + database: 'testdb', + max: 10, + statement_timeout: false, + idleTimeoutMillis: 1000, + connectionTimeoutMillis: 1000 +}); + +// use pool +const promise_r = pool.query('select * from table;', ['11']); +// $ExpectError +const p:boolean = promise_r; // Promise +promise_r.then( result => { + // $ExpectError + const v:boolean = result.command; // string + // $ExpectError + const v2:boolean = result.oid; // string + // $ExpectError + const v3:boolean = result.rowCount; // string + // $ExpectError + const v4:boolean = result.rows; // Array + const rt:ResultSet = result; // the type of result +}) + +// directly use client +const promise_client = pool.connect(); +promise_client.then( client => { + client.query('select * from table;') + .then( result => { + // $ExpectError + const v:boolean = result; // result should be typed + }); + client.release('error msg'); // accept error msg + client.release(); // or without arguments +});