Skip to content

Commit 115efc7

Browse files
haimkastnereranshmil
authored andcommitted
Refactoring project to typescript. (#12)
1 parent f874669 commit 115efc7

27 files changed

+2168
-8355
lines changed

.env.example

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
PORT=8080
2-
DB_URL='postgres://user:pass@localhost:5432/bots_db'
2+
DATABASE_URL='postgres://user:pass@localhost:5432/bots_db'

.prettierrc.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"singleQuote": true,
3+
"printWidth": 95,
4+
"tabWidth": 2
5+
}

.vscode/launch.json

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
{
2+
"version": "0.2.0",
3+
"configurations": [
4+
{
5+
"type": "node",
6+
"request": "launch",
7+
"name": "Debug TypeScript",
8+
"program": "${workspaceFolder}\\src\\index.ts",
9+
"preLaunchTask": "npm: build",
10+
"sourceMaps": true,
11+
"smartStep": true,
12+
"internalConsoleOptions": "openOnSessionStart",
13+
"outFiles": [
14+
"${workspaceFolder}/dist/**/*.js"
15+
]
16+
},
17+
]
18+
}

package-lock.json

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

package.json

Lines changed: 20 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,9 @@
1414
"npm": ">=3.10.0"
1515
},
1616
"scripts": {
17-
"prestart": "npm run -s build",
18-
"start": "node dist/index.js",
19-
"dev": "nodemon src/index.js --exec \"node -r dotenv/config -r babel-register\"",
20-
"clean": "rimraf dist",
21-
"build": "npm run clean && mkdir -p dist && babel src -s -D -d dist",
22-
"test": "jest --watch",
23-
"lint": "esw -w src test"
17+
"jscopy": "copyfiles -u 1 src/**/*.js dist",
18+
"prepare": "tsoa routes && tsoa swagger && tsc && npm run jscopy",
19+
"build": "npm run prepare"
2420
},
2521
"keywords": [
2622
"express",
@@ -35,70 +31,28 @@
3531
"eslint"
3632
],
3733
"dependencies": {
38-
"babel-cli": "^6.26.0",
39-
"babel-plugin-transform-class-properties": "^6.24.1",
40-
"babel-plugin-transform-object-rest-spread": "^6.26.0",
41-
"babel-preset-env": "^1.6.1",
42-
"body-parser": "^1.18.2",
43-
"express": "^4.16.2",
34+
"body-parser": "^1.18.3",
35+
"copyfiles": "^2.1.0",
36+
"express": "^4.16.4",
37+
"express-rate-limit": "^3.4.0",
38+
"generic-json-sanitizer": "^1.0.1",
39+
"helmet": "^3.15.1",
40+
"http": "0.0.0",
4441
"morgan": "^1.9.0",
42+
"path": "^0.12.7",
4543
"pg-promise": "^8.5.6",
4644
"pug": "^2.0.0-beta11",
47-
"rimraf": "^2.6.2"
45+
"randomstring": "^1.1.5",
46+
"rimraf": "^2.6.2",
47+
"tsoa": "^2.3.8"
4848
},
4949
"devDependencies": {
50-
"babel-eslint": "^8.2.3",
51-
"babel-jest": "^21.2.0",
52-
"babel-register": "^6.26.0",
53-
"dotenv": "^4.0.0",
54-
"eslint": "^4.12.1",
55-
"eslint-plugin-import": "^2.11.0",
56-
"eslint-plugin-jest": "^21.3.2",
57-
"eslint-watch": "^3.1.3",
58-
"jest": "^23.6.0",
59-
"nodemon": "^1.12.1",
60-
"supertest": "^3.0.0"
61-
},
62-
"babel": {
63-
"presets": [
64-
[
65-
"env",
66-
{
67-
"targets": {
68-
"node": "current"
69-
}
70-
}
71-
]
72-
],
73-
"plugins": [
74-
"transform-object-rest-spread",
75-
"transform-class-properties"
76-
]
77-
},
78-
"eslintConfig": {
79-
"parser": "babel-eslint",
80-
"plugins": [
81-
"import",
82-
"jest"
83-
],
84-
"parserOptions": {
85-
"ecmaVersion": 2017,
86-
"sourceType": "module"
87-
},
88-
"env": {
89-
"node": true,
90-
"jest": true
91-
},
92-
"extends": [
93-
"eslint:recommended"
94-
],
95-
"rules": {
96-
"jest/no-focused-tests": 2,
97-
"jest/no-identical-title": 2
98-
}
99-
},
100-
"jest": {
101-
"testEnvironment": "node"
50+
"@types/body-parser": "^1.17.0",
51+
"@types/express": "^4.16.0",
52+
"@types/node": "^10.12.27",
53+
"@types/randomstring": "^1.1.6",
54+
"ts-node": "^7.0.1",
55+
"typescript": "^3.3.3333"
10256
},
10357
"bugs": {
10458
"url": "https://github.com/vmasto/express-babel/issues"

public/images/.gitkeep

Whitespace-only changes.

public/scripts/.gitkeep

Whitespace-only changes.

public/styles/style.css

Lines changed: 0 additions & 8 deletions
This file was deleted.

src/app.js

Lines changed: 0 additions & 40 deletions
This file was deleted.

src/app.ts

Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
import * as bodyParser from 'body-parser';
2+
import * as express from 'express';
3+
import * as RateLimit from 'express-rate-limit';
4+
import * as helmet from 'helmet';
5+
import * as path from 'path';
6+
import { RegisterRoutes } from './routers/routes';
7+
import { sanitizeExpressMiddleware } from 'generic-json-sanitizer';
8+
9+
// controllers need to be referenced in order to get crawled by the TSOA generator
10+
import './controllers/botimController';
11+
12+
class App {
13+
public express: express.Express;
14+
15+
constructor() {
16+
/** Creat the express app */
17+
this.express = express();
18+
19+
/** Security is the first thing, right? */
20+
this.vulnerabilityProtection();
21+
22+
/** Parse the request */
23+
this.dataParsing();
24+
25+
/** After data parsed, sanitize it. */
26+
this.sanitizeData();
27+
28+
/** Serve static client side */
29+
this.serveStatic();
30+
31+
/** Route inner system */
32+
this.routes();
33+
34+
/** And never sent errors back to client. */
35+
this.catchErrors();
36+
}
37+
38+
/**
39+
* Serve static files of front-end.
40+
*/
41+
private serveStatic() {
42+
/** In / path only serve the index.html file */
43+
this.express.get('/', (req: express.Request, res: express.Response) =>
44+
res.sendFile(path.join(__dirname, '/public/static/index.html'))
45+
);
46+
/** Get any file in public directory */
47+
this.express.use('/static', express.static(path.join(__dirname, '/public/static/')));
48+
}
49+
50+
/**
51+
* Route requests to API.
52+
*/
53+
private routes(): void {
54+
/** Use generated routers (by TSOA) */
55+
RegisterRoutes(this.express);
56+
}
57+
58+
/**
59+
* Protect from many vulnerabilities ,by http headers such as HSTS HTTPS redirect etc.
60+
*/
61+
private vulnerabilityProtection(): void {
62+
// Protect from DDOS and access thieves
63+
const limiter = new RateLimit({
64+
windowMs: 10 * 60 * 1000,
65+
max: 1000
66+
});
67+
68+
// apply to all IP requests
69+
this.express.use(limiter);
70+
71+
// Protect from XSS and other malicious attacks
72+
this.express.use(helmet());
73+
this.express.use(helmet.frameguard({ action: 'deny' }));
74+
75+
this.express.disable('x-powered-by');
76+
}
77+
78+
/**
79+
* Parse request query and body.
80+
*/
81+
private dataParsing(): void {
82+
this.express.use(bodyParser.json({ limit: '2mb' })); // for parsing application/json
83+
this.express.use(bodyParser.urlencoded({ extended: false }));
84+
}
85+
86+
/**
87+
* Sanitize Json schema arrived from client.
88+
* to avoid stored XSS issues.
89+
*/
90+
private sanitizeData(): void {
91+
92+
// TODO: sanitize query.
93+
this.express.use((req: express.Request, res: express.Response, next: express.NextFunction) => {
94+
sanitizeExpressMiddleware(req, res, next, {
95+
allowedAttributes: {},
96+
allowedTags: []
97+
});
98+
});
99+
}
100+
101+
/**
102+
* Catch any Node / JS error.
103+
*/
104+
private catchErrors() {
105+
// Unknowon routing get 404
106+
this.express.use('*', (req, res) => {
107+
res.statusCode = 404;
108+
res.send();
109+
});
110+
111+
/**
112+
* Production error handler, no stacktraces leaked to user.
113+
*/
114+
this.express.use((err: Error, req: express.Request, res: express.Response, next: express.NextFunction) => {
115+
try {
116+
console.warn(
117+
`express route crash, req: ${req.method} ${req.path} error: ${err.message} body: ${JSON.stringify(
118+
req.body
119+
)}`
120+
);
121+
} catch (error) {
122+
console.warn(`Ok... even the crash route catcher crashd...`);
123+
}
124+
res.status(500).send();
125+
});
126+
}
127+
}
128+
129+
export default new App().express;

0 commit comments

Comments
 (0)