import { jsonSerializer } from '@deepkit/type' ; import { Injectable , Type } from '@nestjs/common' ; import { OgmaService } from '@ogma/nestjs-module' ; import { Pool } from 'pg' ; import { from , Observable , of } from 'rxjs' ; import { catchError , map , tap } from 'rxjs/operators' ; import { DatabaseFeatureOptions , DatabaseInterface , InsertParams , QueryParams , UpdateManyParams , UpdateParams , } from './interfaces/database.interface' ; @ Injectable ( ) export class DatabaseService < T > implements DatabaseInterface < T > { tableName : string ; constructor ( private readonly pool , readonly feature , private readonly logger ) { this . tableName = feature . tableName ; } private runQuery ( query , params , type ) { const start = Date . now ( ) ; return from ( this . pool . query ( query , params ) ) . pipe ( tap ( ( qRes ) => { this . logger . debug ( { query , time : Date . now ( ) - start , rows : qRes . rowCount , } ) ; } ) , map ( ( qRes ) => qRes . rows . map ( this . underScoreToCamelCase ) . map ( ( row ) => jsonSerializer . for ( type ) . deserialize ( row ) ) ) , catchError ( ( err ) => { this . logger . debug ( { query , time : Date . now ( ) - start , } ) ; this . logger . printError ( err ) ; return of ( [ ] ) ; } ) ) ; } private underScoreToCamelCase ( record ) { const newObj = { } ; Object . keys ( record ) . forEach ( ( key ) => { const origKey = key ; while ( key . indexOf ( '_' ) > - 1 ) { const _index = key . indexOf ( '_' ) ; const nextChar = key . charAt ( _index + 1 ) ; key = key . replace ( `_${ nextChar }` , nextChar . toUpperCase ( ) ) ; } newObj [ key ] = record [ origKey ] ; } ) ; return newObj ; } query ( params , type ) { const query = 'SELECT ' + params . query + ' FROM ' + this . tableName + ' WHERE ' + params . where ; return this . runQuery ( query , params . variables , type ) ; } insert ( params , type ) { const query = 'INSERT INTO ' + this . tableName + ' (' + params . query + ') VALUES (' + params . where + ') RETURNING *;' ; return this . runQuery ( query , params . variables , type ) ; } update ( params , type ) { const query = 'UPDATE ' + this . tableName + ' SET ' + params . query + ' WHERE ' + params . where + ' RETURNING *;' ; return this . runQuery ( query , params . variables , type ) ; } updateMany ( params , type ) { const query = 'UPDATE ' + this . tableName + ' AS ' + params . tableAlias + ' SET ' + params . query + ' FROM ' + params . tempTable + ' WHERE ' + params . where + ' RETURNING *;' ; return this . runQuery ( query , params . variables , type ) ; } delete ( params ) { return of ( [ ] ) ; } }