express-generator-typescript 2.5.12 → 2.5.15
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/project-files/package.json +1 -1
- package/lib/project-files/spec/support/index.ts +21 -13
- package/lib/project-files/spec/tests/users.spec.ts +88 -107
- package/lib/project-files/src/common/route-errors.ts +8 -24
- package/lib/project-files/src/index.ts +3 -3
- package/lib/project-files/src/repos/MockOrm.ts +7 -1
- package/lib/project-files/src/repos/UserRepo.ts +33 -0
- package/lib/project-files/src/repos/database.test.json +1 -0
- package/lib/project-files/src/routes/common/index.ts +33 -19
- package/lib/project-files/src/server.ts +4 -4
- package/lib/project-files/src/util/misc.ts +1 -0
- package/package.json +1 -1
- package/lib/project-files/spec/types/misc.ts +0 -13
- package/lib/project-files/spec/types/supertest/index.d.ts +0 -14
- /package/lib/project-files/src/common/{Env.ts → ENV.ts} +0 -0
|
@@ -1,18 +1,26 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import
|
|
1
|
+
import { IReqPropErr } from '@src/routes/common';
|
|
2
|
+
import UserRepo from '@src/repos/UserRepo';
|
|
3
3
|
|
|
4
4
|
|
|
5
|
+
/******************************************************************************
|
|
6
|
+
Types
|
|
7
|
+
******************************************************************************/
|
|
8
|
+
|
|
9
|
+
export interface IValidationErr {
|
|
10
|
+
message: string;
|
|
11
|
+
parameters: IReqPropErr[];
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
/******************************************************************************
|
|
16
|
+
Functions
|
|
17
|
+
******************************************************************************/
|
|
18
|
+
|
|
5
19
|
/**
|
|
6
|
-
*
|
|
7
|
-
* tests to pass we need to convert them back to date objects.
|
|
20
|
+
* Delete all records for unit testing.
|
|
8
21
|
*/
|
|
9
|
-
export function
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
return traverseObject((prop, value, parentObj) => {
|
|
14
|
-
if (toConvert.includes(prop) && isValidDate(value)) {
|
|
15
|
-
parentObj[prop] = new Date(value);
|
|
16
|
-
}
|
|
17
|
-
});
|
|
22
|
+
export async function cleanDatabase(): Promise<void> {
|
|
23
|
+
await Promise.all([
|
|
24
|
+
UserRepo.deleteAllUsers(),
|
|
25
|
+
]);
|
|
18
26
|
}
|
|
@@ -1,8 +1,6 @@
|
|
|
1
|
-
import supertest
|
|
2
|
-
import TestAgent from 'supertest/lib/agent';
|
|
1
|
+
import supertest from 'supertest';
|
|
3
2
|
import insertUrlParams from 'inserturlparams';
|
|
4
|
-
import { parseJson } from 'jet-validators/utils';
|
|
5
|
-
import logger from 'jet-logger';
|
|
3
|
+
import { parseJson, customDeepCompare } from 'jet-validators/utils';
|
|
6
4
|
|
|
7
5
|
import app from '@src/server';
|
|
8
6
|
|
|
@@ -11,191 +9,174 @@ import User, { IUser } from '@src/models/User';
|
|
|
11
9
|
import { USER_NOT_FOUND_ERR } from '@src/services/UserService';
|
|
12
10
|
|
|
13
11
|
import HttpStatusCodes from '@src/common/HttpStatusCodes';
|
|
14
|
-
import {
|
|
12
|
+
import { ValidationErr } from '@src/common/route-errors';
|
|
15
13
|
|
|
16
14
|
import Paths from 'spec/support/Paths';
|
|
17
|
-
import {
|
|
18
|
-
import { TApiCb, TRes } from 'spec/types/misc';
|
|
15
|
+
import { cleanDatabase, IValidationErr } from 'spec/support';
|
|
19
16
|
|
|
20
17
|
|
|
21
18
|
/******************************************************************************
|
|
22
|
-
|
|
19
|
+
Variables
|
|
23
20
|
******************************************************************************/
|
|
24
21
|
|
|
25
22
|
// Dummy users for GET req
|
|
26
|
-
const
|
|
23
|
+
const DB_USERS = [
|
|
27
24
|
User.new({ name: 'Sean Maxwell', email: 'sean.maxwell@gmail.com' }),
|
|
28
25
|
User.new({ name: 'John Smith', email: 'john.smith@gmail.com' }),
|
|
29
26
|
User.new({ name: 'Gordan Freeman', email: 'gordan.freeman@gmail.com' }),
|
|
30
|
-
];
|
|
27
|
+
] as const;
|
|
31
28
|
|
|
32
|
-
//
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
if (!!err) {
|
|
38
|
-
logger.err(err);
|
|
39
|
-
}
|
|
40
|
-
createdKeyToDate(res.body);
|
|
41
|
-
return cb(res);
|
|
42
|
-
};
|
|
29
|
+
// Don't compare "id" and "created" cause those are set dynamically by the
|
|
30
|
+
// database
|
|
31
|
+
const compareUserArrays = customDeepCompare({
|
|
32
|
+
onlyCompareProps: ['name', 'email'],
|
|
33
|
+
})
|
|
43
34
|
|
|
44
35
|
|
|
45
36
|
/******************************************************************************
|
|
46
37
|
Tests
|
|
38
|
+
IMPORTANT: Following TypeScript best practices, we test all scenarios that
|
|
39
|
+
can be triggered by a user under normal circumstances. Not all theoretically
|
|
40
|
+
scenarios (i.e. a failed database connection).
|
|
47
41
|
******************************************************************************/
|
|
48
42
|
|
|
49
43
|
describe('UserRouter', () => {
|
|
50
44
|
|
|
51
|
-
|
|
45
|
+
const agent = supertest.agent(app);
|
|
46
|
+
let dbUsers: IUser[] = [];
|
|
52
47
|
|
|
53
48
|
// Run before all tests
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
49
|
+
beforeEach(async () => {
|
|
50
|
+
await cleanDatabase();
|
|
51
|
+
dbUsers = await UserRepo.insertMult(DB_USERS);
|
|
57
52
|
});
|
|
58
53
|
|
|
59
54
|
// Get all users
|
|
60
55
|
describe(`"GET:${Paths.Users.Get}"`, () => {
|
|
61
56
|
|
|
62
|
-
// Setup API
|
|
63
|
-
const api = (cb: TApiCb) =>
|
|
64
|
-
agent
|
|
65
|
-
.get(Paths.Users.Get)
|
|
66
|
-
.end(wrapCb(cb));
|
|
67
|
-
|
|
68
57
|
// Success
|
|
69
58
|
it('should return a JSON object with all the users and a status code ' +
|
|
70
59
|
`of "${HttpStatusCodes.OK}" if the request was successful.`, done => {
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
done();
|
|
79
|
-
});
|
|
60
|
+
agent
|
|
61
|
+
.get(Paths.Users.Get)
|
|
62
|
+
.end((_, res) => {
|
|
63
|
+
expect(res.status).toBe(HttpStatusCodes.OK);
|
|
64
|
+
expect(compareUserArrays(res.body.users, DB_USERS)).toBeTruthy();
|
|
65
|
+
done();
|
|
66
|
+
});
|
|
80
67
|
});
|
|
81
68
|
});
|
|
82
69
|
|
|
83
70
|
// Test add user
|
|
84
71
|
describe(`"POST:${Paths.Users.Add}"`, () => {
|
|
85
72
|
|
|
86
|
-
const DUMMY_USER = getDummyUsers()[0];
|
|
87
|
-
|
|
88
|
-
// Setup API
|
|
89
|
-
const callApi = (user: IUser | null, cb: TApiCb) =>
|
|
90
|
-
agent
|
|
91
|
-
.post(Paths.Users.Add)
|
|
92
|
-
.send({ user })
|
|
93
|
-
.end(wrapCb(cb));
|
|
94
|
-
|
|
95
73
|
// Test add user success
|
|
96
74
|
it(`should return a status code of "${HttpStatusCodes.CREATED}" if the ` +
|
|
97
75
|
'request was successful.', done => {
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
76
|
+
const user = User.new({ name: 'a', email: 'a@a.com' });
|
|
77
|
+
agent
|
|
78
|
+
.post(Paths.Users.Add)
|
|
79
|
+
.send({ user })
|
|
80
|
+
.end((_, res) => {
|
|
81
|
+
expect(res.status).toBe(HttpStatusCodes.CREATED);
|
|
82
|
+
done();
|
|
83
|
+
});
|
|
105
84
|
});
|
|
106
85
|
|
|
107
86
|
// Missing param
|
|
108
87
|
it('should return a JSON object with an error message of and a status ' +
|
|
109
88
|
`code of "${HttpStatusCodes.BAD_REQUEST}" if the user param was ` +
|
|
110
89
|
'missing.', done => {
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
90
|
+
agent
|
|
91
|
+
.post(Paths.Users.Add)
|
|
92
|
+
.send({ user: null })
|
|
93
|
+
.end((_, res) => {
|
|
94
|
+
expect(res.status).toBe(HttpStatusCodes.BAD_REQUEST);
|
|
95
|
+
const errorObj = parseJson<IValidationErr>(res.body.error);
|
|
96
|
+
expect(errorObj.message).toBe(ValidationErr.MSG);
|
|
97
|
+
expect(errorObj.parameters[0].prop).toBe('user');
|
|
98
|
+
done();
|
|
99
|
+
});
|
|
119
100
|
});
|
|
120
101
|
});
|
|
121
102
|
|
|
122
103
|
// Update users
|
|
123
104
|
describe(`"PUT:${Paths.Users.Update}"`, () => {
|
|
124
105
|
|
|
125
|
-
const DUMMY_USER = getDummyUsers()[0];
|
|
126
|
-
|
|
127
|
-
// Setup API
|
|
128
|
-
const callApi = (user: IUser | null, cb: TApiCb) =>
|
|
129
|
-
agent
|
|
130
|
-
.put(Paths.Users.Update)
|
|
131
|
-
.send({ user })
|
|
132
|
-
.end(wrapCb(cb));
|
|
133
|
-
|
|
134
106
|
// Success
|
|
135
107
|
it(`should return a status code of "${HttpStatusCodes.OK}" if the ` +
|
|
136
108
|
'request was successful.', done => {
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
109
|
+
const user = DB_USERS[0];
|
|
110
|
+
user.name = 'Bill';
|
|
111
|
+
agent
|
|
112
|
+
.put(Paths.Users.Update)
|
|
113
|
+
.send({ user })
|
|
114
|
+
.end((_, res) => {
|
|
115
|
+
expect(res.status).toBe(HttpStatusCodes.OK);
|
|
116
|
+
done();
|
|
117
|
+
});
|
|
143
118
|
});
|
|
144
119
|
|
|
145
120
|
// Param missing
|
|
146
121
|
it('should return a JSON object with an error message and a status code ' +
|
|
147
122
|
`of "${HttpStatusCodes.BAD_REQUEST}" if the user param was missing`,
|
|
148
123
|
done => {
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
124
|
+
agent
|
|
125
|
+
.put(Paths.Users.Update)
|
|
126
|
+
.send({ user: null })
|
|
127
|
+
.end((_, res) => {
|
|
128
|
+
expect(res.status).toBe(HttpStatusCodes.BAD_REQUEST);
|
|
129
|
+
const errorObj = parseJson<IValidationErr>(res.body.error);
|
|
130
|
+
expect(errorObj.message).toBe(ValidationErr.MSG);
|
|
131
|
+
expect(errorObj.parameters[0].prop).toBe('user');
|
|
132
|
+
done();
|
|
133
|
+
});
|
|
156
134
|
});
|
|
157
135
|
|
|
158
136
|
// User not found
|
|
159
137
|
it('should return a JSON object with the error message of ' +
|
|
160
138
|
`"${USER_NOT_FOUND_ERR}" and a status code of ` +
|
|
161
139
|
`"${HttpStatusCodes.NOT_FOUND}" if the id was not found.`, done => {
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
140
|
+
const user = User.new({ id: 4, name: 'a', email: 'a@a.com' });
|
|
141
|
+
agent
|
|
142
|
+
.put(Paths.Users.Update)
|
|
143
|
+
.send({ user })
|
|
144
|
+
.end((_, res) => {
|
|
145
|
+
expect(res.status).toBe(HttpStatusCodes.NOT_FOUND);
|
|
146
|
+
expect(res.body.error).toBe(USER_NOT_FOUND_ERR);
|
|
147
|
+
done();
|
|
148
|
+
});
|
|
167
149
|
});
|
|
168
150
|
});
|
|
169
151
|
|
|
170
152
|
// Delete User
|
|
171
153
|
describe(`"DELETE:${Paths.Users.Delete}"`, () => {
|
|
172
154
|
|
|
173
|
-
|
|
174
|
-
const callApi = (id: number, cb: TApiCb) =>
|
|
175
|
-
agent
|
|
176
|
-
.delete(insertUrlParams(Paths.Users.Delete, { id }))
|
|
177
|
-
.end(wrapCb(cb));
|
|
155
|
+
const getPath = (id: number) => insertUrlParams(Paths.Users.Delete, { id });
|
|
178
156
|
|
|
179
157
|
// Success
|
|
180
158
|
it(`should return a status code of "${HttpStatusCodes.OK}" if the ` +
|
|
181
159
|
'request was successful.', done => {
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
160
|
+
const id = dbUsers[0].id;
|
|
161
|
+
agent
|
|
162
|
+
.delete(getPath(id))
|
|
163
|
+
.end((_, res) => {
|
|
164
|
+
expect(res.status).toBe(HttpStatusCodes.OK);
|
|
165
|
+
done();
|
|
166
|
+
});
|
|
188
167
|
});
|
|
189
168
|
|
|
190
169
|
// User not found
|
|
191
170
|
it('should return a JSON object with the error message of ' +
|
|
192
171
|
`"${USER_NOT_FOUND_ERR}" and a status code of ` +
|
|
193
172
|
`"${HttpStatusCodes.NOT_FOUND}" if the id was not found.`, done => {
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
173
|
+
agent
|
|
174
|
+
.delete(getPath(-1))
|
|
175
|
+
.end((_, res) => {
|
|
176
|
+
expect(res.status).toBe(HttpStatusCodes.NOT_FOUND);
|
|
177
|
+
expect(res.body.error).toBe(USER_NOT_FOUND_ERR);
|
|
178
|
+
done();
|
|
179
|
+
});
|
|
199
180
|
});
|
|
200
181
|
});
|
|
201
182
|
});
|
|
@@ -1,18 +1,6 @@
|
|
|
1
1
|
import HttpStatusCodes from '@src/common/HttpStatusCodes';
|
|
2
2
|
|
|
3
3
|
|
|
4
|
-
/******************************************************************************
|
|
5
|
-
Types
|
|
6
|
-
******************************************************************************/
|
|
7
|
-
|
|
8
|
-
export interface IValidationErrFormat {
|
|
9
|
-
error: string;
|
|
10
|
-
parameter: string;
|
|
11
|
-
value?: unknown;
|
|
12
|
-
'more-info'?: string;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
|
|
16
4
|
/******************************************************************************
|
|
17
5
|
Classes
|
|
18
6
|
******************************************************************************/
|
|
@@ -33,17 +21,13 @@ export class RouteError extends Error {
|
|
|
33
21
|
* Validation in route layer errors.
|
|
34
22
|
*/
|
|
35
23
|
export class ValidationErr extends RouteError {
|
|
36
|
-
public static MSG = '
|
|
37
|
-
|
|
38
|
-
public constructor(
|
|
39
|
-
const
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
if (!!moreInfo) {
|
|
45
|
-
msgObj['more-info'] = moreInfo;
|
|
46
|
-
}
|
|
47
|
-
super(HttpStatusCodes.BAD_REQUEST, JSON.stringify(msgObj));
|
|
24
|
+
public static MSG = 'One or more parameters were missing or invalid.';
|
|
25
|
+
|
|
26
|
+
public constructor(errObj: unknown) {
|
|
27
|
+
const msg = JSON.stringify({
|
|
28
|
+
message: ValidationErr.MSG,
|
|
29
|
+
parameters: errObj,
|
|
30
|
+
});
|
|
31
|
+
super(HttpStatusCodes.BAD_REQUEST, msg);
|
|
48
32
|
}
|
|
49
33
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
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
|
|
|
@@ -9,6 +9,6 @@ import server from './server';
|
|
|
9
9
|
******************************************************************************/
|
|
10
10
|
|
|
11
11
|
const SERVER_START_MSG = ('Express server started on port: ' +
|
|
12
|
-
|
|
12
|
+
ENV.Port.toString());
|
|
13
13
|
|
|
14
|
-
server.listen(
|
|
14
|
+
server.listen(ENV.Port, () => logger.info(SERVER_START_MSG));
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import jsonfile from 'jsonfile';
|
|
2
2
|
|
|
3
|
+
import ENV from '@src/common/ENV';
|
|
4
|
+
import { NodeEnvs } from '@src/common/constants';
|
|
3
5
|
import { IUser } from '@src/models/User';
|
|
4
6
|
|
|
5
7
|
|
|
@@ -7,7 +9,11 @@ import { IUser } from '@src/models/User';
|
|
|
7
9
|
Variables
|
|
8
10
|
******************************************************************************/
|
|
9
11
|
|
|
10
|
-
const DB_FILE_NAME =
|
|
12
|
+
const DB_FILE_NAME = (
|
|
13
|
+
ENV.NodeEnv === NodeEnvs.Test
|
|
14
|
+
? 'database.test.json'
|
|
15
|
+
: 'database.json'
|
|
16
|
+
);
|
|
11
17
|
|
|
12
18
|
|
|
13
19
|
/******************************************************************************
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { IUser } from '@src/models/User';
|
|
2
2
|
import { getRandomInt } from '@src/util/misc';
|
|
3
|
+
|
|
3
4
|
import orm from './MockOrm';
|
|
4
5
|
|
|
5
6
|
|
|
@@ -83,6 +84,36 @@ async function delete_(id: number): Promise<void> {
|
|
|
83
84
|
}
|
|
84
85
|
|
|
85
86
|
|
|
87
|
+
// **** Unit-Tests Only **** //
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Delete every user record.
|
|
91
|
+
*/
|
|
92
|
+
async function deleteAllUsers(): Promise<void> {
|
|
93
|
+
const db = await orm.openDb();
|
|
94
|
+
db.users = [];
|
|
95
|
+
return orm.saveDb(db);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Insert multiple users. Can't do multiple at once cause using a plain file
|
|
100
|
+
* for nmow.
|
|
101
|
+
*/
|
|
102
|
+
async function insertMult(
|
|
103
|
+
users: IUser[] | readonly IUser[],
|
|
104
|
+
): Promise<IUser[]> {
|
|
105
|
+
const db = await orm.openDb(),
|
|
106
|
+
usersF = [ ...users ];
|
|
107
|
+
for (const user of usersF) {
|
|
108
|
+
user.id = getRandomInt();
|
|
109
|
+
user.created = new Date();
|
|
110
|
+
}
|
|
111
|
+
db.users = [ ...db.users, ...users ];
|
|
112
|
+
await orm.saveDb(db);
|
|
113
|
+
return usersF;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
|
|
86
117
|
/******************************************************************************
|
|
87
118
|
Export default
|
|
88
119
|
******************************************************************************/
|
|
@@ -94,4 +125,6 @@ export default {
|
|
|
94
125
|
add,
|
|
95
126
|
update,
|
|
96
127
|
delete: delete_,
|
|
128
|
+
deleteAllUsers,
|
|
129
|
+
insertMult,
|
|
97
130
|
} as const;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"users":[{"id":697609403164,"name":"Bill","created":"2025-02-13T19:25:15.288Z","email":"sean.maxwell@gmail.com"},{"id":387041929717,"name":"John Smith","created":"2025-02-13T19:25:15.288Z","email":"john.smith@gmail.com"},{"id":465077000925,"name":"Gordan Freeman","created":"2025-02-13T19:25:15.288Z","email":"gordan.freeman@gmail.com"}]}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Response, Request } from 'express';
|
|
2
|
-
import { isObject } from 'jet-validators';
|
|
2
|
+
import { isObject, isString } from 'jet-validators';
|
|
3
3
|
import { parseObject, TSchema } from 'jet-validators/utils';
|
|
4
4
|
|
|
5
5
|
import { ValidationErr } from '@src/common/route-errors';
|
|
@@ -13,6 +13,12 @@ type TRecord = Record<string, unknown>;
|
|
|
13
13
|
export type IReq = Request<TRecord, void, TRecord, TRecord>;
|
|
14
14
|
export type IRes = Response<unknown, TRecord>;
|
|
15
15
|
|
|
16
|
+
export interface IReqPropErr {
|
|
17
|
+
prop: string;
|
|
18
|
+
value: unknown;
|
|
19
|
+
moreInfo?: string;
|
|
20
|
+
}
|
|
21
|
+
|
|
16
22
|
|
|
17
23
|
/******************************************************************************
|
|
18
24
|
Functions
|
|
@@ -22,27 +28,35 @@ export type IRes = Response<unknown, TRecord>;
|
|
|
22
28
|
* Parse a Request object property and throw a Validation error if it fails.
|
|
23
29
|
*/
|
|
24
30
|
export function parseReq<U extends TSchema>(schema: U) {
|
|
25
|
-
const parseFn = parseObject<U>(schema, _parseReqOnError);
|
|
26
31
|
return (arg: unknown) => {
|
|
32
|
+
// Don't alter original object
|
|
27
33
|
if (isObject(arg)) {
|
|
28
34
|
arg = { ...arg };
|
|
29
35
|
}
|
|
30
|
-
|
|
36
|
+
// Error callback
|
|
37
|
+
const errArr: IReqPropErr[] = [];
|
|
38
|
+
const errCb = (
|
|
39
|
+
prop = 'undefined',
|
|
40
|
+
value?: unknown,
|
|
41
|
+
caughtErr?: unknown,
|
|
42
|
+
) => {
|
|
43
|
+
const err: IReqPropErr = { prop, value };
|
|
44
|
+
if (caughtErr !== undefined) {
|
|
45
|
+
let moreInfo;
|
|
46
|
+
if (!isString(caughtErr)) {
|
|
47
|
+
moreInfo = JSON.stringify(caughtErr);
|
|
48
|
+
} else {
|
|
49
|
+
moreInfo = caughtErr;
|
|
50
|
+
}
|
|
51
|
+
err.moreInfo = moreInfo;
|
|
52
|
+
}
|
|
53
|
+
errArr.push(err);
|
|
54
|
+
};
|
|
55
|
+
// Return
|
|
56
|
+
const retVal = parseObject<U>(schema, errCb)(arg);
|
|
57
|
+
if (errArr.length > 0) {
|
|
58
|
+
throw new ValidationErr(errArr);
|
|
59
|
+
}
|
|
60
|
+
return retVal;
|
|
31
61
|
};
|
|
32
62
|
}
|
|
33
|
-
|
|
34
|
-
/**
|
|
35
|
-
* Error handler for the request parse function above.
|
|
36
|
-
*/
|
|
37
|
-
function _parseReqOnError(
|
|
38
|
-
prop = 'undefined',
|
|
39
|
-
value?: unknown,
|
|
40
|
-
caughtErr?: unknown,
|
|
41
|
-
): void {
|
|
42
|
-
if (caughtErr !== undefined) {
|
|
43
|
-
const moreInfo = JSON.stringify(caughtErr);
|
|
44
|
-
throw new ValidationErr(prop, value, moreInfo);
|
|
45
|
-
} else {
|
|
46
|
-
throw new ValidationErr(prop, value);
|
|
47
|
-
}
|
|
48
|
-
}
|
|
@@ -9,7 +9,7 @@ import 'express-async-errors';
|
|
|
9
9
|
import BaseRouter from '@src/routes';
|
|
10
10
|
|
|
11
11
|
import Paths from '@src/routes/common/Paths';
|
|
12
|
-
import
|
|
12
|
+
import ENV from '@src/common/ENV';
|
|
13
13
|
import HttpStatusCodes from '@src/common/HttpStatusCodes';
|
|
14
14
|
import { RouteError } from '@src/common/route-errors';
|
|
15
15
|
import { NodeEnvs } from '@src/common/constants';
|
|
@@ -29,12 +29,12 @@ app.use(express.json());
|
|
|
29
29
|
app.use(express.urlencoded({extended: true}));
|
|
30
30
|
|
|
31
31
|
// Show routes called in console during development
|
|
32
|
-
if (
|
|
32
|
+
if (ENV.NodeEnv === NodeEnvs.Dev.valueOf()) {
|
|
33
33
|
app.use(morgan('dev'));
|
|
34
34
|
}
|
|
35
35
|
|
|
36
36
|
// Security
|
|
37
|
-
if (
|
|
37
|
+
if (ENV.NodeEnv === NodeEnvs.Production.valueOf()) {
|
|
38
38
|
app.use(helmet());
|
|
39
39
|
}
|
|
40
40
|
|
|
@@ -43,7 +43,7 @@ app.use(Paths.Base, BaseRouter);
|
|
|
43
43
|
|
|
44
44
|
// Add error handler
|
|
45
45
|
app.use((err: Error, _: Request, res: Response, next: NextFunction) => {
|
|
46
|
-
if (
|
|
46
|
+
if (ENV.NodeEnv !== NodeEnvs.Test.valueOf()) {
|
|
47
47
|
logger.err(err, true);
|
|
48
48
|
}
|
|
49
49
|
let status = HttpStatusCodes.BAD_REQUEST;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "express-generator-typescript",
|
|
3
|
-
"version": "2.5.
|
|
3
|
+
"version": "2.5.15",
|
|
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,13 +0,0 @@
|
|
|
1
|
-
import { Response } from 'supertest';
|
|
2
|
-
import { IUser } from '@src/models/User';
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
// Misc
|
|
6
|
-
export type TRes = Omit<Response, 'body'> & {
|
|
7
|
-
body: {
|
|
8
|
-
error?: string,
|
|
9
|
-
user?: IUser,
|
|
10
|
-
users?: IUser[],
|
|
11
|
-
},
|
|
12
|
-
};
|
|
13
|
-
export type TApiCb = (res: TRes) => void;
|
|
File without changes
|