express-generator-typescript 2.5.15 → 2.5.16
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/Paths.ts +1 -1
- package/lib/project-files/spec/support/index.ts +13 -2
- package/lib/project-files/spec/tests/users.spec.ts +14 -11
- package/lib/project-files/src/common/ENV.ts +9 -2
- package/lib/project-files/src/common/constants.ts +2 -1
- package/lib/project-files/src/repos/MockOrm.ts +2 -2
- package/lib/project-files/src/repos/database.test.json +1 -1
- package/lib/project-files/src/routes/UserRoutes.ts +0 -1
- package/lib/project-files/src/routes/common/index.ts +42 -26
- package/lib/project-files/src/routes/index.ts +1 -1
- package/lib/project-files/src/server.ts +6 -6
- package/package.json +1 -1
- /package/lib/project-files/src/{routes/common → common}/Paths.ts +0 -0
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Response } from 'supertest';
|
|
2
|
+
import { TParseReqErr } from '@src/routes/common';
|
|
2
3
|
import UserRepo from '@src/repos/UserRepo';
|
|
3
4
|
|
|
4
5
|
|
|
@@ -6,9 +7,19 @@ import UserRepo from '@src/repos/UserRepo';
|
|
|
6
7
|
Types
|
|
7
8
|
******************************************************************************/
|
|
8
9
|
|
|
10
|
+
// Use generics to add properties to 'body'
|
|
11
|
+
export type TRes<T = object> = Omit<Response, 'body'> & {
|
|
12
|
+
body: T & { error?: string | IErrObj },
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
interface IErrObj {
|
|
16
|
+
message: string;
|
|
17
|
+
[key: string]: unknown;
|
|
18
|
+
}
|
|
19
|
+
|
|
9
20
|
export interface IValidationErr {
|
|
10
21
|
message: string;
|
|
11
|
-
parameters:
|
|
22
|
+
parameters: TParseReqErr[];
|
|
12
23
|
}
|
|
13
24
|
|
|
14
25
|
|
|
@@ -12,7 +12,8 @@ import HttpStatusCodes from '@src/common/HttpStatusCodes';
|
|
|
12
12
|
import { ValidationErr } from '@src/common/route-errors';
|
|
13
13
|
|
|
14
14
|
import Paths from 'spec/support/Paths';
|
|
15
|
-
import { cleanDatabase, IValidationErr } from 'spec/support';
|
|
15
|
+
import { cleanDatabase, IValidationErr, TRes } from 'spec/support';
|
|
16
|
+
import { isObject } from 'jet-validators';
|
|
16
17
|
|
|
17
18
|
|
|
18
19
|
/******************************************************************************
|
|
@@ -30,7 +31,7 @@ const DB_USERS = [
|
|
|
30
31
|
// database
|
|
31
32
|
const compareUserArrays = customDeepCompare({
|
|
32
33
|
onlyCompareProps: ['name', 'email'],
|
|
33
|
-
})
|
|
34
|
+
});
|
|
34
35
|
|
|
35
36
|
|
|
36
37
|
/******************************************************************************
|
|
@@ -59,7 +60,7 @@ describe('UserRouter', () => {
|
|
|
59
60
|
`of "${HttpStatusCodes.OK}" if the request was successful.`, done => {
|
|
60
61
|
agent
|
|
61
62
|
.get(Paths.Users.Get)
|
|
62
|
-
.end((_, res) => {
|
|
63
|
+
.end((_, res: TRes<{ users: IUser[]}>) => {
|
|
63
64
|
expect(res.status).toBe(HttpStatusCodes.OK);
|
|
64
65
|
expect(compareUserArrays(res.body.users, DB_USERS)).toBeTruthy();
|
|
65
66
|
done();
|
|
@@ -90,11 +91,12 @@ describe('UserRouter', () => {
|
|
|
90
91
|
agent
|
|
91
92
|
.post(Paths.Users.Add)
|
|
92
93
|
.send({ user: null })
|
|
93
|
-
.end((_, res) => {
|
|
94
|
+
.end((_, res: TRes) => {
|
|
94
95
|
expect(res.status).toBe(HttpStatusCodes.BAD_REQUEST);
|
|
95
|
-
const errorObj = parseJson<IValidationErr>(res.body.error)
|
|
96
|
+
const errorObj = parseJson<IValidationErr>(res.body.error),
|
|
97
|
+
parseErr = errorObj.parameters[0];
|
|
96
98
|
expect(errorObj.message).toBe(ValidationErr.MSG);
|
|
97
|
-
expect(
|
|
99
|
+
expect(isObject(parseErr) && parseErr.prop === 'user').toBeTruthy();
|
|
98
100
|
done();
|
|
99
101
|
});
|
|
100
102
|
});
|
|
@@ -124,11 +126,12 @@ describe('UserRouter', () => {
|
|
|
124
126
|
agent
|
|
125
127
|
.put(Paths.Users.Update)
|
|
126
128
|
.send({ user: null })
|
|
127
|
-
.end((_, res) => {
|
|
129
|
+
.end((_, res: TRes) => {
|
|
128
130
|
expect(res.status).toBe(HttpStatusCodes.BAD_REQUEST);
|
|
129
|
-
const errorObj = parseJson<IValidationErr>(res.body.error)
|
|
131
|
+
const errorObj = parseJson<IValidationErr>(res.body.error),
|
|
132
|
+
parseErr = errorObj.parameters[0];
|
|
130
133
|
expect(errorObj.message).toBe(ValidationErr.MSG);
|
|
131
|
-
expect(
|
|
134
|
+
expect(isObject(parseErr) && parseErr.prop === 'user').toBeTruthy();
|
|
132
135
|
done();
|
|
133
136
|
});
|
|
134
137
|
});
|
|
@@ -141,7 +144,7 @@ describe('UserRouter', () => {
|
|
|
141
144
|
agent
|
|
142
145
|
.put(Paths.Users.Update)
|
|
143
146
|
.send({ user })
|
|
144
|
-
.end((_, res) => {
|
|
147
|
+
.end((_, res: TRes) => {
|
|
145
148
|
expect(res.status).toBe(HttpStatusCodes.NOT_FOUND);
|
|
146
149
|
expect(res.body.error).toBe(USER_NOT_FOUND_ERR);
|
|
147
150
|
done();
|
|
@@ -172,7 +175,7 @@ describe('UserRouter', () => {
|
|
|
172
175
|
`"${HttpStatusCodes.NOT_FOUND}" if the id was not found.`, done => {
|
|
173
176
|
agent
|
|
174
177
|
.delete(getPath(-1))
|
|
175
|
-
.end((_, res) => {
|
|
178
|
+
.end((_, res: TRes) => {
|
|
176
179
|
expect(res.status).toBe(HttpStatusCodes.NOT_FOUND);
|
|
177
180
|
expect(res.body.error).toBe(USER_NOT_FOUND_ERR);
|
|
178
181
|
done();
|
|
@@ -5,10 +5,17 @@ import { NodeEnvs } from './constants';
|
|
|
5
5
|
|
|
6
6
|
|
|
7
7
|
/******************************************************************************
|
|
8
|
-
|
|
8
|
+
Setup
|
|
9
9
|
******************************************************************************/
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
const ENV = jetEnv({
|
|
12
12
|
NodeEnv: isEnumVal(NodeEnvs),
|
|
13
13
|
Port: num,
|
|
14
14
|
});
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
/******************************************************************************
|
|
18
|
+
Export default
|
|
19
|
+
******************************************************************************/
|
|
20
|
+
|
|
21
|
+
export default ENV;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"users":[{"id":
|
|
1
|
+
{"users":[{"id":833335167307,"name":"Bill","created":"2025-02-21T15:41:21.593Z","email":"sean.maxwell@gmail.com"},{"id":721615734671,"name":"John Smith","created":"2025-02-21T15:41:21.593Z","email":"john.smith@gmail.com"},{"id":531901228132,"name":"Gordan Freeman","created":"2025-02-21T15:41:21.593Z","email":"gordan.freeman@gmail.com"},{"id":811228870992,"name":"a","created":"2025-02-21T15:41:21.594Z","email":"a@a.com"}]}
|
|
@@ -13,11 +13,11 @@ 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
|
|
17
|
-
prop: string
|
|
18
|
-
value: unknown
|
|
19
|
-
moreInfo?: string
|
|
20
|
-
}
|
|
16
|
+
export type TParseReqErr = {
|
|
17
|
+
prop: string,
|
|
18
|
+
value: unknown,
|
|
19
|
+
moreInfo?: string,
|
|
20
|
+
} | string;
|
|
21
21
|
|
|
22
22
|
|
|
23
23
|
/******************************************************************************
|
|
@@ -29,34 +29,50 @@ export interface IReqPropErr {
|
|
|
29
29
|
*/
|
|
30
30
|
export function parseReq<U extends TSchema>(schema: U) {
|
|
31
31
|
return (arg: unknown) => {
|
|
32
|
-
// Don't alter original object
|
|
32
|
+
// Don't alter original object (shallow copy is good enough)
|
|
33
33
|
if (isObject(arg)) {
|
|
34
34
|
arg = { ...arg };
|
|
35
35
|
}
|
|
36
|
-
//
|
|
37
|
-
const errArr:
|
|
38
|
-
|
|
39
|
-
|
|
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
|
|
36
|
+
// Setup error callback
|
|
37
|
+
const errArr: TParseReqErr[] = [],
|
|
38
|
+
errCb = setupErrorCb(errArr);
|
|
39
|
+
// Run Tests
|
|
56
40
|
const retVal = parseObject<U>(schema, errCb)(arg);
|
|
57
41
|
if (errArr.length > 0) {
|
|
58
42
|
throw new ValidationErr(errArr);
|
|
59
43
|
}
|
|
44
|
+
// Return
|
|
60
45
|
return retVal;
|
|
61
46
|
};
|
|
62
47
|
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Setup the error callback function for when "parseReq" fires and error.
|
|
51
|
+
*/
|
|
52
|
+
function setupErrorCb(errArr: TParseReqErr[]) {
|
|
53
|
+
return function (
|
|
54
|
+
prop = 'undefined',
|
|
55
|
+
value?: unknown,
|
|
56
|
+
caughtErr?: unknown,
|
|
57
|
+
) {
|
|
58
|
+
// Initialize err
|
|
59
|
+
let err: TParseReqErr;
|
|
60
|
+
if (arguments.length === 1) {
|
|
61
|
+
err = prop;
|
|
62
|
+
} else {
|
|
63
|
+
err = { prop, value };
|
|
64
|
+
}
|
|
65
|
+
// Check if there's a "caught error"
|
|
66
|
+
if (isObject(err) && caughtErr !== undefined) {
|
|
67
|
+
let moreInfo;
|
|
68
|
+
if (!isString(caughtErr)) {
|
|
69
|
+
moreInfo = JSON.stringify(caughtErr);
|
|
70
|
+
} else {
|
|
71
|
+
moreInfo = caughtErr;
|
|
72
|
+
}
|
|
73
|
+
err.moreInfo = moreInfo;
|
|
74
|
+
}
|
|
75
|
+
// Add error to array
|
|
76
|
+
errArr.push(err);
|
|
77
|
+
};
|
|
78
|
+
}
|
|
@@ -8,7 +8,7 @@ import 'express-async-errors';
|
|
|
8
8
|
|
|
9
9
|
import BaseRouter from '@src/routes';
|
|
10
10
|
|
|
11
|
-
import Paths from '@src/
|
|
11
|
+
import Paths from '@src/common/Paths';
|
|
12
12
|
import ENV from '@src/common/ENV';
|
|
13
13
|
import HttpStatusCodes from '@src/common/HttpStatusCodes';
|
|
14
14
|
import { RouteError } from '@src/common/route-errors';
|
|
@@ -16,25 +16,25 @@ import { NodeEnvs } from '@src/common/constants';
|
|
|
16
16
|
|
|
17
17
|
|
|
18
18
|
/******************************************************************************
|
|
19
|
-
|
|
19
|
+
Setup
|
|
20
20
|
******************************************************************************/
|
|
21
21
|
|
|
22
22
|
const app = express();
|
|
23
23
|
|
|
24
24
|
|
|
25
|
-
// ****
|
|
25
|
+
// **** Middleware **** //
|
|
26
26
|
|
|
27
27
|
// Basic middleware
|
|
28
28
|
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 (ENV.NodeEnv === NodeEnvs.Dev
|
|
32
|
+
if (ENV.NodeEnv === NodeEnvs.Dev) {
|
|
33
33
|
app.use(morgan('dev'));
|
|
34
34
|
}
|
|
35
35
|
|
|
36
36
|
// Security
|
|
37
|
-
if (ENV.NodeEnv === NodeEnvs.Production
|
|
37
|
+
if (ENV.NodeEnv === NodeEnvs.Production) {
|
|
38
38
|
app.use(helmet());
|
|
39
39
|
}
|
|
40
40
|
|
|
@@ -55,7 +55,7 @@ app.use((err: Error, _: Request, res: Response, next: NextFunction) => {
|
|
|
55
55
|
});
|
|
56
56
|
|
|
57
57
|
|
|
58
|
-
// ****
|
|
58
|
+
// **** FrontEnd Content **** //
|
|
59
59
|
|
|
60
60
|
// Set views directory (html)
|
|
61
61
|
const viewsDir = path.join(__dirname, 'views');
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "express-generator-typescript",
|
|
3
|
-
"version": "2.5.
|
|
3
|
+
"version": "2.5.16",
|
|
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",
|
|
File without changes
|