import { ClientBase , Pool , QueryResult } from "pg" ; import createDebug from "debug" ; const debug = createDebug ( "chess:query" ) ; export type Pg = ClientBase | Pool ; export { QueryResult } ; let _pg ; const q = ( pg ) => { _pg = pg ; return _q ; } ; const _q = async < T > ( strings , ... values ) : Promise < QueryResult < T > > => { const pg = _pg ! ; _pg = undefined ; const { length } = values ; let text = strings [ 0 ] ; for ( let idx = 1 ; idx <= length ; idx ++ ) { text += `$${ idx }` ; text += strings [ idx ] ; } text = text . trim ( ) ; let name ; if ( text . slice ( 0 , 2 ) === "--" ) { const idx = text . indexOf ( "\n" ) ; name = text . slice ( 2 , idx ) . trim ( ) ; text = text . slice ( idx + 1 ) ; } debug ( name || "!UNNAMED!" , values ) ; const res = await pg . query ( { name , text , values } ) ; for ( const field of res . fields ) { field . name = fromUnderscored ( field . name ) ; } res . rows = res . rows . map ( ( raw ) => { const out = { } ; for ( const rawField in raw ) { const outField = fromUnderscored ( rawField ) ; out [ outField ] = raw [ rawField ] ; } return out ; } ) ; return res ; } ; const fromUnderscored = ( input ) : string => { const parts = input . split ( "_" ) ; let out = parts . shift ( ) ; for ( const part of parts ) { out += part [ 0 ] . toUpperCase ( ) + part . slice ( 1 ) ; } return out || "" ; } ; q . withClient = async < T > ( pg , fn ) : Promise < T > => { if ( "idleCount" in pg ) { const pool = < Pool > pg ; const client = await pool . connect ( ) ; try { return await fn ( client ) ; } finally { client . release ( ) ; } } else { return fn ( < ClientBase > pg ) ; } } ; q . transact = < T > ( pg , fn ) : Promise < T > => { return q . withClient ( pg , async ( pg ) => { let res ; await pg . query ( `begin` ) ; try { res = await fn ( pg ) ; } catch ( err ) { await pg . query ( "rollback" ) ; throw err ; } await pg . query ( "commit" ) ; return res ; } ) ; } ; export default q ;