express-generator-typescript 2.2.5 → 2.2.7
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 +1 -1
- package/lib/project-files/build.ts +3 -1
- package/lib/project-files/package.json +1 -0
- package/lib/project-files/spec/tests/users.spec.ts +7 -8
- package/lib/project-files/src/models/User.ts +1 -1
- package/lib/project-files/src/routes/api.ts +4 -3
- package/lib/project-files/src/routes/{middlware → shared}/adminMw.ts +0 -0
- package/lib/project-files/tsconfig.json +2 -1
- package/lib/project-files/tsconfig.prod.json +2 -1
- package/package.json +1 -1
- package/lib/project-files/src/declarations/types.ts +0 -5
- package/lib/project-files/src/routes/middlware/validate.ts +0 -244
|
@@ -26,7 +26,7 @@ const ncpOpts = {
|
|
|
26
26
|
// Project-folder dependencies
|
|
27
27
|
const dependencies = 'express dotenv morgan cookie-parser jet-logger ' +
|
|
28
28
|
'module-alias command-line-args express-async-errors helmet jsonfile ' +
|
|
29
|
-
'bcrypt jsonwebtoken';
|
|
29
|
+
'bcrypt jsonwebtoken jet-validator';
|
|
30
30
|
|
|
31
31
|
// Project-folder development dependencies
|
|
32
32
|
const devDependencies = 'ts-node typescript nodemon find jasmine supertest ' +
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import supertest from 'supertest';
|
|
2
|
-
import {
|
|
1
|
+
import supertest, { SuperTest, Test, Response } from 'supertest';
|
|
2
|
+
import { defaultErrMsg } from 'jet-validator';
|
|
3
3
|
import logger from 'jet-logger';
|
|
4
4
|
|
|
5
5
|
import app from '@src/server';
|
|
@@ -8,7 +8,6 @@ import User, { IUser } from '@src/models/User';
|
|
|
8
8
|
import userRoutes from '@src/routes/user-routes';
|
|
9
9
|
import HttpStatusCodes from '@src/configurations/HttpStatusCodes';
|
|
10
10
|
import loginAgent from '../support/login-agent';
|
|
11
|
-
import { paramInvalidErr } from '@src/routes/middlware/validate';
|
|
12
11
|
import { userNotFoundErr } from '@src/services/user-service';
|
|
13
12
|
|
|
14
13
|
|
|
@@ -44,7 +43,7 @@ const msgs = {
|
|
|
44
43
|
addUserSuccess: 'should return a status code of ' +
|
|
45
44
|
`"${HttpStatusCodes.CREATED}" if the request was successful.`,
|
|
46
45
|
addUserFailedMissingParam: 'should return a JSON object with an error ' +
|
|
47
|
-
`message of "${
|
|
46
|
+
`message of "${defaultErrMsg}" and a status code of ` +
|
|
48
47
|
`"${HttpStatusCodes.BAD_REQUEST}" if the user param was missing.`,
|
|
49
48
|
addUserFallbackErr: 'should return a JSON object with an error message ' +
|
|
50
49
|
`and a status code of "${HttpStatusCodes.BAD_REQUEST}" if the request ` +
|
|
@@ -52,7 +51,7 @@ const msgs = {
|
|
|
52
51
|
updateSuccess: `should return a status code of "${HttpStatusCodes.OK}" if ` +
|
|
53
52
|
'the request was successful.',
|
|
54
53
|
updateParamMissing: 'should return a JSON object with an error message ' +
|
|
55
|
-
`of "${
|
|
54
|
+
`of "${defaultErrMsg}" and a status code of ` +
|
|
56
55
|
`"${HttpStatusCodes.BAD_REQUEST}" if the user param was missing.`,
|
|
57
56
|
updateUserNotFound: 'should return a JSON object with the error message ' +
|
|
58
57
|
`of "${userNotFoundErr}" and a status code of ` +
|
|
@@ -160,7 +159,7 @@ describe('user-router', () => {
|
|
|
160
159
|
.end((err: Error, res: Response) => {
|
|
161
160
|
!!err && logger.err(err);
|
|
162
161
|
expect(res.status).toBe(HttpStatusCodes.BAD_REQUEST);
|
|
163
|
-
expect(res.body.error).toBe(
|
|
162
|
+
expect(res.body.error).toBe(defaultErrMsg);
|
|
164
163
|
done();
|
|
165
164
|
});
|
|
166
165
|
});
|
|
@@ -208,7 +207,7 @@ describe('user-router', () => {
|
|
|
208
207
|
.end((err: Error, res: Response) => {
|
|
209
208
|
!!err && logger.err(err);
|
|
210
209
|
expect(res.status).toBe(HttpStatusCodes.BAD_REQUEST);
|
|
211
|
-
expect(res.body.error).toBe(
|
|
210
|
+
expect(res.body.error).toBe(defaultErrMsg);
|
|
212
211
|
done();
|
|
213
212
|
});
|
|
214
213
|
});
|
|
@@ -280,7 +279,7 @@ describe('user-router', () => {
|
|
|
280
279
|
.end((err: Error, res: Response) => {
|
|
281
280
|
!!err && logger.err(err);
|
|
282
281
|
expect(res.status).toBe(HttpStatusCodes.BAD_REQUEST);
|
|
283
|
-
expect(res.body.error).toBe(
|
|
282
|
+
expect(res.body.error).toBe(defaultErrMsg);
|
|
284
283
|
done();
|
|
285
284
|
});
|
|
286
285
|
});
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Router } from 'express';
|
|
2
|
+
import jetValidator from 'jet-validator';
|
|
2
3
|
|
|
3
|
-
import adminMw from './
|
|
4
|
-
import validate from './middlware/validate';
|
|
4
|
+
import adminMw from './shared/adminMw';
|
|
5
5
|
import User from '@src/models/User';
|
|
6
6
|
import authRoutes from './auth-routes';
|
|
7
7
|
import userRoutes from './user-routes';
|
|
@@ -9,7 +9,8 @@ import userRoutes from './user-routes';
|
|
|
9
9
|
|
|
10
10
|
// **** Init **** //
|
|
11
11
|
|
|
12
|
-
const apiRouter = Router()
|
|
12
|
+
const apiRouter = Router(),
|
|
13
|
+
validate = jetValidator();
|
|
13
14
|
|
|
14
15
|
|
|
15
16
|
// **** Setup auth routes **** //
|
|
File without changes
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "express-generator-typescript",
|
|
3
|
-
"version": "2.2.
|
|
3
|
+
"version": "2.2.7",
|
|
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,244 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* This function returns a middleware-function that validates the parameters
|
|
3
|
-
* provided. Each argument can be a string or array.
|
|
4
|
-
*
|
|
5
|
-
* If the argument is an array the format is:
|
|
6
|
-
* ['paramName', '(optional) type or validator function (default is string)',
|
|
7
|
-
* '(optional) property on "req" to extract the value from (default is body')]
|
|
8
|
-
*
|
|
9
|
-
* If a string, 'validate' makes sure the param is of type string on req.body.
|
|
10
|
-
* For the array, 'validate' makes sure the parameter is of the specified type
|
|
11
|
-
* or that the parameter satifies the validator function. The validator
|
|
12
|
-
* function must return 'true' or 'false'.
|
|
13
|
-
*
|
|
14
|
-
* **NOTE**: For numbers, strings which evalute to (!isNaN('string') => true)
|
|
15
|
-
* are valid for req.query and req.params. But on req.body a number should be
|
|
16
|
-
* 'typeof toCheck === "number"'
|
|
17
|
-
*
|
|
18
|
-
* **NOTE**: For booleans, on req.body must be true or false, on req.query or
|
|
19
|
-
* req.params must be 'true' or 'false'.
|
|
20
|
-
*
|
|
21
|
-
* Sample argument: ['id', 'number'], id is the incoming variable, 'number'
|
|
22
|
-
* is the type, and body is where to extract 'id' from.
|
|
23
|
-
*
|
|
24
|
-
* Example 1: validate('email', ['user', 'object'], ['id', 'number', 'params'])
|
|
25
|
-
* will check that 'email' is a string in req.body, that user is of type
|
|
26
|
-
* object in req.body, and that 'id' is a boolean in req.params.
|
|
27
|
-
* Example 2: validate('password') will check that 'password' is a string on
|
|
28
|
-
* req.body.
|
|
29
|
-
* Example 3: validate(['isAdmin', 'boolean']) will check that 'isAdmin' is a
|
|
30
|
-
* boolean on req.body
|
|
31
|
-
* Example 4: validate(['user', isInstanceOfUser]) will check that 'user'
|
|
32
|
-
* satifies the 'isInstanceOfUser()' function.
|
|
33
|
-
* Example 5: validate(['email']) will check that 'email' is a string in
|
|
34
|
-
* req.body,
|
|
35
|
-
*/
|
|
36
|
-
|
|
37
|
-
import { Request, Response, NextFunction, RequestHandler } from 'express';
|
|
38
|
-
|
|
39
|
-
import HttpStatusCodes from '@src/configurations/HttpStatusCodes';
|
|
40
|
-
import { TAll } from '@src/declarations/types';
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
// **** Variables **** //
|
|
44
|
-
|
|
45
|
-
export const paramInvalidErr = 'One or more of the required params was ' +
|
|
46
|
-
'missing or invalid.';
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
// **** Types **** //
|
|
50
|
-
|
|
51
|
-
type TLoopFn = (req: Request) => boolean;
|
|
52
|
-
type TValidatorFn = ((arg: TAll) => boolean);
|
|
53
|
-
type TReqObjProps = 'body' | 'query' | 'params';
|
|
54
|
-
|
|
55
|
-
type TParamArr = {
|
|
56
|
-
0: string,
|
|
57
|
-
1?: string | TValidatorFn,
|
|
58
|
-
2?: TReqObjProps,
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
interface IParamFields {
|
|
62
|
-
paramName: string;
|
|
63
|
-
type: string;
|
|
64
|
-
reqObjProp: TReqObjProps;
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
// **** Functions **** //
|
|
69
|
-
|
|
70
|
-
/**
|
|
71
|
-
* See comments at beginning of file on usage.
|
|
72
|
-
*/
|
|
73
|
-
function validate(...params: Array<string | TParamArr>): RequestHandler {
|
|
74
|
-
// Setup loop-function array
|
|
75
|
-
const loopFns: TLoopFn[] = [];
|
|
76
|
-
for (const param of params) {
|
|
77
|
-
const { paramName, type, reqObjProp } = getParamFields(param);
|
|
78
|
-
let loopFn: TLoopFn = () => false;
|
|
79
|
-
if (type === 'string') {
|
|
80
|
-
loopFn = checkStr(reqObjProp, paramName);
|
|
81
|
-
} else if (type === 'number') {
|
|
82
|
-
loopFn = checkNum(reqObjProp, paramName);
|
|
83
|
-
} else if (type === 'boolean') {
|
|
84
|
-
loopFn = checkBool(reqObjProp, paramName);
|
|
85
|
-
} else if (type === 'function') {
|
|
86
|
-
const fn = param[1] as TValidatorFn;
|
|
87
|
-
loopFn = checkValidatorFn(reqObjProp, paramName, fn);
|
|
88
|
-
} else {
|
|
89
|
-
loopFn = checkDefault(reqObjProp, paramName, type);
|
|
90
|
-
}
|
|
91
|
-
loopFns.push(loopFn);
|
|
92
|
-
}
|
|
93
|
-
// Return middlware function
|
|
94
|
-
return (req: Request, res: Response, next: NextFunction) => {
|
|
95
|
-
for (const loopFn of loopFns) {
|
|
96
|
-
if (!loopFn(req)) {
|
|
97
|
-
return res
|
|
98
|
-
.status(HttpStatusCodes.BAD_REQUEST)
|
|
99
|
-
.json({ error: paramInvalidErr });
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
return next();
|
|
103
|
-
};
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
/**
|
|
107
|
-
* Get the param name, type to check against, and the request object property
|
|
108
|
-
* as well as validating the format of the param.
|
|
109
|
-
*/
|
|
110
|
-
function getParamFields(param: string | TParamArr): IParamFields {
|
|
111
|
-
let paramName = '';
|
|
112
|
-
let type = 'string';
|
|
113
|
-
let reqObjProp: TReqObjProps = 'body';
|
|
114
|
-
// Param is string
|
|
115
|
-
if (typeof param === 'string') {
|
|
116
|
-
paramName = param;
|
|
117
|
-
// Param is array
|
|
118
|
-
} else if (param instanceof Array) {
|
|
119
|
-
// Get the param name
|
|
120
|
-
paramName = param[0];
|
|
121
|
-
if (typeof paramName !== 'string') {
|
|
122
|
-
throw Error('param name must be a string');
|
|
123
|
-
}
|
|
124
|
-
// Get the type
|
|
125
|
-
if (typeof param[1] === 'string') {
|
|
126
|
-
type = param[1];
|
|
127
|
-
} else if (typeof param[1] === 'function') {
|
|
128
|
-
type = 'function';
|
|
129
|
-
} else {
|
|
130
|
-
throw Error('param[1] must be a string or a validator function');
|
|
131
|
-
}
|
|
132
|
-
// Get the request object property
|
|
133
|
-
const prop = (param.length >= 3 ? param[2] : 'body');
|
|
134
|
-
if (prop !== 'body' && prop !== 'params' && prop !== 'query') {
|
|
135
|
-
throw Error('param[2] must be "body", "query", or "params"');
|
|
136
|
-
} else {
|
|
137
|
-
reqObjProp = prop;
|
|
138
|
-
}
|
|
139
|
-
// Throw error if not string or array
|
|
140
|
-
} else {
|
|
141
|
-
throw Error('"validate()" argument must be a string or array');
|
|
142
|
-
}
|
|
143
|
-
// Return
|
|
144
|
-
return { paramName, type, reqObjProp };
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
/**
|
|
148
|
-
* Check param is a valid string.
|
|
149
|
-
*/
|
|
150
|
-
function checkStr(reqObjProp: TReqObjProps, paramName: string): TLoopFn {
|
|
151
|
-
return getLoopFn(reqObjProp, paramName, (toCheck) => {
|
|
152
|
-
return (typeof toCheck === 'string');
|
|
153
|
-
});
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
/**
|
|
157
|
-
* Check param is a valid number. See notes at beginning of file.
|
|
158
|
-
*/
|
|
159
|
-
function checkNum(reqObjProp: TReqObjProps, paramName: string): TLoopFn {
|
|
160
|
-
return getLoopFn(reqObjProp, paramName, (toCheck) => {
|
|
161
|
-
if (reqObjProp === 'query' || reqObjProp === 'params') {
|
|
162
|
-
return !isNaN(toCheck as number);
|
|
163
|
-
} else if (reqObjProp === 'body' && typeof toCheck !== 'number') {
|
|
164
|
-
return false;
|
|
165
|
-
} else {
|
|
166
|
-
return true;
|
|
167
|
-
}
|
|
168
|
-
});
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
/**
|
|
172
|
-
* Check param is a valid boolean. See notes at beginning of file.
|
|
173
|
-
*/
|
|
174
|
-
function checkBool(reqObjProp: TReqObjProps, paramName: string): TLoopFn {
|
|
175
|
-
return getLoopFn(reqObjProp, paramName, (toCheck) => {
|
|
176
|
-
if (reqObjProp === 'query' || reqObjProp === 'params') {
|
|
177
|
-
return isBool(toCheck as boolean);
|
|
178
|
-
} else if (reqObjProp === 'body' && typeof toCheck !== 'boolean') {
|
|
179
|
-
return false;
|
|
180
|
-
} else {
|
|
181
|
-
return true;
|
|
182
|
-
}
|
|
183
|
-
});
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
/**
|
|
187
|
-
* Checks if arg is a boolean, or a string that is 'true', or 'false'.
|
|
188
|
-
*/
|
|
189
|
-
function isBool(arg: string | boolean): boolean {
|
|
190
|
-
if (typeof arg === 'boolean') {
|
|
191
|
-
return true;
|
|
192
|
-
} else if (typeof arg === 'string') {
|
|
193
|
-
arg = arg.toLowerCase();
|
|
194
|
-
return (arg === 'true' || arg === 'false');
|
|
195
|
-
} else {
|
|
196
|
-
return false;
|
|
197
|
-
}
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
/**
|
|
201
|
-
* Make sure the parameter satifies the supplied validator function.
|
|
202
|
-
*/
|
|
203
|
-
function checkValidatorFn(
|
|
204
|
-
reqObjProp: TReqObjProps,
|
|
205
|
-
paramName: string,
|
|
206
|
-
validatorFn: TValidatorFn,
|
|
207
|
-
) {
|
|
208
|
-
return getLoopFn(reqObjProp, paramName, (toCheck) => {
|
|
209
|
-
return validatorFn(toCheck);
|
|
210
|
-
});
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
/**
|
|
214
|
-
* For all other type make sure the param equals the type.
|
|
215
|
-
*/
|
|
216
|
-
function checkDefault(
|
|
217
|
-
reqObjProp: TReqObjProps,
|
|
218
|
-
paramName: string,
|
|
219
|
-
type: string,
|
|
220
|
-
): TLoopFn {
|
|
221
|
-
return getLoopFn(reqObjProp, paramName, (toCheck) => {
|
|
222
|
-
return (toCheck === type);
|
|
223
|
-
});
|
|
224
|
-
}
|
|
225
|
-
|
|
226
|
-
/**
|
|
227
|
-
* Extract the value to check and get the loop function.
|
|
228
|
-
*/
|
|
229
|
-
function getLoopFn(
|
|
230
|
-
reqObjProp: TReqObjProps,
|
|
231
|
-
paramName: string,
|
|
232
|
-
cb: (toCheck: TAll) => boolean,
|
|
233
|
-
): TLoopFn {
|
|
234
|
-
return (req: Request) => {
|
|
235
|
-
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
|
236
|
-
const toCheck = req[reqObjProp][paramName] as TAll;
|
|
237
|
-
return cb(toCheck);
|
|
238
|
-
};
|
|
239
|
-
}
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
// **** Export Default **** //
|
|
243
|
-
|
|
244
|
-
export default validate;
|