express-generator-typescript 2.4.25 → 2.5.0
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 +24 -33
- package/lib/cli.js +5 -25
- package/lib/express-generator-typescript.js +11 -19
- package/lib/project-files/README.md +18 -1
- package/lib/{project-files-auth/env/development.env → project-files/config/.env.development} +0 -9
- package/lib/project-files/config/.env.production +14 -0
- package/lib/project-files/{env/test.env → config/.env.test} +0 -10
- package/lib/project-files/config.js +18 -0
- package/lib/project-files/config.ts +22 -0
- package/lib/project-files/eslint.config.ts +96 -0
- package/lib/project-files/gitignore +2 -0
- package/lib/project-files/package.json +16 -9
- package/lib/project-files/scripts/build.ts +4 -0
- package/lib/project-files/spec/support/Paths.ts +1 -6
- package/lib/project-files/spec/support/apiCb.ts +18 -6
- package/lib/project-files/spec/tests/users.spec.ts +28 -33
- package/lib/project-files/spec/types/misc.ts +7 -6
- package/lib/project-files/spec/types/supertest/index.d.ts +2 -2
- package/lib/project-files/src/common/Env.ts +10 -0
- package/lib/project-files/src/common/route-errors.ts +41 -0
- package/lib/project-files/src/index.ts +3 -3
- package/lib/project-files/src/models/User.ts +9 -57
- package/lib/project-files/src/repos/MockOrm.ts +0 -2
- package/lib/project-files/src/repos/database.json +1 -1
- package/lib/project-files/src/routes/UserRoutes.ts +14 -5
- package/lib/project-files/src/{common → routes/common}/Paths.ts +0 -4
- package/lib/project-files/src/routes/common/index.ts +37 -0
- package/lib/project-files/src/routes/index.ts +1 -1
- package/lib/project-files/src/server.ts +7 -9
- package/lib/project-files/src/services/UserService.ts +1 -1
- package/lib/project-files/src/util/misc.ts +0 -16
- package/lib/project-files/src/util/schema.ts +11 -0
- package/lib/project-files/src/util/validators.ts +322 -0
- package/lib/project-files/tsconfig.json +20 -71
- package/lib/project-files/tsconfig.prod.json +22 -2
- package/package.json +1 -1
- package/lib/project-files/env/development.env +0 -24
- package/lib/project-files/env/production.env +0 -25
- package/lib/project-files/eslint.config.mjs +0 -58
- package/lib/project-files/preload.js +0 -23
- package/lib/project-files/src/common/EnvVars.ts +0 -24
- package/lib/project-files/src/common/classes.ts +0 -32
- package/lib/project-files/src/common/misc.ts +0 -5
- package/lib/project-files/src/routes/common/check.ts +0 -143
- package/lib/project-files/src/routes/common/types.ts +0 -8
- package/lib/project-files-auth/README.md +0 -35
- package/lib/project-files-auth/env/production.env +0 -25
- package/lib/project-files-auth/env/test.env +0 -24
- package/lib/project-files-auth/eslint.config.mjs +0 -58
- package/lib/project-files-auth/gitignore +0 -3
- package/lib/project-files-auth/package.json +0 -60
- package/lib/project-files-auth/preload.js +0 -23
- package/lib/project-files-auth/scripts/build.ts +0 -62
- package/lib/project-files-auth/spec/index.ts +0 -46
- package/lib/project-files-auth/spec/support/Paths.ts +0 -10
- package/lib/project-files-auth/spec/support/apiCb.ts +0 -76
- package/lib/project-files-auth/spec/support/jasmine.json +0 -11
- package/lib/project-files-auth/spec/support/login.ts +0 -42
- package/lib/project-files-auth/spec/tests/auth.spec.ts +0 -115
- package/lib/project-files-auth/spec/tests/users.spec.ts +0 -190
- package/lib/project-files-auth/spec/types/misc.ts +0 -12
- package/lib/project-files-auth/spec/types/supertest/index.d.ts +0 -14
- package/lib/project-files-auth/src/common/EnvVars.ts +0 -24
- package/lib/project-files-auth/src/common/HttpStatusCodes.ts +0 -386
- package/lib/project-files-auth/src/common/Paths.ts +0 -20
- package/lib/project-files-auth/src/common/classes.ts +0 -31
- package/lib/project-files-auth/src/index.ts +0 -12
- package/lib/project-files-auth/src/models/User.ts +0 -89
- package/lib/project-files-auth/src/public/scripts/http.js +0 -26
- package/lib/project-files-auth/src/public/scripts/login.js +0 -15
- package/lib/project-files-auth/src/public/scripts/users.js +0 -138
- package/lib/project-files-auth/src/public/stylesheets/login.css +0 -24
- package/lib/project-files-auth/src/public/stylesheets/users.css +0 -43
- package/lib/project-files-auth/src/repos/MockOrm.ts +0 -42
- package/lib/project-files-auth/src/repos/UserRepo.ts +0 -93
- package/lib/project-files-auth/src/repos/database.json +0 -1
- package/lib/project-files-auth/src/routes/AuthRoutes.ts +0 -42
- package/lib/project-files-auth/src/routes/UserRoutes.ts +0 -55
- package/lib/project-files-auth/src/routes/common/check.ts +0 -143
- package/lib/project-files-auth/src/routes/common/types.ts +0 -22
- package/lib/project-files-auth/src/routes/index.ts +0 -43
- package/lib/project-files-auth/src/routes/middleware/adminMw.ts +0 -47
- package/lib/project-files-auth/src/server.ts +0 -91
- package/lib/project-files-auth/src/services/AuthService.ts +0 -57
- package/lib/project-files-auth/src/services/UserService.ts +0 -59
- package/lib/project-files-auth/src/util/PwdUtil.ts +0 -39
- package/lib/project-files-auth/src/util/SessionUtil.ts +0 -94
- package/lib/project-files-auth/src/util/misc.ts +0 -22
- package/lib/project-files-auth/src/views/login.html +0 -58
- package/lib/project-files-auth/src/views/users.html +0 -140
- package/lib/project-files-auth/tsconfig.json +0 -87
- package/lib/project-files-auth/tsconfig.prod.json +0 -12
- /package/lib/{project-files-auth/src/common/misc.ts → project-files/src/common/constants.ts} +0 -0
|
@@ -6,23 +6,23 @@ import app from '@src/server';
|
|
|
6
6
|
|
|
7
7
|
import UserRepo from '@src/repos/UserRepo';
|
|
8
8
|
import User, { IUser } from '@src/models/User';
|
|
9
|
-
import HttpStatusCodes from '@src/common/HttpStatusCodes';
|
|
10
9
|
import { USER_NOT_FOUND_ERR } from '@src/services/UserService';
|
|
10
|
+
import { safeJsonParse } from '@src/util/validators';
|
|
11
|
+
|
|
12
|
+
import HttpStatusCodes from '@src/common/HttpStatusCodes';
|
|
13
|
+
import { IValidationErrFormat, ValidationErr } from '@src/common/route-errors';
|
|
11
14
|
|
|
12
15
|
import Paths from 'spec/support/Paths';
|
|
13
16
|
import apiCb from 'spec/support/apiCb';
|
|
14
17
|
import { TApiCb } from 'spec/types/misc';
|
|
15
|
-
import { ValidationErr } from '@src/common/classes';
|
|
16
18
|
|
|
17
19
|
|
|
18
20
|
// Dummy users for GET req
|
|
19
|
-
const getDummyUsers = () =>
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
];
|
|
25
|
-
};
|
|
21
|
+
const getDummyUsers = () => [
|
|
22
|
+
User.new({ name: 'Sean Maxwell', email: 'sean.maxwell@gmail.com' }),
|
|
23
|
+
User.new({ name: 'John Smith', email: 'john.smith@gmail.com' }),
|
|
24
|
+
User.new({ name: 'Gordan Freeman', email: 'gordan.freeman@gmail.com' }),
|
|
25
|
+
];
|
|
26
26
|
|
|
27
27
|
|
|
28
28
|
// Tests
|
|
@@ -47,7 +47,7 @@ describe('UserRouter', () => {
|
|
|
47
47
|
|
|
48
48
|
// Success
|
|
49
49
|
it('should return a JSON object with all the users and a status code ' +
|
|
50
|
-
`of "${HttpStatusCodes.OK}" if the request was successful.`,
|
|
50
|
+
`of "${HttpStatusCodes.OK}" if the request was successful.`, done => {
|
|
51
51
|
// Add spy
|
|
52
52
|
const data = getDummyUsers();
|
|
53
53
|
spyOn(UserRepo, 'getAll').and.resolveTo(data);
|
|
@@ -63,8 +63,7 @@ describe('UserRouter', () => {
|
|
|
63
63
|
// Test add user
|
|
64
64
|
describe(`"POST:${Paths.Users.Add}"`, () => {
|
|
65
65
|
|
|
66
|
-
const
|
|
67
|
-
DUMMY_USER = getDummyUsers()[0];
|
|
66
|
+
const DUMMY_USER = getDummyUsers()[0];
|
|
68
67
|
|
|
69
68
|
// Setup API
|
|
70
69
|
const callApi = (user: IUser | null, cb: TApiCb) =>
|
|
@@ -75,7 +74,7 @@ describe('UserRouter', () => {
|
|
|
75
74
|
|
|
76
75
|
// Test add user success
|
|
77
76
|
it(`should return a status code of "${HttpStatusCodes.CREATED}" if the ` +
|
|
78
|
-
'request was successful.',
|
|
77
|
+
'request was successful.', done => {
|
|
79
78
|
// Spy
|
|
80
79
|
spyOn(UserRepo, 'add').and.resolveTo();
|
|
81
80
|
// Call api
|
|
@@ -86,13 +85,15 @@ describe('UserRouter', () => {
|
|
|
86
85
|
});
|
|
87
86
|
|
|
88
87
|
// Missing param
|
|
89
|
-
it(
|
|
90
|
-
|
|
91
|
-
|
|
88
|
+
it('should return a JSON object with an error message of and a status ' +
|
|
89
|
+
`code of "${HttpStatusCodes.BAD_REQUEST}" if the user param was ` +
|
|
90
|
+
'missing.', done => {
|
|
92
91
|
// Call api
|
|
93
92
|
callApi(null, res => {
|
|
94
93
|
expect(res.status).toBe(HttpStatusCodes.BAD_REQUEST);
|
|
95
|
-
|
|
94
|
+
const errorObj = safeJsonParse<IValidationErrFormat>(res.body.error);
|
|
95
|
+
expect(errorObj.error).toBe(ValidationErr.MSG);
|
|
96
|
+
expect(errorObj.parameter).toBe('user');
|
|
96
97
|
done();
|
|
97
98
|
});
|
|
98
99
|
});
|
|
@@ -101,8 +102,7 @@ describe('UserRouter', () => {
|
|
|
101
102
|
// Update users
|
|
102
103
|
describe(`"PUT:${Paths.Users.Update}"`, () => {
|
|
103
104
|
|
|
104
|
-
const
|
|
105
|
-
DUMMY_USER = getDummyUsers()[0];
|
|
105
|
+
const DUMMY_USER = getDummyUsers()[0];
|
|
106
106
|
|
|
107
107
|
// Setup API
|
|
108
108
|
const callApi = (user: IUser | null, cb: TApiCb) =>
|
|
@@ -113,11 +113,9 @@ describe('UserRouter', () => {
|
|
|
113
113
|
|
|
114
114
|
// Success
|
|
115
115
|
it(`should return a status code of "${HttpStatusCodes.OK}" if the ` +
|
|
116
|
-
'request was successful.',
|
|
117
|
-
// Setup spies
|
|
116
|
+
'request was successful.', done => {
|
|
118
117
|
spyOn(UserRepo, 'update').and.resolveTo();
|
|
119
118
|
spyOn(UserRepo, 'persists').and.resolveTo(true);
|
|
120
|
-
// Call api
|
|
121
119
|
callApi(DUMMY_USER, res => {
|
|
122
120
|
expect(res.status).toBe(HttpStatusCodes.OK);
|
|
123
121
|
done();
|
|
@@ -125,13 +123,14 @@ describe('UserRouter', () => {
|
|
|
125
123
|
});
|
|
126
124
|
|
|
127
125
|
// Param missing
|
|
128
|
-
it(
|
|
129
|
-
`
|
|
130
|
-
|
|
131
|
-
// Call api
|
|
126
|
+
it('should return a JSON object with an error message and a status code ' +
|
|
127
|
+
`of "${HttpStatusCodes.BAD_REQUEST}" if the user param was missing`,
|
|
128
|
+
done => {
|
|
132
129
|
callApi(null, res => {
|
|
133
130
|
expect(res.status).toBe(HttpStatusCodes.BAD_REQUEST);
|
|
134
|
-
|
|
131
|
+
const errorObj = safeJsonParse<IValidationErrFormat>(res.body.error);
|
|
132
|
+
expect(errorObj.error).toBe(ValidationErr.MSG);
|
|
133
|
+
expect(errorObj.parameter).toBe('user');
|
|
135
134
|
done();
|
|
136
135
|
});
|
|
137
136
|
});
|
|
@@ -139,8 +138,7 @@ describe('UserRouter', () => {
|
|
|
139
138
|
// User not found
|
|
140
139
|
it('should return a JSON object with the error message of ' +
|
|
141
140
|
`"${USER_NOT_FOUND_ERR}" and a status code of ` +
|
|
142
|
-
`"${HttpStatusCodes.NOT_FOUND}" if the id was not found.`,
|
|
143
|
-
// Call api
|
|
141
|
+
`"${HttpStatusCodes.NOT_FOUND}" if the id was not found.`, done => {
|
|
144
142
|
callApi(DUMMY_USER, res => {
|
|
145
143
|
expect(res.status).toBe(HttpStatusCodes.NOT_FOUND);
|
|
146
144
|
expect(res.body.error).toBe(USER_NOT_FOUND_ERR);
|
|
@@ -160,11 +158,9 @@ describe('UserRouter', () => {
|
|
|
160
158
|
|
|
161
159
|
// Success
|
|
162
160
|
it(`should return a status code of "${HttpStatusCodes.OK}" if the ` +
|
|
163
|
-
'request was successful.',
|
|
164
|
-
// Setup spies
|
|
161
|
+
'request was successful.', done => {
|
|
165
162
|
spyOn(UserRepo, 'delete').and.resolveTo();
|
|
166
163
|
spyOn(UserRepo, 'persists').and.resolveTo(true);
|
|
167
|
-
// Call api
|
|
168
164
|
callApi(5, res => {
|
|
169
165
|
expect(res.status).toBe(HttpStatusCodes.OK);
|
|
170
166
|
done();
|
|
@@ -175,7 +171,6 @@ describe('UserRouter', () => {
|
|
|
175
171
|
it('should return a JSON object with the error message of ' +
|
|
176
172
|
`"${USER_NOT_FOUND_ERR}" and a status code of ` +
|
|
177
173
|
`"${HttpStatusCodes.NOT_FOUND}" if the id was not found.`, done => {
|
|
178
|
-
// Setup spies
|
|
179
174
|
callApi(-1, res => {
|
|
180
175
|
expect(res.status).toBe(HttpStatusCodes.NOT_FOUND);
|
|
181
176
|
expect(res.body.error).toBe(USER_NOT_FOUND_ERR);
|
|
@@ -3,10 +3,11 @@ import { IUser } from '@src/models/User';
|
|
|
3
3
|
|
|
4
4
|
|
|
5
5
|
// Misc
|
|
6
|
-
export type
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
}
|
|
6
|
+
export type TRes = Omit<Response, 'body'> & {
|
|
7
|
+
body: {
|
|
8
|
+
error?: string,
|
|
9
|
+
user?: IUser,
|
|
10
|
+
users?: IUser[],
|
|
11
|
+
},
|
|
12
|
+
};
|
|
12
13
|
export type TApiCb = (res: TRes) => void;
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import HttpStatusCodes from '@src/common/HttpStatusCodes';
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
export interface IValidationErrFormat {
|
|
5
|
+
error: string;
|
|
6
|
+
parameter: string;
|
|
7
|
+
value?: unknown;
|
|
8
|
+
'more-info'?: string;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Error with status code and message.
|
|
14
|
+
*/
|
|
15
|
+
export class RouteError extends Error {
|
|
16
|
+
public status: HttpStatusCodes;
|
|
17
|
+
|
|
18
|
+
public constructor(status: HttpStatusCodes, message: string) {
|
|
19
|
+
super(message);
|
|
20
|
+
this.status = status;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Validation in route layer errors.
|
|
26
|
+
*/
|
|
27
|
+
export class ValidationErr extends RouteError {
|
|
28
|
+
public static MSG = 'The following parameter was missing or invalid.';
|
|
29
|
+
|
|
30
|
+
public constructor(parameter: string, value?: unknown, moreInfo?: string) {
|
|
31
|
+
const msgObj: Record<string, unknown> = {
|
|
32
|
+
error: ValidationErr.MSG,
|
|
33
|
+
parameter,
|
|
34
|
+
value,
|
|
35
|
+
};
|
|
36
|
+
if (!!moreInfo) {
|
|
37
|
+
msgObj['more-info'] = moreInfo;
|
|
38
|
+
}
|
|
39
|
+
super(HttpStatusCodes.BAD_REQUEST, JSON.stringify(msgObj));
|
|
40
|
+
}
|
|
41
|
+
}
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import logger from 'jet-logger';
|
|
2
2
|
|
|
3
|
-
import
|
|
3
|
+
import Env from '@src/common/Env';
|
|
4
4
|
import server from './server';
|
|
5
5
|
|
|
6
6
|
|
|
7
7
|
// **** Run **** //
|
|
8
8
|
|
|
9
9
|
const SERVER_START_MSG = ('Express server started on port: ' +
|
|
10
|
-
|
|
10
|
+
Env.Port.toString());
|
|
11
11
|
|
|
12
|
-
server.listen(
|
|
12
|
+
server.listen(Env.Port, () => logger.info(SERVER_START_MSG));
|
|
@@ -1,14 +1,7 @@
|
|
|
1
|
-
import
|
|
1
|
+
import schema from '@src/util/schema';
|
|
2
|
+
import { isNum, isStr } from '@src/util/validators';
|
|
2
3
|
|
|
3
4
|
|
|
4
|
-
// **** Variables **** //
|
|
5
|
-
|
|
6
|
-
const INVALID_CONSTRUCTOR_PARAM = 'nameOrObj arg must a string or an object ' +
|
|
7
|
-
'with the appropriate user keys.';
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
// **** Types **** //
|
|
11
|
-
|
|
12
5
|
export interface IUser {
|
|
13
6
|
id: number;
|
|
14
7
|
name: string;
|
|
@@ -16,55 +9,14 @@ export interface IUser {
|
|
|
16
9
|
created: Date;
|
|
17
10
|
}
|
|
18
11
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
function new_(
|
|
26
|
-
name?: string,
|
|
27
|
-
email?: string,
|
|
28
|
-
created?: Date,
|
|
29
|
-
id?: number, // id last cause usually set by db
|
|
30
|
-
): IUser {
|
|
31
|
-
return {
|
|
32
|
-
id: (id ?? -1),
|
|
33
|
-
name: (name ?? ''),
|
|
34
|
-
email: (email ?? ''),
|
|
35
|
-
created: (created ? new Date(created) : new Date()),
|
|
36
|
-
};
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
/**
|
|
40
|
-
* Get user instance from object.
|
|
41
|
-
*/
|
|
42
|
-
function from(param: object): IUser {
|
|
43
|
-
if (isUser(param)) {
|
|
44
|
-
return new_(param.name, param.email, param.created, param.id);
|
|
45
|
-
}
|
|
46
|
-
throw new Error(INVALID_CONSTRUCTOR_PARAM);
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
/**
|
|
50
|
-
* See if the param meets criteria to be a user.
|
|
51
|
-
*/
|
|
52
|
-
function isUser(arg: unknown): arg is IUser {
|
|
53
|
-
return (
|
|
54
|
-
!!arg &&
|
|
55
|
-
typeof arg === 'object' &&
|
|
56
|
-
'id' in arg && typeof arg.id === 'number' &&
|
|
57
|
-
'email' in arg && typeof arg.email === 'string' &&
|
|
58
|
-
'name' in arg && typeof arg.name === 'string' &&
|
|
59
|
-
'created' in arg && moment(arg.created as string | Date).isValid()
|
|
60
|
-
);
|
|
61
|
-
}
|
|
12
|
+
const User = schema<IUser>({
|
|
13
|
+
id: isNum,
|
|
14
|
+
name: isStr,
|
|
15
|
+
created: Date,
|
|
16
|
+
email: isStr,
|
|
17
|
+
});
|
|
62
18
|
|
|
63
19
|
|
|
64
20
|
// **** Export default **** //
|
|
65
21
|
|
|
66
|
-
export default
|
|
67
|
-
new: new_,
|
|
68
|
-
from,
|
|
69
|
-
isUser,
|
|
70
|
-
} as const;
|
|
22
|
+
export default User;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"users":[{"id":366115170645,"name":"Sean Maxwell","email":"smaxwell@example.com","created":"2024-03-22T05:14:36.252Z"},{"id":310946254456,"name":"John Smith","email":"john.smith@example.com","created":"2024-03-22T05:20:55.079Z"},{"id":143027113460,"name":"Gordan Freeman","email":"nova@prospect.com","created":"2024-03-22T05:42:18.895Z"}
|
|
1
|
+
{"users":[{"id":366115170645,"name":"Sean Maxwell","email":"smaxwell@example.com","created":"2024-03-22T05:14:36.252Z"},{"id":310946254456,"name":"John Smith","email":"john.smith@example.com","created":"2024-03-22T05:20:55.079Z"},{"id":143027113460,"name":"Gordan Freeman","email":"nova@prospect.com","created":"2024-03-22T05:42:18.895Z"}]}
|
|
@@ -1,9 +1,18 @@
|
|
|
1
1
|
import HttpStatusCodes from '@src/common/HttpStatusCodes';
|
|
2
2
|
import UserService from '@src/services/UserService';
|
|
3
3
|
import User from '@src/models/User';
|
|
4
|
+
import { isNum, transform } from '@src/util/validators';
|
|
4
5
|
|
|
5
|
-
import { IReq, IRes } from './common
|
|
6
|
-
|
|
6
|
+
import { reqParse, IReq, IRes } from './common';
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
// **** Variables **** //
|
|
10
|
+
|
|
11
|
+
const Validators = {
|
|
12
|
+
add: reqParse({ user: User.test }),
|
|
13
|
+
update: reqParse({ user: User.test }),
|
|
14
|
+
delete: reqParse({ id: transform(Number, isNum) }),
|
|
15
|
+
} as const;
|
|
7
16
|
|
|
8
17
|
|
|
9
18
|
// **** Functions **** //
|
|
@@ -20,7 +29,7 @@ async function getAll(_: IReq, res: IRes) {
|
|
|
20
29
|
* Add one user.
|
|
21
30
|
*/
|
|
22
31
|
async function add(req: IReq, res: IRes) {
|
|
23
|
-
const user =
|
|
32
|
+
const { user } = Validators.add(req.body);
|
|
24
33
|
await UserService.addOne(user);
|
|
25
34
|
res.status(HttpStatusCodes.CREATED).end();
|
|
26
35
|
}
|
|
@@ -29,7 +38,7 @@ async function add(req: IReq, res: IRes) {
|
|
|
29
38
|
* Update one user.
|
|
30
39
|
*/
|
|
31
40
|
async function update(req: IReq, res: IRes) {
|
|
32
|
-
const user =
|
|
41
|
+
const { user } = Validators.update(req.body);
|
|
33
42
|
await UserService.updateOne(user);
|
|
34
43
|
res.status(HttpStatusCodes.OK).end();
|
|
35
44
|
}
|
|
@@ -38,7 +47,7 @@ async function update(req: IReq, res: IRes) {
|
|
|
38
47
|
* Delete one user.
|
|
39
48
|
*/
|
|
40
49
|
async function delete_(req: IReq, res: IRes) {
|
|
41
|
-
const id =
|
|
50
|
+
const { id } = Validators.delete(req.params);
|
|
42
51
|
await UserService.delete(id);
|
|
43
52
|
res.status(HttpStatusCodes.OK).end();
|
|
44
53
|
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { Response, Request } from 'express';
|
|
2
|
+
|
|
3
|
+
import { parseObj, TSchema } from '@src/util/validators';
|
|
4
|
+
import { ValidationErr } from '@src/common/route-errors';
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
// **** Types **** //
|
|
8
|
+
|
|
9
|
+
type TObj = Record<string, unknown>;
|
|
10
|
+
export type IReq = Request<TObj, void, TObj, TObj>;
|
|
11
|
+
export type IRes = Response<unknown, TObj>;
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
// **** Functions **** //
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Parse a Request object property and throw a Validation error if it fails.
|
|
18
|
+
*/
|
|
19
|
+
export function reqParse<U extends TSchema>(schema: U) {
|
|
20
|
+
return parseObj<U>(schema, reqParseOnError);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Error handler for the request parse function above.
|
|
25
|
+
*/
|
|
26
|
+
function reqParseOnError(
|
|
27
|
+
prop = 'undefined',
|
|
28
|
+
value?: unknown,
|
|
29
|
+
caughtErr?: unknown,
|
|
30
|
+
): void {
|
|
31
|
+
if (caughtErr !== undefined) {
|
|
32
|
+
const moreInfo = JSON.stringify(caughtErr);
|
|
33
|
+
throw new ValidationErr(prop, value, moreInfo);
|
|
34
|
+
} else {
|
|
35
|
+
throw new ValidationErr(prop, value);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import cookieParser from 'cookie-parser';
|
|
2
1
|
import morgan from 'morgan';
|
|
3
2
|
import path from 'path';
|
|
4
3
|
import helmet from 'helmet';
|
|
@@ -9,11 +8,11 @@ import 'express-async-errors';
|
|
|
9
8
|
|
|
10
9
|
import BaseRouter from '@src/routes';
|
|
11
10
|
|
|
12
|
-
import Paths from '@src/common/Paths';
|
|
13
|
-
import
|
|
11
|
+
import Paths from '@src/routes/common/Paths';
|
|
12
|
+
import Env from '@src/common/Env';
|
|
14
13
|
import HttpStatusCodes from '@src/common/HttpStatusCodes';
|
|
15
|
-
import { RouteError } from '@src/common/
|
|
16
|
-
import { NodeEnvs } from '@src/common/
|
|
14
|
+
import { RouteError } from '@src/common/route-errors';
|
|
15
|
+
import { NodeEnvs } from '@src/common/constants';
|
|
17
16
|
|
|
18
17
|
|
|
19
18
|
// **** Variables **** //
|
|
@@ -26,15 +25,14 @@ const app = express();
|
|
|
26
25
|
// Basic middleware
|
|
27
26
|
app.use(express.json());
|
|
28
27
|
app.use(express.urlencoded({extended: true}));
|
|
29
|
-
app.use(cookieParser(EnvVars.CookieProps.Secret));
|
|
30
28
|
|
|
31
29
|
// Show routes called in console during development
|
|
32
|
-
if (
|
|
30
|
+
if (Env.NodeEnv === NodeEnvs.Dev.valueOf()) {
|
|
33
31
|
app.use(morgan('dev'));
|
|
34
32
|
}
|
|
35
33
|
|
|
36
34
|
// Security
|
|
37
|
-
if (
|
|
35
|
+
if (Env.NodeEnv === NodeEnvs.Production.valueOf()) {
|
|
38
36
|
app.use(helmet());
|
|
39
37
|
}
|
|
40
38
|
|
|
@@ -43,7 +41,7 @@ app.use(Paths.Base, BaseRouter);
|
|
|
43
41
|
|
|
44
42
|
// Add error handler
|
|
45
43
|
app.use((err: Error, _: Request, res: Response, next: NextFunction) => {
|
|
46
|
-
if (
|
|
44
|
+
if (Env.NodeEnv !== NodeEnvs.Test.valueOf()) {
|
|
47
45
|
logger.err(err, true);
|
|
48
46
|
}
|
|
49
47
|
let status = HttpStatusCodes.BAD_REQUEST;
|
|
@@ -1,22 +1,6 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Miscellaneous shared functions go here.
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
|
|
6
1
|
/**
|
|
7
2
|
* Get a random number between 1 and 1,000,000,000,000
|
|
8
3
|
*/
|
|
9
4
|
export function getRandomInt(): number {
|
|
10
5
|
return Math.floor(Math.random() * 1_000_000_000_000);
|
|
11
6
|
}
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
* Wait for a certain number of milliseconds.
|
|
15
|
-
*/
|
|
16
|
-
export function tick(milliseconds: number): Promise<void> {
|
|
17
|
-
return new Promise((resolve) => {
|
|
18
|
-
setTimeout(() => {
|
|
19
|
-
resolve();
|
|
20
|
-
}, milliseconds);
|
|
21
|
-
});
|
|
22
|
-
}
|