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.
@@ -27,7 +27,7 @@
27
27
  "jet-logger": "^2.0.1",
28
28
  "jet-paths": "^1.1.0",
29
29
  "jet-schema": "^1.4.2",
30
- "jet-validators": "^1.0.17",
30
+ "jet-validators": "^1.1.0",
31
31
  "jsonfile": "^6.1.0",
32
32
  "module-alias": "^2.2.2",
33
33
  "morgan": "^1.10.0"
@@ -1,5 +1,5 @@
1
1
  import jetPaths from 'jet-paths';
2
- import Paths from '@src/routes/common/Paths';
2
+ import Paths from '@src/common/Paths';
3
3
 
4
4
 
5
5
  export default jetPaths(Paths);
@@ -1,4 +1,5 @@
1
- import { IReqPropErr } from '@src/routes/common';
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: IReqPropErr[];
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(errorObj.parameters[0].prop).toBe('user');
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(errorObj.parameters[0].prop).toBe('user');
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
- Export default
8
+ Setup
9
9
  ******************************************************************************/
10
10
 
11
- export default jetEnv({
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;
@@ -3,8 +3,9 @@
3
3
  Enums
4
4
  ******************************************************************************/
5
5
 
6
+ // NOTE: These need to match the names of your ".env" files
6
7
  export enum NodeEnvs {
7
8
  Dev = 'development',
8
9
  Test = 'test',
9
10
  Production = 'production'
10
- }
11
+ }
@@ -11,8 +11,8 @@ import { IUser } from '@src/models/User';
11
11
 
12
12
  const DB_FILE_NAME = (
13
13
  ENV.NodeEnv === NodeEnvs.Test
14
- ? 'database.test.json'
15
- : 'database.json'
14
+ ? 'database.test.json'
15
+ : 'database.json'
16
16
  );
17
17
 
18
18
 
@@ -1 +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
+ {"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"}]}
@@ -5,7 +5,6 @@ import HttpStatusCodes from '@src/common/HttpStatusCodes';
5
5
  import UserService from '@src/services/UserService';
6
6
  import User from '@src/models/User';
7
7
 
8
-
9
8
  import { parseReq, IReq, IRes } from './common';
10
9
 
11
10
 
@@ -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 interface IReqPropErr {
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
- // 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
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
+ }
@@ -1,6 +1,6 @@
1
1
  import { Router } from 'express';
2
2
 
3
- import Paths from './common/Paths';
3
+ import Paths from '../common/Paths';
4
4
  import UserRoutes from './UserRoutes';
5
5
 
6
6
 
@@ -8,7 +8,7 @@ import 'express-async-errors';
8
8
 
9
9
  import BaseRouter from '@src/routes';
10
10
 
11
- import Paths from '@src/routes/common/Paths';
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
- Variables
19
+ Setup
20
20
  ******************************************************************************/
21
21
 
22
22
  const app = express();
23
23
 
24
24
 
25
- // **** Setup
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.valueOf()) {
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.valueOf()) {
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
- // **** Front-End Content
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.15",
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",