0.1.0•Updated 7 months ago
import { Client, ConnectionString } from "https://deno.land/x/postgres@v0.19.3/mod.ts";
import { Sluggify } from "../../utils/slug.ts";
export class PostgresClient {
client: Client
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.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);
await this.EnsureDatabaseExists('postgres');
this.SETUP_FINISHED = true;
await this.client.end();
this.client = new Client(`${this.connection_string}/${this.database}`);
await this.client.connect();
return this;
}
private async EnsureDatabaseExists(name: string) {
if(this.SETUP_FINISHED) return;
const { rowCount = 0 } = await this.query(`SELECT datname FROM pg_catalog.pg_database where datname=$1`, [name]);
if(rowCount === 0) {
await this.query(`CREATE DATABASE "${name}"`);
}
}
async query<T = any>(query: string, args?: any[]) {
return this.client.queryObject<T>(query, args);
}
get end() { return this.client.end.bind(this.client); }
}
interface CreateTableOptions {
onCreate?: () => Promise<void>
}