Skip to content

Commit

Permalink
Merge pull request #1 from damascus-mx/Tests/Ts
Browse files Browse the repository at this point in the history
PR: Use Typescript
  • Loading branch information
maestre3d authored Aug 16, 2019
2 parents 8aae349 + bc0515a commit 0bea1cd
Show file tree
Hide file tree
Showing 16 changed files with 1,125 additions and 1,487 deletions.
1 change: 0 additions & 1 deletion .babelrc

This file was deleted.

4 changes: 2 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,8 @@ typings/
# next.js build output
.next

# node modules
node_modules/
# Vscode folder
.vscode/

# generated babel dist
dist/
2,224 changes: 776 additions & 1,448 deletions package-lock.json

Large diffs are not rendered by default.

39 changes: 23 additions & 16 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,12 @@
"description": "Andromeda's platform API",
"main": "server.js",
"scripts": {
"start": "node ./bin/server",
"start": "node ./dist/bin/server.js",
"test": "echo \"Error: no test specified\" && exit 1",
"server": "babel-node ./src/bin/server",
"server:prod": "node ./dist/bin/server",
"dev": "SET NODE_ENV=development & npm-run-all server",
"clean": "rimraf dist",
"build": "babel ./src --out-dir dist",
"prod": "SET NODE_ENV=production & npm-run-all clean build server:prod",
"watch": "nodemon"
"dev": "ts-node-dev --respawn --transpileOnly ./src/bin/server.ts",
"prod": "tsc && node ./dist/bin/server.js",
"watch": "nodemon",
"tsc": "tsc"
},
"repository": {
"type": "git",
Expand All @@ -25,16 +22,26 @@
},
"homepage": "https://github.com/damascus-mx/Nebula#readme",
"dependencies": {
"dot-env": "0.0.1",
"aws-sdk": "^2.510.0",
"bcryptjs": "^2.4.3",
"body-parser": "^1.19.0",
"compression": "^1.7.4",
"cors": "^2.8.5",
"dotenv": "^8.0.0",
"express": "^4.17.1",
"npm-run-all": "^4.1.5",
"rimraf": "^2.7.1"
"pg": "^7.12.1",
"uuid": "^3.3.2"
},
"devDependencies": {
"@babel/cli": "^7.5.5",
"@babel/core": "^7.5.5",
"@babel/node": "^7.5.5",
"@babel/preset-env": "^7.5.5",
"nodemon": "^1.19.1"
"@types/compression": "^1.0.0",
"@types/dotenv": "^6.1.1",
"@types/express": "^4.17.0",
"@types/morgan": "^1.7.36",
"@types/pg": "^7.4.14",
"morgan": "^1.9.1",
"nodemon": "^1.19.1",
"rotating-file-stream": "^1.4.3",
"ts-node-dev": "^1.0.0-pre.40",
"typescript": "^3.5.3"
}
}
5 changes: 0 additions & 5 deletions src/bin/app.js

This file was deleted.

50 changes: 50 additions & 0 deletions src/bin/app.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
// Required libs
import express from 'express';
import compression from 'compression';
import * as bodyParser from 'body-parser';
import morgan from 'morgan';
import * as rfs from 'rotating-file-stream';
import * as fs from 'fs';
import * as path from 'path';
// Custom libs

// Const
const app = express();
const API_ROUTE = '/api/v1';

// Routes import
import { UserRoutes } from '../routes/user.routes';

// Gzip compression
app.use(compression());

// Parser to JSON
app.use(bodyParser.urlencoded({extended: false}));
app.use(bodyParser.json());

// Config logger
const logDirectory = path.join(__dirname, 'log');
fs.existsSync(logDirectory) || fs.mkdirSync(logDirectory);
const accessLogStream = rfs.default(
'access.log', {
interval: '5d',
path: logDirectory
}
);
app.use(morgan("combined", { stream: accessLogStream }));

// CORS
// TODO - Change public policy to AWS Cloudfront/VPC
app.use((req, res, next) => {
res.header('Access-Control-Allow-Origin', '*');
res.header('Access-Control-Allow-Headers', 'Authorization, X-API-KEY, Origin, X-Requested-Width, Content-Type, Accept, Access-Control-Allow-Request-Method');
res.header('Access-Control-Allow-Methods', 'GET, POST, DELETE, PUT, OPTIONS');
res.header('Allow', 'GET, POST, DELETE, PUT, OPTIONS');

next();
});

// Routes
app.use(API_ROUTE, UserRoutes);

export default app;
15 changes: 0 additions & 15 deletions src/bin/server.js

This file was deleted.

31 changes: 31 additions & 0 deletions src/bin/server.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
// Modules
import cluster from 'cluster';
import { Pool } from 'pg';
import dotenv from 'dotenv';
// Custom Modules
import app from './app';
import { PoolInstance } from '../infrastructure/pool';

// Start dotenv
dotenv.config();

// Start pool
const pool: Pool = PoolInstance.getInstance();

const PORT = process.env.PORT || 5000;

// Start API cluster
if ( cluster.isMaster ) {
const CPU_COUNT = require('os').cpus().length;
for (let i = 0; i < CPU_COUNT; i += 1) {
cluster.fork();
}

cluster.on('exit', function(worker) {
console.log(`Cluster ${worker.id} died.`);
cluster.fork();
});
} else {
// pool.query('SELECT NOW()').then(res => console.log(res.rows[0])).catch(e => console.log(e.message));
app.listen( PORT, () => { console.log(`Server running on port ${PORT}`); });
}
1 change: 1 addition & 0 deletions src/common/config/app.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export const GENERIC_ERROR = 'Something went wrong';
43 changes: 43 additions & 0 deletions src/controllers/user.controller.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import { Repository } from "../core/repository";
import { UserModel } from "../domain/models/user.model";
import { UserRepository } from "../infrastructure/repositories/user.repository";
import { Pool } from "pg";
import { PoolInstance } from "../infrastructure/pool";
import { GENERIC_ERROR } from "../common/config/app.config";

export class UserController {
private _Pool: Pool;

constructor(private _userRepository: Repository<UserModel>) {
this._Pool = PoolInstance.getInstance();
}

public async CreateUser(req: any, res: any) {
const payload = req.body;


res.status(500).send({message: 'Method under construction.'});
}

public async GetUser(req: any, res: any) {
try {
const repo = new UserRepository();
const users = await repo.GetById(req.params.id);
users ? res.status(200).send({users: users}) : res.status(404).send({message: 'User not found'});
} catch (error) {
res.status(400).send({message: GENERIC_ERROR, error: error.message});
}
}

public async GetUsers(req: any, res: any) {
try {
const repo = new UserRepository();
const users = await repo.GetAll();
users && users.length > 0 ? res.status(200).send({users: users}) : res.status(404).send({message: 'User not found'});
} catch (error) {
res.status(400).send({message: GENERIC_ERROR, error: error.message});
}
}


}
7 changes: 7 additions & 0 deletions src/core/repository.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
export interface Repository<T> {
Create(model: T): Promise<void>;
Update(Id: any, payload: any): Promise<void>;
Delete(Id: any): Promise<void>;
GetById(Id: any): Promise<T>;
GetAll(): Promise<T[]>;
}
51 changes: 51 additions & 0 deletions src/domain/models/user.model.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
export interface UserModel {
id: number,
username: string,
password: string,
email: string,
name: string,
surname: string,
image?: string,
cover?: string,
bio?: string,
total_followers: number,
phone?: number,
location?: string,
city?: string,
country: string,
theme_hex?: string,
iat: Date,
role: string,
private: boolean,
verified: boolean,
confirmed: boolean,
active: boolean,
last_modification: Date
}

export function toModel(objectModel: any): UserModel {
return {
id: Number(objectModel.id),
username: objectModel.username,
password: objectModel.password,
email: objectModel.email,
name: objectModel.name,
surname: objectModel.surname,
image: objectModel.image,
cover: objectModel.cover,
bio: objectModel.bio,
total_followers: Number(objectModel.total_followers),
phone: Number(objectModel.phone),
location: objectModel.location,
city: objectModel.city,
country: objectModel.country,
theme_hex: objectModel.theme_hex,
iat: new Date(objectModel.iat),
role: objectModel.role,
private: objectModel.private,
verified: objectModel.verified,
confirmed: objectModel.confirmed,
active: objectModel.active,
last_modification: new Date(objectModel.last_modification)
};
}
20 changes: 20 additions & 0 deletions src/infrastructure/pool.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { Pool } from 'pg';

export abstract class PoolInstance {
private static _Pool: Pool;

constructor(){}

public static getInstance(): Pool {
if ( !PoolInstance._Pool ) {
PoolInstance._Pool = new Pool({
connectionString: process.env.LOCAL_DB
});
}
return PoolInstance._Pool;
}

public query(text: string, params?: any): any {
return PoolInstance._Pool.query(text, params);
};
}
44 changes: 44 additions & 0 deletions src/infrastructure/repositories/user.repository.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import { Repository } from "../../core/repository";
import { UserModel, toModel } from "../../domain/models/user.model";
import * as AWS from 'aws-sdk';
import { Pool } from 'pg';
import { PoolInstance } from "../pool";

export class UserRepository implements Repository<UserModel> {
private _Pool: Pool;

constructor() {
this._Pool = PoolInstance.getInstance();
}

Create(model: UserModel): any {
// const rds = new AWS.RDS();
return this._Pool.query(`CALL CLIENT.CREATE_USER()`)
}

Update(Id: number, payload: any): any {
throw new Error("Method not implemented.");
}

Delete(Id: number): any {
throw new Error("Method not implemented.");
}

GetById(Id: number): Promise<UserModel> {
return this._Pool.query(`SELECT * FROM CLIENT.GET_USER(${Id})`)
.then(user => toModel(user.rows[0]))
.catch(e => { throw e });
}

GetAll(): Promise<UserModel[]> {
return this._Pool.query('SELECT * FROM CLIENT.USER_BY_FOLLOWERS()')
.then(usersDB => {
usersDB.rows.forEach((item, i) => {
usersDB.rows[i] = toModel(item);
});
return usersDB.rows;
})
.catch( e => { throw e });

}
}
14 changes: 14 additions & 0 deletions src/routes/user.routes.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { UserController } from '../controllers/user.controller';
import express from 'express';
import { UserRepository } from '../infrastructure/repositories/user.repository';

const _userRepo = new UserRepository();

const api = express.Router();
const controller = new UserController(_userRepo);

api.post('/user', controller.CreateUser);
api.get('/user', controller.GetUsers);
api.get('/user/:id', controller.GetUser);

export const UserRoutes = api;
Loading

0 comments on commit 0bea1cd

Please sign in to comment.