InsidersByte/honeymoon-gift-list

View on GitHub
flow-typed/npm/pg_v6.x.x.js

Summary

Maintainability
A
2 hrs
Test Coverage
// flow-typed signature: 0fa8645f698c218659697bf5a3573a9c
// flow-typed version: cb69951a83/pg_v6.x.x/flow_>=v0.32.x

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 <flow 0.36 did not support export type very well,
  // so copy the types from pg-pool
  // https://github.com/flowtype/flow-typed/issues/16
  // https://github.com/facebook/flow/commit/843389f89c69516506213e298096a14867a45061
  const Pool = require('pg-pool');
  import type {
    PgPoolConfig,
    PoolConnectCallback,
    DoneCallback,
    PoolClient
  } from 'pg-pool';
  */

  // ------------- copy from 'pg-pool' ------------>>
  /*
   * 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,
    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,

    // 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<any>, 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<PgPoolConfig>, Client?: Class<Client>): void,
    connect(cb?: PoolConnectCallback): Promise<PoolClient>,
    take(cb?: PoolConnectCallback): Promise<PoolClient>,
    end(cb?: DoneCallback): Promise<void>,

    // 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<mixed>,
    // the overloading will not work
    query: ((query: QueryConfig | string, callback?: QueryCallback) => Promise<ResultSet>) & ((
      text: string,
      values: Array<any>,
      callback?: QueryCallback
    ) => Promise<ResultSet>),

    /* 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<Row>,
  };
  declare type ResultBuilder = {
    command: string,
    rowCount: number,
    oid: number,
    rows: Array<Row>,
    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<T>(p: Promise<T> | 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<ResultSet> {
    then<U>(onFulfill?: (value: ResultSet) => Promise<U> | U, onReject?: (error: PG_ERROR) => Promise<U> | U): Promise<U>,
    // Because then and catch return a Promise,
    // .then.catch will lose catch's type information PG_ERROR.
    catch<U>(onReject?: (error: PG_ERROR) => ?Promise<U> | U): Promise<U>,

    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,

    query: ((query: QueryConfig | string, callback?: QueryCallback) => Query) & ((text: string, values: Array<any>, 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<Client>,
    Pool: Class<Pool>,
    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<Client>,
      Pool: Class<Pool>,
      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;
}