express-generator-typescript 2.1.12 → 2.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/express-generator-typescript.js +15 -11
- package/lib/project-files/package.json +2 -2
- package/lib/project-files/spec/support/login-agent.ts +2 -4
- package/lib/project-files/spec/tests/auth.spec.ts +29 -34
- package/lib/project-files/spec/tests/users.spec.ts +55 -56
- package/lib/project-files/src/{shared → configurations}/EnvVars.ts +0 -0
- package/lib/project-files/src/configurations/HttpStatusCodes.ts +386 -0
- package/lib/project-files/src/declarations/classes.ts +13 -0
- package/lib/project-files/src/{shared → declarations}/enums.ts +0 -0
- package/lib/project-files/src/{shared → declarations}/functions.ts +1 -0
- package/lib/project-files/src/{shared → declarations}/types.ts +0 -0
- package/lib/project-files/src/index.ts +1 -1
- package/lib/project-files/src/models/User.ts +1 -1
- package/lib/project-files/src/repos/user-repo.ts +1 -1
- package/lib/project-files/src/routes/auth-routes.ts +5 -8
- package/lib/project-files/src/routes/middlware/adminMw.ts +26 -27
- package/lib/project-files/src/routes/middlware/validate.ts +29 -25
- package/lib/project-files/src/routes/user-routes.ts +6 -9
- package/lib/project-files/src/server.ts +11 -17
- package/lib/project-files/src/services/auth-service.ts +21 -6
- package/lib/project-files/src/services/user-service.ts +17 -3
- package/lib/project-files/src/util/jwt-util.ts +1 -1
- package/lib/project-files/src/util/pwd-util.ts +39 -0
- package/lib/project-files/tsconfig.json +5 -2
- package/package.json +1 -1
- package/lib/project-files/src/shared/errors.ts +0 -54
|
@@ -1,15 +1,12 @@
|
|
|
1
|
-
import
|
|
1
|
+
import HttpStatusCodes from '@configurations/HttpStatusCodes';
|
|
2
2
|
|
|
3
3
|
import userService from '@services/user-service';
|
|
4
4
|
import { IUser } from '@models/User';
|
|
5
|
-
import { IReq, IRes } from '@
|
|
5
|
+
import { IReq, IRes } from '@declarations/types';
|
|
6
6
|
|
|
7
7
|
|
|
8
8
|
// **** Variables **** //
|
|
9
9
|
|
|
10
|
-
// Misc
|
|
11
|
-
const { CREATED, OK } = StatusCodes;
|
|
12
|
-
|
|
13
10
|
// Paths
|
|
14
11
|
const paths = {
|
|
15
12
|
basePath: '/users',
|
|
@@ -27,7 +24,7 @@ const paths = {
|
|
|
27
24
|
*/
|
|
28
25
|
async function getAll(_: IReq, res: IRes) {
|
|
29
26
|
const users = await userService.getAll();
|
|
30
|
-
return res.status(OK).json({ users });
|
|
27
|
+
return res.status(HttpStatusCodes.OK).json({ users });
|
|
31
28
|
}
|
|
32
29
|
|
|
33
30
|
/**
|
|
@@ -36,7 +33,7 @@ async function getAll(_: IReq, res: IRes) {
|
|
|
36
33
|
async function add(req: IReq<{user: IUser}>, res: IRes) {
|
|
37
34
|
const { user } = req.body;
|
|
38
35
|
await userService.addOne(user);
|
|
39
|
-
return res.status(CREATED).end();
|
|
36
|
+
return res.status(HttpStatusCodes.CREATED).end();
|
|
40
37
|
}
|
|
41
38
|
|
|
42
39
|
/**
|
|
@@ -45,7 +42,7 @@ async function add(req: IReq<{user: IUser}>, res: IRes) {
|
|
|
45
42
|
async function update(req: IReq<{user: IUser}>, res: IRes) {
|
|
46
43
|
const { user } = req.body;
|
|
47
44
|
await userService.updateOne(user);
|
|
48
|
-
return res.status(OK).end();
|
|
45
|
+
return res.status(HttpStatusCodes.OK).end();
|
|
49
46
|
}
|
|
50
47
|
|
|
51
48
|
/**
|
|
@@ -54,7 +51,7 @@ async function update(req: IReq<{user: IUser}>, res: IRes) {
|
|
|
54
51
|
async function _delete(req: IReq, res: IRes) {
|
|
55
52
|
const id = +req.params.id;
|
|
56
53
|
await userService.delete(id);
|
|
57
|
-
return res.status(OK).end();
|
|
54
|
+
return res.status(HttpStatusCodes.OK).end();
|
|
58
55
|
}
|
|
59
56
|
|
|
60
57
|
|
|
@@ -2,17 +2,16 @@ import cookieParser from 'cookie-parser';
|
|
|
2
2
|
import morgan from 'morgan';
|
|
3
3
|
import path from 'path';
|
|
4
4
|
import helmet from 'helmet';
|
|
5
|
-
import StatusCodes from 'http-status-codes';
|
|
6
5
|
import express, { Request, Response, NextFunction } from 'express';
|
|
7
6
|
|
|
8
7
|
import 'express-async-errors';
|
|
9
8
|
|
|
10
9
|
import BaseRouter from './routes/api';
|
|
11
10
|
import logger from 'jet-logger';
|
|
12
|
-
import EnvVars from '@
|
|
13
|
-
import
|
|
14
|
-
|
|
15
|
-
import {
|
|
11
|
+
import EnvVars from '@configurations/EnvVars';
|
|
12
|
+
import HttpStatusCodes from '@configurations/HttpStatusCodes';
|
|
13
|
+
import { NodeEnvs } from '@declarations/enums';
|
|
14
|
+
import { RouteError } from '@declarations/classes';
|
|
16
15
|
|
|
17
16
|
|
|
18
17
|
// **** Init express **** //
|
|
@@ -44,23 +43,18 @@ app.use('/api', BaseRouter);
|
|
|
44
43
|
|
|
45
44
|
// Setup error handler
|
|
46
45
|
app.use((
|
|
47
|
-
err: Error
|
|
46
|
+
err: Error,
|
|
48
47
|
_: Request,
|
|
49
48
|
res: Response,
|
|
50
49
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
51
|
-
|
|
50
|
+
next: NextFunction,
|
|
52
51
|
) => {
|
|
53
52
|
logger.err(err, true);
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
);
|
|
60
|
-
// Return
|
|
61
|
-
return res.status(status).json({
|
|
62
|
-
error: err.message,
|
|
63
|
-
});
|
|
53
|
+
let status = HttpStatusCodes.BAD_REQUEST;
|
|
54
|
+
if (err instanceof RouteError) {
|
|
55
|
+
status = err.status;
|
|
56
|
+
}
|
|
57
|
+
return res.status(status).json({ error: err.message });
|
|
64
58
|
});
|
|
65
59
|
|
|
66
60
|
|
|
@@ -1,8 +1,17 @@
|
|
|
1
|
-
import bcrypt from 'bcrypt';
|
|
2
|
-
|
|
3
1
|
import userRepo from '@repos/user-repo';
|
|
4
2
|
import jwtUtil from '@util/jwt-util';
|
|
5
|
-
import
|
|
3
|
+
import pwdUtil from '@util/pwd-util';
|
|
4
|
+
import HttpStatusCodes from '@configurations/HttpStatusCodes';
|
|
5
|
+
import { RouteError } from '@declarations/classes';
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
// **** Variables **** //
|
|
9
|
+
|
|
10
|
+
// Errors
|
|
11
|
+
export const errors = {
|
|
12
|
+
unauth: 'Unauthorized',
|
|
13
|
+
emailNotFound: (email: string) => `User with email "${email}" not found`,
|
|
14
|
+
} as const;
|
|
6
15
|
|
|
7
16
|
|
|
8
17
|
// **** Functions **** //
|
|
@@ -14,13 +23,19 @@ async function getJwt(email: string, password: string): Promise<string> {
|
|
|
14
23
|
// Fetch user
|
|
15
24
|
const user = await userRepo.getOne(email);
|
|
16
25
|
if (!user) {
|
|
17
|
-
throw new
|
|
26
|
+
throw new RouteError(
|
|
27
|
+
HttpStatusCodes.UNAUTHORIZED,
|
|
28
|
+
errors.emailNotFound(email),
|
|
29
|
+
);
|
|
18
30
|
}
|
|
19
31
|
// Check password
|
|
20
32
|
const hash = (user.pwdHash ?? '');
|
|
21
|
-
const pwdPassed = await
|
|
33
|
+
const pwdPassed = await pwdUtil.compare(password, hash);
|
|
22
34
|
if (!pwdPassed) {
|
|
23
|
-
throw new
|
|
35
|
+
throw new RouteError(
|
|
36
|
+
HttpStatusCodes.UNAUTHORIZED,
|
|
37
|
+
errors.unauth,
|
|
38
|
+
);
|
|
24
39
|
}
|
|
25
40
|
// Setup Admin Cookie
|
|
26
41
|
return jwtUtil.sign({
|
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
import userRepo from '@repos/user-repo';
|
|
2
2
|
import { IUser } from '@models/User';
|
|
3
|
-
import {
|
|
3
|
+
import { RouteError } from '@declarations/classes';
|
|
4
|
+
import HttpStatusCodes from '@configurations/HttpStatusCodes';
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
// **** Variables **** //
|
|
8
|
+
|
|
9
|
+
export const userNotFoundErr = 'User not found';
|
|
4
10
|
|
|
5
11
|
|
|
6
12
|
// **** Functions **** //
|
|
@@ -25,8 +31,12 @@ function addOne(user: IUser): Promise<void> {
|
|
|
25
31
|
async function updateOne(user: IUser): Promise<void> {
|
|
26
32
|
const persists = await userRepo.persists(user.id);
|
|
27
33
|
if (!persists) {
|
|
28
|
-
throw new
|
|
34
|
+
throw new RouteError(
|
|
35
|
+
HttpStatusCodes.NOT_FOUND,
|
|
36
|
+
userNotFoundErr,
|
|
37
|
+
);
|
|
29
38
|
}
|
|
39
|
+
// Return user
|
|
30
40
|
return userRepo.update(user);
|
|
31
41
|
}
|
|
32
42
|
|
|
@@ -36,8 +46,12 @@ async function updateOne(user: IUser): Promise<void> {
|
|
|
36
46
|
async function _delete(id: number): Promise<void> {
|
|
37
47
|
const persists = await userRepo.persists(id);
|
|
38
48
|
if (!persists) {
|
|
39
|
-
throw new
|
|
49
|
+
throw new RouteError(
|
|
50
|
+
HttpStatusCodes.NOT_FOUND,
|
|
51
|
+
userNotFoundErr,
|
|
52
|
+
);
|
|
40
53
|
}
|
|
54
|
+
// Delete user
|
|
41
55
|
return userRepo.delete(id);
|
|
42
56
|
}
|
|
43
57
|
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import bcrypt from 'bcrypt';
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
// **** Variables **** //
|
|
5
|
+
|
|
6
|
+
const saltRounds = 12;
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
// **** Functions **** //
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Get a hash from the password.
|
|
13
|
+
*/
|
|
14
|
+
function getHash(pwd: string): Promise<string> {
|
|
15
|
+
return bcrypt.hash(pwd, saltRounds);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Useful for testing.
|
|
20
|
+
*/
|
|
21
|
+
function hashSync(pwd: string): string {
|
|
22
|
+
return bcrypt.hashSync(pwd, saltRounds);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* See if a password passes the hash.
|
|
27
|
+
*/
|
|
28
|
+
function compare(pwd: string, hash: string): Promise<boolean> {
|
|
29
|
+
return bcrypt.compare(pwd, hash);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
// **** Export Default **** //
|
|
34
|
+
|
|
35
|
+
export default {
|
|
36
|
+
getHash,
|
|
37
|
+
hashSync,
|
|
38
|
+
compare,
|
|
39
|
+
} as const;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "express-generator-typescript",
|
|
3
|
-
"version": "2.1
|
|
3
|
+
"version": "2.2.1",
|
|
4
4
|
"description": "Generate new Express applications similar to express-generate which but sets it up to use TypeScript instead",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"express-generator-typescript": "node bin/cli.js",
|
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
import HttpStatusCodes from 'http-status-codes';
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
export abstract class CustomError extends Error {
|
|
5
|
-
|
|
6
|
-
public readonly HttpStatus = HttpStatusCodes.BAD_REQUEST;
|
|
7
|
-
|
|
8
|
-
constructor(msg: string, httpStatus: number) {
|
|
9
|
-
super(msg);
|
|
10
|
-
this.HttpStatus = httpStatus;
|
|
11
|
-
}
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
export class ParamInvalidError extends CustomError {
|
|
15
|
-
|
|
16
|
-
public static readonly Msg = 'One or more of the required was missing ' +
|
|
17
|
-
'or invalid.';
|
|
18
|
-
public static readonly HttpStatus = HttpStatusCodes.BAD_REQUEST;
|
|
19
|
-
|
|
20
|
-
constructor() {
|
|
21
|
-
super(ParamInvalidError.Msg, ParamInvalidError.HttpStatus);
|
|
22
|
-
}
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
export class ValidatorFnError extends CustomError {
|
|
26
|
-
|
|
27
|
-
public static readonly Msg = 'Validator function failed. function name: ';
|
|
28
|
-
public static readonly HttpStatus = HttpStatusCodes.BAD_REQUEST;
|
|
29
|
-
|
|
30
|
-
constructor(fnName: string) {
|
|
31
|
-
super(ValidatorFnError.Msg + fnName, ValidatorFnError.HttpStatus);
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
export class UserNotFoundError extends CustomError {
|
|
36
|
-
|
|
37
|
-
public static readonly Msg = 'A user with the given id does not exists ' +
|
|
38
|
-
'in the database.';
|
|
39
|
-
public static readonly HttpStatus = HttpStatusCodes.NOT_FOUND;
|
|
40
|
-
|
|
41
|
-
constructor() {
|
|
42
|
-
super(UserNotFoundError.Msg, UserNotFoundError.HttpStatus);
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
export class UnauthorizedError extends CustomError {
|
|
47
|
-
|
|
48
|
-
public static readonly Msg = 'Login failed';
|
|
49
|
-
public static readonly HttpStatus = HttpStatusCodes.UNAUTHORIZED;
|
|
50
|
-
|
|
51
|
-
constructor() {
|
|
52
|
-
super(UnauthorizedError.Msg, UnauthorizedError.HttpStatus);
|
|
53
|
-
}
|
|
54
|
-
}
|