express-generator-typescript 2.3.2 → 2.3.4
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/README.md +2 -0
- package/lib/project-files/spec/support/login.ts +1 -1
- package/lib/project-files/spec/tests/auth.spec.ts +3 -3
- package/lib/project-files/spec/tests/users.spec.ts +6 -5
- package/lib/project-files/src/models/User.ts +49 -50
- package/lib/project-files/src/routes/api.ts +2 -2
- package/lib/project-files/src/routes/middleware/adminMw.ts +0 -1
- package/lib/project-files/src/services/AuthService.ts +4 -2
- package/package.json +1 -1
- package/lib/project-files/src/routes/user-routes.ts +0 -60
package/README.md
CHANGED
|
@@ -12,6 +12,8 @@
|
|
|
12
12
|
Creates a new express application similar to the _express-generator_ module. Except this new
|
|
13
13
|
application is configured to use TypeScript instead of plain JavaScript.
|
|
14
14
|
|
|
15
|
+
This project complies with Typescript best practices listed <a href="https://github.com/seanpmaxwell/Typescript-Best-Practices/blob/main/README.md">here</a>.
|
|
16
|
+
|
|
15
17
|
|
|
16
18
|
## Why express-generator-typescript?
|
|
17
19
|
|
|
@@ -23,7 +23,7 @@ function login(beforeAgent: SuperTest<Test>, done: (arg: string) => void) {
|
|
|
23
23
|
// Setup dummy data
|
|
24
24
|
const role = UserRoles.Admin,
|
|
25
25
|
pwdHash = PwdUtil.hashSync(LoginCreds.password),
|
|
26
|
-
loginUser = User
|
|
26
|
+
loginUser = new User('john smith', LoginCreds.email, role, pwdHash);
|
|
27
27
|
// Add spy
|
|
28
28
|
spyOn(UserRepo, 'getOne').and.resolveTo(loginUser);
|
|
29
29
|
// Call Login API
|
|
@@ -50,7 +50,7 @@ describe('AuthRouter', () => {
|
|
|
50
50
|
// ** Test login ** //
|
|
51
51
|
describe(`"POST:${Login}"`, () => {
|
|
52
52
|
|
|
53
|
-
const EMAIL_NOT_FOUND_ERR = Errors.
|
|
53
|
+
const EMAIL_NOT_FOUND_ERR = Errors.EmailNotFound(LoginCreds.email);
|
|
54
54
|
|
|
55
55
|
const callApi = (reqBody: TReqBody) =>
|
|
56
56
|
agent
|
|
@@ -64,7 +64,7 @@ describe('AuthRouter', () => {
|
|
|
64
64
|
// Setup data
|
|
65
65
|
const role = UserRoles.Standard,
|
|
66
66
|
pwdHash = PwdUtil.hashSync(LoginCreds.password),
|
|
67
|
-
loginUser = User
|
|
67
|
+
loginUser = new User('john smith', LoginCreds.email, role, pwdHash);
|
|
68
68
|
// Add spy
|
|
69
69
|
spyOn(UserRepo, 'getOne').and.resolveTo(loginUser);
|
|
70
70
|
// Call API
|
|
@@ -99,7 +99,7 @@ describe('AuthRouter', () => {
|
|
|
99
99
|
// Setup data
|
|
100
100
|
const role = UserRoles.Standard,
|
|
101
101
|
pwdHash = PwdUtil.hashSync('bad password'),
|
|
102
|
-
loginUser = User
|
|
102
|
+
loginUser = new User('john smith', LoginCreds.email, role, pwdHash);
|
|
103
103
|
// Add spy
|
|
104
104
|
spyOn(UserRepo, 'getOne').and.resolveTo(loginUser);
|
|
105
105
|
// Call API
|
|
@@ -34,14 +34,14 @@ const {
|
|
|
34
34
|
|
|
35
35
|
// Dummy users for GET req
|
|
36
36
|
const DummyGetAllUsers = [
|
|
37
|
-
User
|
|
38
|
-
User
|
|
39
|
-
User
|
|
37
|
+
new User('Sean Maxwell', 'sean.maxwell@gmail.com'),
|
|
38
|
+
new User('John Smith', 'john.smith@gmail.com'),
|
|
39
|
+
new User('Gordan Freeman', 'gordan.freeman@gmail.com'),
|
|
40
40
|
] as const;
|
|
41
41
|
|
|
42
42
|
// Dummy update user
|
|
43
43
|
const DummyUserData = {
|
|
44
|
-
user: User
|
|
44
|
+
user: new User('Gordan Freeman', 'gordan.freeman@gmail.com'),
|
|
45
45
|
} as const;
|
|
46
46
|
|
|
47
47
|
|
|
@@ -79,7 +79,8 @@ describe('UserRouter', () => {
|
|
|
79
79
|
.end((_: Error, res: Response) => {
|
|
80
80
|
expect(res.status).toBe(OK);
|
|
81
81
|
for (let i = 0; i < res.body.users.length; i++) {
|
|
82
|
-
|
|
82
|
+
const user = new User(res.body.users[i]);
|
|
83
|
+
expect(user).toEqual(DummyGetAllUsers[i]);
|
|
83
84
|
}
|
|
84
85
|
done();
|
|
85
86
|
});
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { TAll } from 'jet-validator';
|
|
2
|
-
|
|
3
|
-
|
|
4
1
|
// **** Variables **** //
|
|
5
2
|
|
|
3
|
+
const INVALID_CONSTRUCTOR_PARAM = 'nameOrObj arg must a string or an object ' +
|
|
4
|
+
'with the appropriate user keys.';
|
|
5
|
+
|
|
6
6
|
export enum UserRoles {
|
|
7
7
|
Standard,
|
|
8
8
|
Admin,
|
|
@@ -27,58 +27,57 @@ export interface ISessionUser {
|
|
|
27
27
|
}
|
|
28
28
|
|
|
29
29
|
|
|
30
|
-
// ****
|
|
30
|
+
// **** User **** //
|
|
31
31
|
|
|
32
|
-
|
|
33
|
-
* Get a new User object.
|
|
34
|
-
*/
|
|
35
|
-
function new_(
|
|
36
|
-
name: string,
|
|
37
|
-
email: string,
|
|
38
|
-
role?: UserRoles,
|
|
39
|
-
pwdHash?: string,
|
|
40
|
-
): IUser {
|
|
41
|
-
return {
|
|
42
|
-
id: -1,
|
|
43
|
-
email,
|
|
44
|
-
name,
|
|
45
|
-
role: (role ?? UserRoles.Standard),
|
|
46
|
-
pwdHash: (pwdHash ?? ''),
|
|
47
|
-
};
|
|
48
|
-
}
|
|
32
|
+
class User implements IUser {
|
|
49
33
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
34
|
+
public id: number;
|
|
35
|
+
public name: string;
|
|
36
|
+
public email: string;
|
|
37
|
+
public role?: UserRoles;
|
|
38
|
+
public pwdHash?: string;
|
|
39
|
+
|
|
40
|
+
constructor(
|
|
41
|
+
nameOrObj: string | object,
|
|
42
|
+
email?: string,
|
|
43
|
+
role?: UserRoles,
|
|
44
|
+
pwdHash?: string,
|
|
45
|
+
id?: number,
|
|
46
|
+
) {
|
|
47
|
+
if (typeof nameOrObj === 'string') {
|
|
48
|
+
this.name = nameOrObj;
|
|
49
|
+
this.email = (email ?? '');
|
|
50
|
+
this.role = (role ?? UserRoles.Standard);
|
|
51
|
+
this.pwdHash = (pwdHash ?? '');
|
|
52
|
+
this.id = (id ?? -1);
|
|
53
|
+
} else if (User.IsUserObj(nameOrObj)) {
|
|
54
|
+
const o = nameOrObj as IUser;
|
|
55
|
+
this.name = o.name;
|
|
56
|
+
this.email = (o.email ?? '');
|
|
57
|
+
this.role = (o.role ?? UserRoles.Standard);
|
|
58
|
+
this.pwdHash = (o.pwdHash ?? '');
|
|
59
|
+
this.id = (o.id ?? -1);
|
|
60
|
+
} else {
|
|
61
|
+
throw new Error(INVALID_CONSTRUCTOR_PARAM);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
62
64
|
|
|
63
|
-
/**
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
65
|
+
/**
|
|
66
|
+
* Is this an object which contains all the user keys.
|
|
67
|
+
*/
|
|
68
|
+
public static IsUserObj(this: void, arg: unknown): boolean {
|
|
69
|
+
return (
|
|
70
|
+
!!arg &&
|
|
71
|
+
typeof arg === 'object' &&
|
|
72
|
+
'id' in arg &&
|
|
73
|
+
'email' in arg &&
|
|
74
|
+
'name' in arg &&
|
|
75
|
+
'role' in arg
|
|
76
|
+
);
|
|
77
|
+
}
|
|
75
78
|
}
|
|
76
79
|
|
|
77
80
|
|
|
78
81
|
// **** Export default **** //
|
|
79
82
|
|
|
80
|
-
export default
|
|
81
|
-
new: new_,
|
|
82
|
-
copy,
|
|
83
|
-
instanceOf,
|
|
84
|
-
} as const;
|
|
83
|
+
export default User;
|
|
@@ -48,14 +48,14 @@ userRouter.get(
|
|
|
48
48
|
// Add one user
|
|
49
49
|
userRouter.post(
|
|
50
50
|
Paths.Users.Add,
|
|
51
|
-
validate(['user', User.
|
|
51
|
+
validate(['user', User.IsUserObj]),
|
|
52
52
|
UserRoutes.add,
|
|
53
53
|
);
|
|
54
54
|
|
|
55
55
|
// Update one user
|
|
56
56
|
userRouter.put(
|
|
57
57
|
Paths.Users.Update,
|
|
58
|
-
validate(['user', User.
|
|
58
|
+
validate(['user', User.IsUserObj]),
|
|
59
59
|
UserRoutes.update,
|
|
60
60
|
);
|
|
61
61
|
|
|
@@ -6,7 +6,6 @@ import { Request, Response, NextFunction } from 'express';
|
|
|
6
6
|
import { JwtPayload } from 'jsonwebtoken';
|
|
7
7
|
|
|
8
8
|
import HttpStatusCodes from '@src/constants/HttpStatusCodes';
|
|
9
|
-
import EnvVars from '@src/constants/EnvVars';
|
|
10
9
|
|
|
11
10
|
import SessionUtil from '@src/util/SessionUtil';
|
|
12
11
|
import { ISessionUser, UserRoles } from '@src/models/User';
|
|
@@ -13,7 +13,9 @@ import { IUser } from '@src/models/User';
|
|
|
13
13
|
// Errors
|
|
14
14
|
export const Errors = {
|
|
15
15
|
Unauth: 'Unauthorized',
|
|
16
|
-
|
|
16
|
+
EmailNotFound(email: string) {
|
|
17
|
+
return `User with email "${email}" not found`;
|
|
18
|
+
},
|
|
17
19
|
} as const;
|
|
18
20
|
|
|
19
21
|
|
|
@@ -28,7 +30,7 @@ async function login(email: string, password: string): Promise<IUser> {
|
|
|
28
30
|
if (!user) {
|
|
29
31
|
throw new RouteError(
|
|
30
32
|
HttpStatusCodes.UNAUTHORIZED,
|
|
31
|
-
Errors.
|
|
33
|
+
Errors.EmailNotFound(email),
|
|
32
34
|
);
|
|
33
35
|
}
|
|
34
36
|
// Check password
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "express-generator-typescript",
|
|
3
|
-
"version": "2.3.
|
|
3
|
+
"version": "2.3.4",
|
|
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,60 +0,0 @@
|
|
|
1
|
-
import HttpStatusCodes from '@src/constants/HttpStatusCodes';
|
|
2
|
-
|
|
3
|
-
import userService from '@src/services/user-service';
|
|
4
|
-
import { IUser } from '@src/models/User';
|
|
5
|
-
import { IReq, IRes } from './shared/types';
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
// **** Variables **** //
|
|
9
|
-
|
|
10
|
-
// Paths
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
// **** Functions **** //
|
|
15
|
-
|
|
16
|
-
/**
|
|
17
|
-
* Get all users.
|
|
18
|
-
*/
|
|
19
|
-
async function getAll(_: IReq, res: IRes) {
|
|
20
|
-
const users = await userService.getAll();
|
|
21
|
-
return res.status(HttpStatusCodes.OK).json({ users });
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
/**
|
|
25
|
-
* Add one user.
|
|
26
|
-
*/
|
|
27
|
-
async function add(req: IReq<{user: IUser}>, res: IRes) {
|
|
28
|
-
const { user } = req.body;
|
|
29
|
-
await userService.addOne(user);
|
|
30
|
-
return res.status(HttpStatusCodes.CREATED).end();
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
/**
|
|
34
|
-
* Update one user.
|
|
35
|
-
*/
|
|
36
|
-
async function update(req: IReq<{user: IUser}>, res: IRes) {
|
|
37
|
-
const { user } = req.body;
|
|
38
|
-
await userService.updateOne(user);
|
|
39
|
-
return res.status(HttpStatusCodes.OK).end();
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
/**
|
|
43
|
-
* Delete one user.
|
|
44
|
-
*/
|
|
45
|
-
async function _delete(req: IReq, res: IRes) {
|
|
46
|
-
const id = +req.params.id;
|
|
47
|
-
await userService.delete(id);
|
|
48
|
-
return res.status(HttpStatusCodes.OK).end();
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
// **** Export default **** //
|
|
53
|
-
|
|
54
|
-
export default {
|
|
55
|
-
paths,
|
|
56
|
-
getAll,
|
|
57
|
-
add,
|
|
58
|
-
update,
|
|
59
|
-
delete: _delete,
|
|
60
|
-
} as const;
|