0.1.4•Updated 6 months ago
import { Pool, Client, type ConnectionString } from "https://deno.land/x/postgres@v0.19.3/mod.ts";
import { Sluggify } from "@infinity-beyond/utils/slug.ts";
export class PostgresClient {
private _setup_client: Client
pool!: Pool
readonly connection_string: string
readonly database: string
private SETUP_FINISHED = false;
constructor(connection_string: ConnectionString) {
const [ _, extracted_connection_string, database ] = connection_string.match(/((?:postgresql|postgres):\/\/(?:[^:@\s]*(?::[^@\s]*)?@)?(?:[^\/\?\s]+))\b(?:\/(.+))?/) ?? [];
if(!extracted_connection_string) throw new Error('PostgresClient_Invalid connection_string provided')
this.connection_string = extracted_connection_string;
this.database = Sluggify(database);
this._setup_client = new Client(`${this.connection_string}/postgres`);
}
async CreateTable<T = Record<string, string>>(name: string, fields: { [P in keyof Required<T>]: string }, { onCreate }: CreateTableOptions = {}) {
const fields_array: string[] = Object.entries(fields).map(([ name, type ]) => `${name} ${type}`);
const query = `CREATE TABLE IF NOT EXISTS "${name}" (${fields_array.join(',')})`;
const response = await this.query(query);
if(response.warnings.length === 0) {
onCreate?.();
}
return response;
}
async Setup() {
if(this.SETUP_FINISHED) return this;
await this.EnsureDatabaseExists(this.database);
this.SETUP_FINISHED = true;
await this._setup_client.end();
this.pool = new Pool(`${this.connection_string}/${this.database}`, 20, true);
return this;
}
private async EnsureDatabaseExists(name: string) {
if(this.SETUP_FINISHED) return;
const { rowCount = 0 } = await this._setup_client.queryObject(`SELECT datname FROM pg_catalog.pg_database where datname=$1`, [name]);
if(rowCount === 0) {
await this._setup_client.queryObject(`CREATE DATABASE "${name}"`);
}
}
async query<T = any>(query: string, args?: any[]) {
const client = await this.pool.connect();
try {
if(Deno.env.get('LOGGING_QUERIES')) console.log(query);
return await client.queryObject<T>(query, args);
} finally {
client.release()
}
}
get end() { return this.pool.end.bind(this.pool); }
}
interface CreateTableOptions {
onCreate?: () => Promise<void>
}