Last active
August 24, 2021 15:00
-
-
Save samstr/fc7fd916023f5ea39d531c80aff5e9e6 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* utils/aws/rds.ts */ | |
import { Client } from 'pg'; | |
import type { QueryResult } from 'pg'; | |
interface AnyObject { | |
[key: string]: any; | |
} | |
export enum RdsSource { | |
Reader, | |
Writer, | |
} | |
export interface RdsConfig { | |
database: string; | |
debugQuery?: boolean; | |
password: string; | |
port: number; | |
readerHost: string; | |
user: string; | |
writerHost: string; | |
} | |
export type QueryValues = (string | number | boolean)[]; | |
class Rds { | |
client?: Client; | |
database: string; | |
debugQuery?: boolean; | |
password: string; | |
port: number; | |
readerHost: string; | |
source?: RdsSource; | |
user: string; | |
writerHost: string; | |
constructor(config: RdsConfig) { | |
const { | |
database, | |
debugQuery = false, | |
password, | |
port, | |
readerHost, | |
user, | |
writerHost, | |
} = config; | |
if (database) { | |
this.database = database; | |
} | |
if (debugQuery) { | |
this.debugQuery = debugQuery; | |
} | |
if (password) { | |
this.password = password; | |
} | |
if (port) { | |
this.port = port; | |
} | |
if (readerHost) { | |
this.readerHost = readerHost; | |
} | |
if (user) { | |
this.user = user; | |
} | |
if (writerHost) { | |
this.writerHost = writerHost; | |
} | |
} | |
connect(source: RdsSource): void { | |
if (!this.client) { | |
this.source = source; | |
console.log(`Connecting to ${this.source}`); | |
this.client = new Client({ | |
user: this.user, | |
host: | |
this.source === RdsSource.Writer ? this.writerHost : this.readerHost, | |
database: this.database, | |
password: this.password, | |
port: this.port, | |
}); | |
this.client.connect(); | |
} else { | |
console.log(`Client already exists (connected to ${this.source}`); | |
} | |
} | |
disconnect(): void { | |
if (this.client) { | |
console.log(`Disconnecting from ${this.source}: Done`); | |
this.client.end(); | |
this.client = null; | |
} else { | |
console.log(`No need to disconnect (no client connected)`); | |
} | |
} | |
async query(query: string, values: QueryValues = []): Promise<QueryResult> { | |
if (this.debugQuery) { | |
console.log( | |
`Query on (${this.source}):`, | |
query.replace('\n', '').replace(/\s+/g, ' '), | |
values || [] | |
); | |
} | |
const result = await this.client.query(query, values); | |
return result; | |
} | |
async transaction(fn: () => AnyObject): Promise<AnyObject> { | |
try { | |
if (this.debugQuery) { | |
console.log('Transaction: BEGIN'); | |
} | |
await this.client.query('BEGIN'); | |
const data = await fn(); | |
if (this.debugQuery) { | |
console.log('Transaction: COMMIT'); | |
} | |
await this.client.query('COMMIT'); | |
return data; | |
} catch (err) { | |
console.error('Error during transaction', err); | |
if (this.debugQuery) { | |
console.log('Transaction: ROLLBACK'); | |
} | |
await this.client.query('ROLLBACK'); | |
throw err; | |
} | |
} | |
} | |
export default Rds; | |
// Usage | |
import Rds, { RdsSource } from 'utils/aws/rds'; | |
const db = new Rds({ | |
writerHost: PG_WRITER_HOST, // Vercel ENV Vars | |
readerHost: PG_READER_HOST, | |
port: PG_PORT, | |
user: PG_USER, | |
password: PG_PASSWORD, | |
database: PG_DATABASE, | |
debugQuery: PG_DEBUG_QUERY, | |
}); | |
db.connect(RdsSource.Reader); | |
const result = await db.query('SELECT * FROM table WHERE id = $1', [123]); | |
db.disconnect(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment