Skip to content

Commit 5815e19

Browse files
committed
Commit comitted
0 parents  commit 5815e19

File tree

15 files changed

+2411
-0
lines changed

15 files changed

+2411
-0
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
node_modules/*
2+
.idea/*

Entry.ts

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import {App} from "./app/App";
2+
3+
const port: number = 3000;
4+
new App().start().then((server) => {
5+
server.listen(port);
6+
server.on("error", (error: any) => {
7+
if (error.syscall !== "listen") {
8+
throw error;
9+
}
10+
switch (error.code) {
11+
case "EACCES":
12+
console.error("Port requires elevated privileges");
13+
process.exit(1);
14+
break;
15+
case "EADDRINUSE":
16+
console.error("Port is already in use");
17+
process.exit(1);
18+
break;
19+
default:
20+
throw error;
21+
}
22+
});
23+
server.on("listening", () => {
24+
console.log("Server is running in process " + process.pid + " listening on PORT " + port + "\n");
25+
});
26+
});

README.md

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
#Starter template Rest
2+
#### TypeScript + TypeOrm + ExpressJS + Validator Middleware
3+
## Structure
4+
```
5+
/app
6+
/controllers (Controllers of the app)
7+
/core (Core of starter template)
8+
/middlewares (Middlewares for the routes of the app)
9+
/routes (Routes for Controllers of the app)
10+
/models (Models configuration for use)
11+
/repository (Custom queries)
12+
/App.ts (Server configuration)
13+
/Router.ts (Config file for Routing)
14+
15+
config.ts (Config file for the app)
16+
tsconfig.json (File configuration typescript)
17+
tslint.json (File configuration rules typescript)
18+
Entry.ts (Main file to start the app)
19+
```
20+
21+
## Usage
22+
In Development mode, the express app is started with nodemon for automatic refresh when changes are made.
23+
````
24+
npm run dev
25+
````
26+
## Todo
27+
- [X] TypeORM
28+
- [X] Validator Middleware
29+
- [ ] Configuration file
30+
- [ ] Swagger Docs
31+
- [ ] Release bundle
32+
- [ ] JWT Middleware
33+
- [ ] Dockerfile
34+
35+
## License
36+
Usage is provided under the MIT License. See LICENSE for the full details. \
37+
Copyright © 2020, Taoufik Tribki

app/App.ts

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
/**
2+
* @Ta0uf19
3+
* Server application class
4+
*/
5+
6+
import * as express from "express";
7+
import * as http from "http"
8+
import * as logger from "morgan"
9+
import {createConnection, Connection} from "typeorm";
10+
import {Router} from "./Router";
11+
12+
export class App {
13+
14+
private readonly app: express.Application;
15+
private readonly server: http.Server;
16+
17+
constructor() {
18+
this.app = express();
19+
this.server = http.createServer(this.app);
20+
}
21+
22+
/**
23+
* Start server
24+
*/
25+
public async start(): Promise<http.Server> {
26+
this.configureExpress();
27+
this.configureRouter();
28+
29+
// start connection
30+
await App.getConnection();
31+
return this.server;
32+
}
33+
34+
/**
35+
* Get application instance
36+
*/
37+
get App(): express.Application {
38+
return this.app;
39+
}
40+
41+
/**
42+
* Configure connection to database
43+
*/
44+
private static async getConnection(): Promise<Connection> {
45+
const connection: Connection = await createConnection({
46+
type: "mongodb",
47+
host: "localhost",
48+
port: 27017,
49+
database: "express",
50+
entities: [
51+
"./app/models/*.ts"
52+
],
53+
});
54+
return connection;
55+
}
56+
57+
/**
58+
* Config express middlewares
59+
*/
60+
private configureExpress(): void {
61+
this.app.use(logger('dev'));
62+
this.app.use(express.json());
63+
this.app.use(express.urlencoded({ extended: false }));
64+
this.app.use((req, res, next): void => {
65+
res.header("Access-Control-Allow-Origin", "*");
66+
res.header("Access-Control-Allow-Headers", "X-Requested-With, Content-Type, Authorization");
67+
res.header("Access-Control-Allow-Methods", "GET,PUT,PATCH,POST,DELETE,OPTIONS");
68+
next();
69+
});
70+
//this.app.use(cookieParser());
71+
}
72+
73+
private configureRouter(): void {
74+
for(let route of Router) {
75+
this.app.use(route.path, route.middleware, route.router)
76+
}
77+
78+
this.app.use((req: express.Request, res: express.Response, next: express.NextFunction): void => {
79+
res.status(404);
80+
res.json({
81+
error: "Not found",
82+
});
83+
next();
84+
});
85+
86+
}
87+
}

app/Router.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import * as express from "express";
2+
import { GarantieRouter } from "./routes/GarantieRouter";
3+
4+
interface IRouter {
5+
path: string;
6+
middleware: any[];
7+
router: express.Router;
8+
}
9+
10+
export const Router: IRouter[] = [
11+
{
12+
path: "/api/garantie",
13+
middleware: [],
14+
router: (new GarantieRouter()).router,
15+
}
16+
];

app/controllers/GarantieController.ts

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
import {Controller} from "../core/Controller";
2+
import { Request, Response } from "express";
3+
import {Repository, getConnection, ObjectID} from "typeorm";
4+
import {Garantie} from "../models/Garantie";
5+
import {validate, ValidationError} from 'class-validator';
6+
import {plainToClass} from "class-transformer";
7+
8+
export class GarantieController extends Controller {
9+
10+
private garantieRepository : Repository<Garantie>;
11+
12+
constructor(req: Request, res: Response) {
13+
super(req, res);
14+
this.garantieRepository = getConnection().getRepository(Garantie);
15+
}
16+
17+
public async all(): Promise<Response> {
18+
const list = await this.garantieRepository.find();
19+
return this.res.send(list);
20+
}
21+
22+
public async find(): Promise<Response> {
23+
const { id } = this.req.params as unknown as { id: string };
24+
25+
const garantie = id.match(/^[0-9a-fA-F]{24}$/) && await this.garantieRepository.findOneOrFail(id);
26+
if (garantie) {
27+
return this.res.status(200).send(garantie);
28+
} else {
29+
return this.res.status(404).send({ text: "not found" });
30+
}
31+
}
32+
33+
/**
34+
* Ajouter
35+
*/
36+
public async add(): Promise<Response> {
37+
const garantie: Garantie = plainToClass(Garantie, this.req.body);
38+
const result = await this.garantieRepository.save(garantie);
39+
return this.res.status(200).send(result);
40+
}
41+
/**
42+
* Update
43+
*/
44+
public async update(): Promise<Response> {
45+
const { id } = this.req.params as unknown as { id: string };
46+
const garantie: Garantie = id.match(/^[0-9a-fA-F]{24}$/) && await this.garantieRepository.findOneOrFail(id);
47+
48+
if (garantie) {
49+
this.garantieRepository.merge(garantie, this.req.body);
50+
const results = await this.garantieRepository.save(garantie);
51+
52+
return this.res.status(200).send(results);
53+
} else {
54+
return this.res.status(404).send({ message: "not found" });
55+
}
56+
}
57+
58+
/**
59+
* Supprimer
60+
*/
61+
public async delete(): Promise<Response> {
62+
const { id } = this.req.params as unknown as { id: string };
63+
const garantie: Garantie = id.match(/^[0-9a-fA-F]{24}$/) && await this.garantieRepository.findOneOrFail(id);
64+
if (garantie) {
65+
await this.garantieRepository.delete(garantie);
66+
return this.res.status(200).send({message: "Garantie a bien été supprimé"});
67+
} else {
68+
return this.res.status(404).send({ message: "not found" });
69+
}
70+
}
71+
72+
73+
}

app/core/Controller.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import * as express from "express";
2+
3+
export abstract class Controller {
4+
5+
public req: express.Request;
6+
public res: express.Response;
7+
8+
constructor(req: express.Request, res: express.Response) {
9+
this.req = req;
10+
this.res = res;
11+
}
12+
}

app/core/Router.ts

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
/**
2+
* @Ta0uf19
3+
*/
4+
import * as express from "express";
5+
6+
export abstract class Router {
7+
8+
public router: express.Router;
9+
private controller: any;
10+
11+
constructor(controller: any) {
12+
this.controller = controller;
13+
this.router = express.Router();
14+
}
15+
16+
/**
17+
* Passing method of a controller to call
18+
* @param action
19+
*/
20+
protected handler(action: () => void): any {
21+
return (req: Request, res: Response) => action.call(new this.controller(req, res));
22+
}
23+
24+
}

app/middleware/Validator.ts

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
/**
2+
* Validation error middlware
3+
* @Ta0uf19
4+
*/
5+
import * as express from 'express';
6+
import {Validator} from 'class-validator';
7+
import {plainToClass} from "class-transformer";
8+
9+
10+
export function validator<T>(type: any): express.RequestHandler {
11+
12+
return (req: express.Request, res: express.Response, next: express.NextFunction) => {
13+
const params = req.method === "GET" ? req.params : req.body;
14+
let input = plainToClass(type, params);
15+
let validator = new Validator();
16+
17+
let errors = validator.validateSync(input);
18+
if (errors.length > 0) {
19+
res.status(400).json({errors: errors}).end();
20+
} else {
21+
next();
22+
}
23+
24+
};
25+
}

app/models/Garantie.ts

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import {Entity, ObjectID, ObjectIdColumn, Column, BeforeInsert, BeforeUpdate} from "typeorm";
2+
import {IsNumber} from 'class-validator';
3+
4+
@Entity({ name: "garantie" })
5+
export class Garantie {
6+
7+
@ObjectIdColumn()
8+
id: ObjectID;
9+
10+
@Column()
11+
nom: string;
12+
13+
@Column()
14+
@IsNumber({}, {
15+
message: "Le montant doit être un nombre"
16+
})
17+
montant: number;
18+
19+
@Column()
20+
description: string;
21+
22+
23+
}

app/routes/GarantieRouter.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import {Router} from "../core/Router";
2+
import {GarantieController} from "../controllers/GarantieController";
3+
import {validator} from "../middleware/Validator";
4+
import {Garantie} from "../models/Garantie";
5+
6+
export class GarantieRouter extends Router {
7+
constructor() {
8+
super(GarantieController);
9+
this.router
10+
.get("/", this.handler(GarantieController.prototype.all))
11+
.post('/', validator(Garantie), this.handler(GarantieController.prototype.add))
12+
.get('/:id', this.handler(GarantieController.prototype.find))
13+
.put('/:id', validator(Garantie), this.handler(GarantieController.prototype.update))
14+
.delete('/:id', this.handler(GarantieController.prototype.delete))
15+
}
16+
}

0 commit comments

Comments
 (0)