Skip to content

Commit 6e08fa7

Browse files
committed
implemented db init/create
1 parent d2ea022 commit 6e08fa7

16 files changed

+737
-49
lines changed

Projects/BooksLibrary/.env.sample

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,9 @@
11
BASE_URL=http://localhost:7272/api/v1
22
PORT=7272
33
NODE_ENV=development
4-
API_VERSION=0.0.1
4+
API_VERSION=0.0.1
5+
6+
DB_USER_NAME = someusername
7+
DB_USER_PASSWORD = somepass
8+
DB_NAME = somename
9+
DB_HOST = host

Projects/BooksLibrary/package-lock.json

Lines changed: 534 additions & 43 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Projects/BooksLibrary/package.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,10 @@
3030
"express": "^4.17.3",
3131
"express-fileupload": "^1.3.1",
3232
"jsonwebtoken": "^8.5.1",
33+
"pg": "^8.7.3",
3334
"reflect-metadata": "^0.1.13",
35+
"sequelize": "^6.17.0",
36+
"sequelize-typescript": "^2.1.3",
3437
"tsyringe": "^4.6.0"
3538
}
3639
}

Projects/BooksLibrary/src/app.config.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
"Database": {
88
"Type": "SQL",
99
"ORM": "Sequelize",
10-
"Flavour": "MySQL"
10+
"Flavour": "PostGreSQL"
1111
},
1212
"FileStorage": {
1313
"Provider": "AWS-S3"

Projects/BooksLibrary/src/config/configuration.manager.ts

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,33 @@
1-
import { AuthenticationType, AuthorizationType, Configurations } from './configuration.types';
2-
import * as AppConfig from '../app.config.json';
1+
import {
2+
AuthenticationType,
3+
AuthorizationType,
4+
Configurations,
5+
DatabaseFlavour,
6+
DatabaseORM,
7+
DatabaseType,
8+
} from './configuration.types';
9+
import * as configuration from '../app.config.json';
310

411
export class ConfigurationManager {
512
static _config: Configurations = null;
613

14+
public static DatabaseFlavour = (): DatabaseFlavour => {
15+
return ConfigurationManager._config.Database.Flavour;
16+
};
17+
718
public static loadConfigurations = (): void => {
819
ConfigurationManager._config = {
920
BaseUrl: process.env.BASE_URL,
1021
SystemIdentifier: '',
1122
MaxUploadFileSize: 0,
1223
Auth: {
13-
Authentication: AppConfig.Auth.Authentication as AuthenticationType,
14-
Authorization: AppConfig.Auth.Authorization as AuthorizationType,
24+
Authentication: configuration.Auth.Authentication as AuthenticationType,
25+
Authorization: configuration.Auth.Authorization as AuthorizationType,
26+
},
27+
Database: {
28+
Type: configuration.Database.Type as DatabaseType,
29+
ORM: configuration.Database.ORM as DatabaseORM,
30+
Flavour: configuration.Database.Flavour as DatabaseFlavour,
1531
},
1632
};
1733
};

Projects/BooksLibrary/src/config/configuration.types.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,22 @@
11
export type AuthorizationType = 'Custom'; //TBD: Other options need to be supported
22
export type AuthenticationType = 'Custom'; //TBD: Other options need to be supported
3+
4+
export type DatabaseFlavour = 'MySQL' | 'PostGreSQL' | 'MongoDB';
5+
export type DatabaseType = 'SQL' | 'NoSQL';
6+
export type DatabaseORM = 'Sequelize' | 'Knex' | 'Mongoose';
7+
8+
export interface DatabaseConfig {
9+
Type: DatabaseType;
10+
ORM: DatabaseORM;
11+
Flavour: DatabaseFlavour;
12+
}
13+
314
export interface Configurations {
415
SystemIdentifier: string;
516
BaseUrl: string;
617
MaxUploadFileSize: number;
718
Auth: AuthConfig;
19+
Database: DatabaseConfig;
820
}
921
export interface AuthConfig {
1022
Authentication: AuthenticationType;
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import { Logger } from 'common/logger';
2+
import * as dotenv from 'dotenv';
3+
dotenv.config();
4+
5+
if (process.env.NODE_ENV === 'test') {
6+
Logger.instance().log('================================================');
7+
Logger.instance().log('Environment : ' + process.env.NODE_ENV);
8+
Logger.instance().log('Database name : ' + process.env.DB_NAME);
9+
Logger.instance().log('Database user : ' + process.env.DB_USER_NAME);
10+
Logger.instance().log('Database host : ' + process.env.DB_HOST);
11+
Logger.instance().log('================================================');
12+
}
13+
14+
export class DbConfig {
15+
public static config = {
16+
username: process.env.DB_USER_NAME,
17+
password: process.env.DB_USER_PASSWORD,
18+
database: process.env.DB_NAME,
19+
host: process.env.DB_HOST,
20+
dialect: 'mysql',
21+
pool: {
22+
max: 20,
23+
min: 0,
24+
acquire: 30000,
25+
idle: 10000,
26+
},
27+
};
28+
}
Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
import { Logger } from 'common/logger';
2+
import { IDatabaseConnector } from 'database/database.connector.interface';
3+
import { DbConfig } from './database.config';
4+
import { Dialect } from 'sequelize';
5+
import { Sequelize } from 'sequelize-typescript';
6+
import { ConfigurationManager } from 'config/configuration.manager';
7+
import { PostgresqlClient } from './dilect.clients/postgresql.client';
8+
9+
export class DatabaseConnector_Sequelize implements IDatabaseConnector {
10+
private _sequelize: Sequelize = null;
11+
12+
private getDialect = (): Dialect => {
13+
let dialect: Dialect = 'postgres';
14+
const flavour = ConfigurationManager.DatabaseFlavour();
15+
16+
if (flavour === 'MySQL') {
17+
dialect = 'mysql';
18+
}
19+
if (flavour === 'PostGreSQL') {
20+
dialect = 'postgres';
21+
}
22+
23+
return dialect;
24+
};
25+
26+
connect = async (): Promise<boolean> => {
27+
try {
28+
const config = DbConfig.config;
29+
const dialect: Dialect = this.getDialect();
30+
const modelsPath = [__dirname + '/models'];
31+
const options = {
32+
host: config.host,
33+
dialect: dialect,
34+
models: modelsPath,
35+
pool: {
36+
max: config.pool.max,
37+
min: config.pool.min,
38+
acquire: config.pool.acquire,
39+
idle: config.pool.idle,
40+
},
41+
logging: false, //TODO: Please provide a function here to handle logging...
42+
};
43+
44+
this._sequelize = new Sequelize(config.database, config.username, config.password, options);
45+
46+
Logger.instance().log(`Connecting to database '${config.database}' ...`);
47+
Logger.instance().log(`Database flavour: ${config.dialect}`);
48+
Logger.instance().log(`Database host: ${config.host}`);
49+
50+
await this.createDatabase();
51+
// test the connection by trying to authenticate to database server
52+
// with the config that we have defined above
53+
await this._sequelize.authenticate();
54+
// alter: true is not adviced to be used on prod env
55+
await this._sequelize.sync({ alter: true });
56+
57+
return true;
58+
} catch (err) {
59+
Logger.instance().log(err.message);
60+
return false;
61+
}
62+
};
63+
64+
sync(): Promise<boolean> {
65+
throw new Error('Method not implemented.');
66+
}
67+
68+
private getClient = () => {
69+
const flavour = ConfigurationManager.DatabaseFlavour();
70+
71+
if (flavour === 'PostGreSQL') {
72+
return PostgresqlClient;
73+
}
74+
75+
throw new Error('Only PostGreSQL is supported for now!');
76+
};
77+
78+
createDatabase = async (): Promise<boolean> => {
79+
try {
80+
const client = this.getClient();
81+
await client.createDb();
82+
return true;
83+
} catch (err) {
84+
Logger.instance().log(err.message);
85+
}
86+
};
87+
88+
dropDatabase(): Promise<boolean> {
89+
throw new Error('Method not implemented.');
90+
}
91+
92+
executeQuery(query: string): Promise<boolean> {
93+
throw new Error('Method not implemented.');
94+
}
95+
96+
migrate(): Promise<boolean> {
97+
throw new Error('Method not implemented.');
98+
}
99+
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import { Logger } from 'common/logger';
2+
import { DbConfig } from '../database.config';
3+
import { Client } from 'pg';
4+
5+
export class PostgresqlClient {
6+
static async executeQuery(query: string) {
7+
try {
8+
const config = DbConfig.config;
9+
const client = new Client({
10+
user: config.username,
11+
host: config.host,
12+
password: config.password,
13+
port: 5432,
14+
});
15+
16+
await client.connect();
17+
await client.query(query);
18+
await client.end();
19+
} catch (err) {
20+
Logger.instance().log(err.message);
21+
}
22+
}
23+
24+
public static createDb = async () => {
25+
try {
26+
const config = DbConfig.config;
27+
const query = `CREATE DATABASE ${config.database}`;
28+
await PostgresqlClient.executeQuery(query);
29+
} catch (error) {
30+
Logger.instance().log(error.message);
31+
}
32+
};
33+
}

Projects/BooksLibrary/src/database/sql/sequelize/models/author.model.ts

Whitespace-only changes.

0 commit comments

Comments
 (0)