Skip to content

Commit 4990ff8

Browse files
committed
feat(database): add database initialization and seeding functionality
- Implemented DatabaseService to initialize tables and seed data - Added seedTables method to load and execute SQL seed data from a file - Enhanced ConnectionPool to handle database creation if it doesn't exist - Improved error handling in the connection process using custom decorators
1 parent 8f966b9 commit 4990ff8

2 files changed

Lines changed: 96 additions & 0 deletions

File tree

src/database/ConnectionPool.ts

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
import { Pool, PoolClient } from 'pg';
2+
import Config from '../config';
3+
import { Catch } from '../decorators/ErrorHandlingDecorator';
4+
export class ConnectionPool {
5+
private _pool: Pool;
6+
constructor() {
7+
const connectionString = this.getConnectionString();
8+
this._pool = new Pool({
9+
connectionString,
10+
});
11+
}
12+
@Catch({
13+
message: 'Failed to connect to the database. Please check your credentials or network connection.',
14+
statusCode: 500,
15+
category: 'ConnectionPool',
16+
})
17+
async connect(): Promise<void> {
18+
try {
19+
await this._pool.connect();
20+
} catch (error: any) {
21+
console.log('error:', error.code);
22+
23+
if (error.code === '3D000') {
24+
console.log(`Database does not exist. Creating database ${Config.database.databaseName}...`);
25+
await this.createDatabase();
26+
await this._pool.end(); // End the current pool connection
27+
const newConnectionString = this.getConnectionString();
28+
this._pool = new Pool({
29+
connectionString: newConnectionString,
30+
});
31+
await this._pool.connect();
32+
}
33+
}
34+
}
35+
@Catch({
36+
message: 'Failed to create the database. Please check the connection or permissions.',
37+
statusCode: 500,
38+
category: 'ConnectionPool',
39+
})
40+
private async createDatabase(): Promise<void> {
41+
const { user, host, password, port, databaseName } = Config.database;
42+
const client = new Pool({
43+
user,
44+
host,
45+
password,
46+
port,
47+
database: 'postgres',
48+
});
49+
await client.query(`CREATE DATABASE ${databaseName}`);
50+
}
51+
private getConnectionString(): string {
52+
const { user, host, databaseName, password, port, url } = Config.database;
53+
return url || `postgresql://${user}:${password}@${host}:${port}/${databaseName}`;
54+
}
55+
async getClient(): Promise<PoolClient> {
56+
return this._pool.connect();
57+
}
58+
59+
async close(): Promise<void> {
60+
await this._pool.end();
61+
}
62+
}

src/database/index.ts

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import { ConnectionPool } from './ConnectionPool';
2+
import * as fs from 'fs/promises';
3+
import * as path from 'path';
4+
export class DatabaseService {
5+
private _connectionPool: ConnectionPool;
6+
7+
constructor() {
8+
this._connectionPool = new ConnectionPool();
9+
}
10+
11+
async initialize() {
12+
await this._connectionPool.connect();
13+
await this.setupInitialTables();
14+
await this.seedTables();
15+
}
16+
17+
private async setupInitialTables() {
18+
const client = await this._connectionPool.getClient();
19+
const sqlFilePath = path.join(__dirname, './tables/Tables.sql');
20+
const sql = await fs.readFile(sqlFilePath, 'utf-8');
21+
await client.query(sql);
22+
console.log('Initial tables have been set up successfully.');
23+
}
24+
private async seedTables() {
25+
const client = await this._connectionPool.getClient();
26+
// Define the path where seed files are stored
27+
const sqlFilePath = path.join(__dirname, './seed/SeedDataTables.sql');
28+
29+
// Get all seed files
30+
const sql = await fs.readFile(sqlFilePath, 'utf-8');
31+
await client.query(sql);
32+
console.log('All tables have been seeded successfully.');
33+
}
34+
}

0 commit comments

Comments
 (0)