Database Connection
- added QueryHelper - added DAO - added `default-config.yaml` - added auto-copying of the `default-config.yaml` to a `config.yaml` on startup if no config existspull/1/head
parent
b7d10454ab
commit
0dcd590b80
@ -1,6 +0,0 @@
|
|||||||
database:
|
|
||||||
url: localhost
|
|
||||||
port: 54332
|
|
||||||
user: greenvironment
|
|
||||||
password: greendev
|
|
||||||
database: greenvironment
|
|
@ -0,0 +1,11 @@
|
|||||||
|
# database connection info
|
||||||
|
database:
|
||||||
|
host:
|
||||||
|
port:
|
||||||
|
user:
|
||||||
|
password:
|
||||||
|
database:
|
||||||
|
|
||||||
|
# http server configuration
|
||||||
|
server:
|
||||||
|
port:
|
@ -1,3 +1,16 @@
|
|||||||
|
import * as fsx from "fs-extra";
|
||||||
import App from "./app";
|
import App from "./app";
|
||||||
|
|
||||||
|
const configPath = "config.yaml";
|
||||||
|
const defaultConfig = __dirname + "/default-config.yaml";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* async main function wrapper.
|
||||||
|
*/
|
||||||
|
(async () => {
|
||||||
|
if (!(await fsx.pathExists(configPath))) {
|
||||||
|
await fsx.copy(defaultConfig, configPath);
|
||||||
|
}
|
||||||
const app = new App();
|
const app = new App();
|
||||||
|
})();
|
||||||
|
|
||||||
|
@ -0,0 +1,19 @@
|
|||||||
|
import {Pool} from "pg";
|
||||||
|
import globals from "./globals";
|
||||||
|
import {QueryHelper} from "./QueryHelper";
|
||||||
|
|
||||||
|
const config = globals.config;
|
||||||
|
|
||||||
|
export class DAO {
|
||||||
|
private queryHelper: QueryHelper;
|
||||||
|
constructor() {
|
||||||
|
const dbClient: Pool = new Pool({
|
||||||
|
database: config.database.database,
|
||||||
|
host: config.database.host,
|
||||||
|
password: config.database.password,
|
||||||
|
port: config.database.port,
|
||||||
|
user: config.database.user,
|
||||||
|
});
|
||||||
|
this.queryHelper = new QueryHelper(dbClient);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,116 @@
|
|||||||
|
import {Pool, PoolClient, QueryConfig, QueryResult} from "pg";
|
||||||
|
import globals from "./globals";
|
||||||
|
|
||||||
|
const logger = globals.logger;
|
||||||
|
|
||||||
|
export class SqlTransaction {
|
||||||
|
constructor(private client: PoolClient) {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Begins the transaction.
|
||||||
|
*/
|
||||||
|
public async begin() {
|
||||||
|
return await this.client.query("BEGIN");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Commits the transaction
|
||||||
|
*/
|
||||||
|
public async commit() {
|
||||||
|
return await this.client.query("COMMIT");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Rolls back the transaction
|
||||||
|
*/
|
||||||
|
public async rollback() {
|
||||||
|
return await this.client.query("ROLLBACK");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Executes a query inside the transaction.
|
||||||
|
* @param query
|
||||||
|
*/
|
||||||
|
public async query(query: QueryConfig) {
|
||||||
|
return await this.client.query(query);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Releases the client back to the pool.
|
||||||
|
*/
|
||||||
|
public async release() {
|
||||||
|
this.client.release();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class QueryHelper {
|
||||||
|
private pool: Pool;
|
||||||
|
|
||||||
|
constructor(pgPool: Pool) {
|
||||||
|
this.pool = pgPool;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* executes the sql query with values and returns all results.
|
||||||
|
* @param query
|
||||||
|
*/
|
||||||
|
public async all(query: QueryConfig): Promise<any[]> {
|
||||||
|
const result = await this.query(query);
|
||||||
|
return result.rows;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* executes the sql query with values and returns the first result.
|
||||||
|
* @param query
|
||||||
|
*/
|
||||||
|
public async first(query: QueryConfig): Promise<any> {
|
||||||
|
const result = await this.query(query);
|
||||||
|
if (result.rows && result.rows.length > 0) {
|
||||||
|
return result.rows[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new Transaction to be uses with error handling.
|
||||||
|
*/
|
||||||
|
public async createTransaction() {
|
||||||
|
const client: PoolClient = await this.pool.connect();
|
||||||
|
return new SqlTransaction(client);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Queries the database with error handling.
|
||||||
|
* @param query - the sql and values to execute
|
||||||
|
*/
|
||||||
|
private async query(query: QueryConfig): Promise<QueryResult|{rows: any}> {
|
||||||
|
try {
|
||||||
|
return await this.pool.query(query);
|
||||||
|
} catch (err) {
|
||||||
|
logger.debug(`Error on query "${query}".`);
|
||||||
|
logger.error(`Sql query failed: ${err}`);
|
||||||
|
logger.verbose(err.stack);
|
||||||
|
return {
|
||||||
|
rows: null,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the parameterized value sql for inserting
|
||||||
|
* @param columnCount
|
||||||
|
* @param rowCount
|
||||||
|
* @param [offset]
|
||||||
|
*/
|
||||||
|
export function buildSqlParameters(columnCount: number, rowCount: number, offset?: number): string {
|
||||||
|
let sql = "";
|
||||||
|
for (let i = 0; i < rowCount; i++) {
|
||||||
|
sql += "(";
|
||||||
|
for (let j = 0; j < columnCount; j++) {
|
||||||
|
sql += `$${(i * columnCount) + j + 1 + offset},`;
|
||||||
|
}
|
||||||
|
sql = sql.replace(/,$/, "") + "),";
|
||||||
|
}
|
||||||
|
return sql.replace(/,$/, "");
|
||||||
|
}
|
@ -0,0 +1,25 @@
|
|||||||
|
import * as fsx from "fs-extra";
|
||||||
|
import * as yaml from "js-yaml";
|
||||||
|
import * as winston from "winston";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defines global variables to be used.
|
||||||
|
*/
|
||||||
|
namespace globals {
|
||||||
|
export const config = yaml.safeLoad(fsx.readFileSync("config.yaml", "utf-8"));
|
||||||
|
export const logger = winston.createLogger({
|
||||||
|
transports: [
|
||||||
|
new winston.transports.Console({
|
||||||
|
format: winston.format.combine(
|
||||||
|
winston.format.timestamp(),
|
||||||
|
winston.format.colorize(),
|
||||||
|
winston.format.printf(({ level, message, label, timestamp }) => {
|
||||||
|
return `${timestamp} [${label}] ${level}: ${message}`;
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export default globals;
|
Loading…
Reference in New Issue