-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathpostgresql.ts
More file actions
114 lines (88 loc) · 3.71 KB
/
Copy pathpostgresql.ts
File metadata and controls
114 lines (88 loc) · 3.71 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
import { Pool } from 'pg'
import { database } from '..'
export interface DatabaseConfig {
user: string
host: string
database: string
password: string
port: number
customIdentifierKey?: string
}
export type QueryValue = string | number | boolean | Date | Buffer | undefined | null | { toSqlString: () => string }
export interface OperationOptions {
showQuery?: boolean
}
export default class PostgreSQL {
protected pool: Pool
constructor(config: DatabaseConfig) {
this.pool = new Pool(config)
this.pool.on('error', (err) => {
console.error('Error:', err)
})
}
// eslint-disable-next-line class-methods-use-this
async start(): Promise<void> {
await database.query('SELECT 1', [])
console.log('PostgreSQL connection established successfully.')
return undefined
}
async stop(): Promise<void> {
await this.pool.end()
}
async query<ResultObject = any>(query: string, values?: QueryValue[], options?: OperationOptions) {
const queryPromise = async (): Promise<ResultObject[]> => {
return new Promise((resolve, reject) => {
try {
this.pool.query(query, values !== undefined ? values : [], (error, response) => {
if (error) {
console.log('Failed query: ', query)
console.log('With these values: ', values)
console.log('error 1', error)
reject(error)
return
}
if (options && options.showQuery) {
console.log('Executed query: ', query)
}
const results = response.rows
try {
const responseData: ResultObject[] = JSON.parse(JSON.stringify(results))
if (!Array.isArray(responseData)) {
const parsedResponseData: ResultObject[] = [JSON.parse(JSON.stringify(results))]
resolve(parsedResponseData)
}
resolve(responseData)
} catch (error) {
console.log('query response: ', results)
console.log('catch error: ', error)
reject(error)
console.log('error 2', error)
}
})
} catch (error) {
console.log('catch error: ', error)
console.log('error 3', error)
reject(error)
}
})
}
try {
const rows = await queryPromise()
return rows
} catch (error: any) {
throw new Error(error)
}
}
public async edit<T>(tableName: string, object: Omit<Partial<T>, 'id'>, objectId: number) {
const keys = Object.keys(object).map((key, index) => `${checkAndTransformKey(key)} = $${index + 1}`)
const values: any[] = Object.values(object)
const query = `UPDATE ${checkAndTransformKey(tableName)} ${tableName} SET ${keys} WHERE id = $${keys.length + 1} RETURNING *`
const rows = await this.query<T>(query, [...values, objectId])
return rows[0]
}
}
// Add backtick to sql reserved keywords
export const checkAndTransformKey = (key: string): string => {
const protectedKeywords = ['key', 'table', 'group', 'from', 'desc', 'condition', 'before', 'grant', 'user', 'is']
return protectedKeywords.includes(key) ? `"${key}"` : key
}