express-generator-typescript 2.4.12 → 2.4.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.
Files changed (27) hide show
  1. package/lib/express-generator-typescript.js +1 -1
  2. package/lib/project-files/package.json +0 -1
  3. package/lib/project-files/spec/tests/users.spec.ts +3 -3
  4. package/lib/project-files/src/common/classes.ts +32 -0
  5. package/lib/project-files/src/models/User.ts +4 -5
  6. package/lib/project-files/src/routes/UserRoutes.ts +8 -7
  7. package/lib/project-files/src/routes/common/check.ts +143 -0
  8. package/lib/project-files/src/routes/common/types.ts +4 -21
  9. package/lib/project-files/src/routes/index.ts +6 -29
  10. package/lib/project-files/src/server.ts +1 -1
  11. package/lib/project-files/src/services/UserService.ts +1 -1
  12. package/lib/project-files-auth/package.json +0 -1
  13. package/lib/project-files-auth/spec/tests/users.spec.ts +3 -3
  14. package/lib/project-files-auth/src/common/classes.ts +31 -0
  15. package/lib/project-files-auth/src/models/User.ts +2 -3
  16. package/lib/project-files-auth/src/routes/AuthRoutes.ts +4 -12
  17. package/lib/project-files-auth/src/routes/UserRoutes.ts +8 -6
  18. package/lib/project-files-auth/src/routes/common/check.ts +143 -0
  19. package/lib/project-files-auth/src/routes/common/types.ts +4 -46
  20. package/lib/project-files-auth/src/routes/index.ts +11 -44
  21. package/lib/project-files-auth/src/server.ts +3 -3
  22. package/lib/project-files-auth/src/services/AuthService.ts +1 -1
  23. package/lib/project-files-auth/src/services/UserService.ts +1 -1
  24. package/lib/project-files-auth/src/util/SessionUtil.ts +6 -6
  25. package/package.json +1 -1
  26. package/lib/project-files/src/common/RouteError.ts +0 -20
  27. package/lib/project-files-auth/src/common/RouteError.ts +0 -20
@@ -20,7 +20,7 @@ const PROJECT_FOLDER_PATH = './project-files';
20
20
  // Project-folder dependencies
21
21
  const DEPENDENCIES = 'express dotenv morgan cookie-parser jet-logger ' +
22
22
  'module-alias express-async-errors helmet jsonfile inserturlparams ' +
23
- 'jet-validator ts-command-line-args jet-paths moment',
23
+ 'ts-command-line-args jet-paths moment',
24
24
  DEPENDENCIES_AUTH = ' bcrypt jsonwebtoken',
25
25
  DEV_DEPENDENCIES = 'ts-node typescript nodemon find jasmine supertest ' +
26
26
  '@types/node @types/express @types/jasmine @types/find @types/morgan ' +
@@ -36,7 +36,6 @@
36
36
  "inserturlparams": "^1.0.1",
37
37
  "jet-logger": "^1.3.1",
38
38
  "jet-paths": "^1.0.5",
39
- "jet-validator": "^1.0.3",
40
39
  "jsonfile": "^6.1.0",
41
40
  "jsonwebtoken": "^8.5.1",
42
41
  "module-alias": "^2.2.2",
@@ -1,6 +1,5 @@
1
1
  import supertest, { Test } from 'supertest';
2
2
  import TestAgent from 'supertest/lib/agent';
3
- import { defaultErrMsg as ValidatorErr } from 'jet-validator';
4
3
  import insertUrlParams from 'inserturlparams';
5
4
 
6
5
  import app from '@src/server';
@@ -13,6 +12,7 @@ import { USER_NOT_FOUND_ERR } from '@src/services/UserService';
13
12
  import Paths from 'spec/support/Paths';
14
13
  import apiCb from 'spec/support/apiCb';
15
14
  import { TApiCb } from 'spec/types/misc';
15
+ import { ValidationErr } from '@src/common/classes';
16
16
 
17
17
 
18
18
  // Dummy users for GET req
@@ -63,7 +63,7 @@ describe('UserRouter', () => {
63
63
  // Test add user
64
64
  describe(`"POST:${Paths.Users.Add}"`, () => {
65
65
 
66
- const ERROR_MSG = `${ValidatorErr}"user".`,
66
+ const ERROR_MSG = ValidationErr.GetMsg('user'),
67
67
  DUMMY_USER = getDummyUsers()[0];
68
68
 
69
69
  // Setup API
@@ -101,7 +101,7 @@ describe('UserRouter', () => {
101
101
  // Update users
102
102
  describe(`"PUT:${Paths.Users.Update}"`, () => {
103
103
 
104
- const ERROR_MSG = `${ValidatorErr}"user".`,
104
+ const ERROR_MSG = ValidationErr.GetMsg('user'),
105
105
  DUMMY_USER = getDummyUsers()[0];
106
106
 
107
107
  // Setup API
@@ -0,0 +1,32 @@
1
+ import HttpStatusCodes from '@src/common/HttpStatusCodes';
2
+
3
+
4
+ /**
5
+ * Error with status code and message.
6
+ */
7
+ export class RouteError extends Error {
8
+
9
+ public status: HttpStatusCodes;
10
+
11
+ public constructor(status: HttpStatusCodes, message: string) {
12
+ super(message);
13
+ this.status = status;
14
+ }
15
+ }
16
+
17
+ /**
18
+ * If route validation fails.
19
+ */
20
+ export class ValidationErr extends RouteError {
21
+
22
+ public static MSG = 'The follow parameter were missing or invalid "';
23
+
24
+ public constructor(paramName: string) {
25
+ super(HttpStatusCodes.BAD_REQUEST, ValidationErr.GetMsg(paramName));
26
+ }
27
+
28
+ public static GetMsg(param: string) {
29
+ return ValidationErr.MSG + param + '".';
30
+ }
31
+ }
32
+
@@ -40,17 +40,16 @@ function new_(
40
40
  * Get user instance from object.
41
41
  */
42
42
  function from(param: object): IUser {
43
- if (!isUser(param)) {
44
- throw new Error(INVALID_CONSTRUCTOR_PARAM);
43
+ if (isUser(param)) {
44
+ return new_(param.name, param.email, param.created, param.id);
45
45
  }
46
- const p = param as IUser;
47
- return new_(p.name, p.email, p.created, p.id);
46
+ throw new Error(INVALID_CONSTRUCTOR_PARAM);
48
47
  }
49
48
 
50
49
  /**
51
50
  * See if the param meets criteria to be a user.
52
51
  */
53
- function isUser(arg: unknown): boolean {
52
+ function isUser(arg: unknown): arg is IUser {
54
53
  return (
55
54
  !!arg &&
56
55
  typeof arg === 'object' &&
@@ -1,8 +1,9 @@
1
1
  import HttpStatusCodes from '@src/common/HttpStatusCodes';
2
-
3
2
  import UserService from '@src/services/UserService';
4
- import { IUser } from '@src/models/User';
3
+ import User from '@src/models/User';
4
+
5
5
  import { IReq, IRes } from './common/types';
6
+ import check from './common/check';
6
7
 
7
8
 
8
9
  // **** Functions **** //
@@ -18,8 +19,8 @@ async function getAll(_: IReq, res: IRes) {
18
19
  /**
19
20
  * Add one user.
20
21
  */
21
- async function add(req: IReq<{user: IUser}>, res: IRes) {
22
- const { user } = req.body;
22
+ async function add(req: IReq, res: IRes) {
23
+ const user = check.isValid(req.body, 'user', User.isUser);
23
24
  await UserService.addOne(user);
24
25
  return res.status(HttpStatusCodes.CREATED).end();
25
26
  }
@@ -27,8 +28,8 @@ async function add(req: IReq<{user: IUser}>, res: IRes) {
27
28
  /**
28
29
  * Update one user.
29
30
  */
30
- async function update(req: IReq<{user: IUser}>, res: IRes) {
31
- const { user } = req.body;
31
+ async function update(req: IReq, res: IRes) {
32
+ const user = check.isValid(req.body, 'user', User.isUser);
32
33
  await UserService.updateOne(user);
33
34
  return res.status(HttpStatusCodes.OK).end();
34
35
  }
@@ -37,7 +38,7 @@ async function update(req: IReq<{user: IUser}>, res: IRes) {
37
38
  * Delete one user.
38
39
  */
39
40
  async function delete_(req: IReq, res: IRes) {
40
- const id = +req.params.id;
41
+ const id = check.isNum(req.params, 'id');
41
42
  await UserService.delete(id);
42
43
  return res.status(HttpStatusCodes.OK).end();
43
44
  }
@@ -0,0 +1,143 @@
1
+ import { ValidationErr } from '@src/common/classes';
2
+
3
+
4
+ type TReqObj = Record<string, unknown>;
5
+
6
+
7
+ /**
8
+ * Check that param/s is a string
9
+ */
10
+ function isStr(reqObj: TReqObj, params: string): string;
11
+ function isStr(reqObj: TReqObj, params: ReadonlyArray<string>): string[];
12
+ function isStr(
13
+ reqObj: TReqObj,
14
+ params: string | ReadonlyArray<string>,
15
+ ): string | string[] {
16
+ return _checkWrapper(reqObj, params, _checkStr);
17
+ }
18
+
19
+ /**
20
+ * Check validator for string
21
+ */
22
+ function _checkStr(val: unknown): string | undefined {
23
+ if (!!val && typeof val === 'string') {
24
+ return val;
25
+ } else {
26
+ return undefined;
27
+ }
28
+ }
29
+
30
+ /**
31
+ * Check that param/s is a number.
32
+ */
33
+ function isNum(reqObj: TReqObj, params: string): number;
34
+ function isNum(reqObj: TReqObj, params: ReadonlyArray<string>): number[];
35
+ function isNum(
36
+ reqObj: TReqObj,
37
+ params: string | ReadonlyArray<string>,
38
+ ): number | number[] {
39
+ return _checkWrapper(reqObj, params, _checkNum);
40
+ }
41
+
42
+ /**
43
+ * Check validator for string
44
+ */
45
+ function _checkNum(val: unknown): number | undefined {
46
+ const valF = Number(val);
47
+ if (!isNaN(valF)) {
48
+ return valF;
49
+ } else {
50
+ return undefined;
51
+ }
52
+ }
53
+
54
+ /**
55
+ * Check that param/s is a number
56
+ */
57
+ function isBool(reqObj: TReqObj, params: string): boolean;
58
+ function isBool(reqObj: TReqObj, params: ReadonlyArray<string>): boolean[];
59
+ function isBool(
60
+ reqObj: TReqObj,
61
+ params: string | ReadonlyArray<string>,
62
+ ): boolean | boolean[] {
63
+ return _checkWrapper(reqObj, params, _checkBool);
64
+ }
65
+
66
+ /**
67
+ * Check validator for string
68
+ */
69
+ function _checkBool(val: unknown): boolean | undefined {
70
+ if (typeof val === 'boolean') {
71
+ return val;
72
+ } else if (typeof val === 'string') {
73
+ val = val.toLowerCase();
74
+ if (val === 'true') {
75
+ return true;
76
+ } else if (val === 'false') {
77
+ return false;
78
+ } else {
79
+ return undefined;
80
+ }
81
+ } else {
82
+ return undefined;
83
+ }
84
+ }
85
+
86
+ /**
87
+ * Check that param satisfies the validator function.
88
+ */
89
+ function isValid<T>(
90
+ reqObj: TReqObj,
91
+ param: string,
92
+ validatorFn: (param: unknown) => param is T,
93
+ ): T {
94
+ const val = reqObj[param];
95
+ if (validatorFn(val)) {
96
+ return val;
97
+ } else {
98
+ throw new ValidationErr(param);
99
+ }
100
+ }
101
+
102
+
103
+ // **** Shared Helpers **** //
104
+
105
+ /**
106
+ * Do stuff based on whether or not params is an array
107
+ */
108
+ function _checkWrapper<T>(
109
+ reqObj: TReqObj,
110
+ params: string | ReadonlyArray<string>,
111
+ checkFn: (val: unknown) => T | undefined,
112
+ ): T | T[] {
113
+ // If is array
114
+ if (params instanceof Array) {
115
+ const retVal: T[] = [];
116
+ for (const param of params) {
117
+ const val = checkFn(reqObj[param]);
118
+ if (val !== undefined) {
119
+ retVal.push(val);
120
+ } else {
121
+ throw new ValidationErr(param);
122
+ }
123
+ }
124
+ return retVal;
125
+ }
126
+ // If not an array
127
+ const val = checkFn(reqObj[params]);
128
+ if (val !== undefined) {
129
+ return val;
130
+ }
131
+ // Throw error
132
+ throw new ValidationErr(params);
133
+ }
134
+
135
+
136
+ // **** Export Default **** //
137
+
138
+ export default {
139
+ isStr,
140
+ isNum,
141
+ isBool,
142
+ isValid,
143
+ } as const;
@@ -6,28 +6,11 @@
6
6
  import { Response, Request } from 'express';
7
7
 
8
8
 
9
- // **** Express Request **** //
9
+ // **** Express **** //
10
10
 
11
- type TPathParams = Record<string, string>;
11
+ type TObj = Record<string, unknown>;
12
12
 
13
- interface QryObj {
14
- [key: string]: string | string[] | undefined;
15
- }
13
+ export type IReq = Request<TObj, void, TObj, TObj>;
16
14
 
17
- type TQueryParams<U = void> =
18
- U extends void
19
- ? QryObj
20
- : U extends QryObj
21
- ? U
22
- : never;
23
-
24
-
25
- export interface IReq<T = void, U extends QryObj | void = void> extends Request<TPathParams, void, T, TQueryParams<U>> {
26
- body: T;
27
- }
28
-
29
-
30
- export interface IRes extends Response {
31
- locals: Record<string, unknown>;
32
- }
15
+ export type IRes = Response<unknown, TObj>
33
16
 
@@ -1,47 +1,24 @@
1
1
  import { Router } from 'express';
2
- import jetValidator from 'jet-validator';
3
2
 
4
3
  import Paths from '../common/Paths';
5
- import User from '@src/models/User';
6
4
  import UserRoutes from './UserRoutes';
7
5
 
8
6
 
9
7
  // **** Variables **** //
10
8
 
11
- const apiRouter = Router(),
12
- validate = jetValidator();
9
+ const apiRouter = Router();
13
10
 
14
11
 
15
12
  // ** Add UserRouter ** //
16
13
 
14
+ // Init router
17
15
  const userRouter = Router();
18
16
 
19
17
  // Get all users
20
- userRouter.get(
21
- Paths.Users.Get,
22
- UserRoutes.getAll,
23
- );
24
-
25
- // Add one user
26
- userRouter.post(
27
- Paths.Users.Add,
28
- validate(['user', User.isUser]),
29
- UserRoutes.add,
30
- );
31
-
32
- // Update one user
33
- userRouter.put(
34
- Paths.Users.Update,
35
- validate(['user', User.isUser]),
36
- UserRoutes.update,
37
- );
38
-
39
- // Delete one user
40
- userRouter.delete(
41
- Paths.Users.Delete,
42
- validate(['id', 'number', 'params']),
43
- UserRoutes.delete,
44
- );
18
+ userRouter.get(Paths.Users.Get, UserRoutes.getAll);
19
+ userRouter.post(Paths.Users.Add, UserRoutes.add);
20
+ userRouter.put(Paths.Users.Update, UserRoutes.update);
21
+ userRouter.delete(Paths.Users.Delete, UserRoutes.delete);
45
22
 
46
23
  // Add UserRouter
47
24
  apiRouter.use(Paths.Users.Base, userRouter);
@@ -16,7 +16,7 @@ import BaseRouter from '@src/routes';
16
16
  import Paths from '@src/common/Paths';
17
17
  import EnvVars from '@src/common/EnvVars';
18
18
  import HttpStatusCodes from '@src/common/HttpStatusCodes';
19
- import RouteError from '@src/common/RouteError';
19
+ import { RouteError } from '@src/common/classes';
20
20
  import { NodeEnvs } from '@src/common/misc';
21
21
 
22
22
 
@@ -1,4 +1,4 @@
1
- import RouteError from '@src/common/RouteError';
1
+ import { RouteError } from '@src/common/classes';
2
2
  import HttpStatusCodes from '@src/common/HttpStatusCodes';
3
3
 
4
4
  import UserRepo from '@src/repos/UserRepo';
@@ -36,7 +36,6 @@
36
36
  "inserturlparams": "^1.0.1",
37
37
  "jet-logger": "^1.3.1",
38
38
  "jet-paths": "^1.0.5",
39
- "jet-validator": "^1.0.3",
40
39
  "jsonfile": "^6.1.0",
41
40
  "jsonwebtoken": "^8.5.1",
42
41
  "module-alias": "^2.2.2",
@@ -1,6 +1,5 @@
1
1
  import supertest, { Test } from 'supertest';
2
2
  import TestAgent from 'supertest/lib/agent';
3
- import { defaultErrMsg as ValidatorErr } from 'jet-validator';
4
3
  import insertUrlParams from 'inserturlparams';
5
4
 
6
5
  import app from '@src/server';
@@ -14,6 +13,7 @@ import Paths from 'spec/support/Paths';
14
13
  import apiCb from 'spec/support/apiCb';
15
14
  import login from 'spec/support/login';
16
15
  import { TApiCb } from 'spec/types/misc';
16
+ import { ValidationErr } from '@src/common/classes';
17
17
 
18
18
 
19
19
  // Dummy users for GET req
@@ -67,7 +67,7 @@ describe('UserRouter', () => {
67
67
  // Test add user
68
68
  describe(`"POST:${Paths.Users.Add}"`, () => {
69
69
 
70
- const ERROR_MSG = `${ValidatorErr}"user".`,
70
+ const ERROR_MSG = ValidationErr.GetMsg('user'),
71
71
  DUMMY_USER = getDummyUsers()[0];
72
72
 
73
73
  // Setup API
@@ -105,7 +105,7 @@ describe('UserRouter', () => {
105
105
  // Update users
106
106
  describe(`"PUT:${Paths.Users.Update}"`, () => {
107
107
 
108
- const ERROR_MSG = `${ValidatorErr}"user".`,
108
+ const ERROR_MSG = ValidationErr.GetMsg('user'),
109
109
  DUMMY_USER = getDummyUsers()[0];
110
110
 
111
111
  // Setup API
@@ -0,0 +1,31 @@
1
+ import HttpStatusCodes from '@src/common/HttpStatusCodes';
2
+
3
+
4
+ /**
5
+ * Error with status code and message.
6
+ */
7
+ export class RouteError extends Error {
8
+
9
+ public status: HttpStatusCodes;
10
+
11
+ public constructor(status: HttpStatusCodes, message: string) {
12
+ super(message);
13
+ this.status = status;
14
+ }
15
+ }
16
+
17
+ /**
18
+ * If route validation fails.
19
+ */
20
+ export class ValidationErr extends RouteError {
21
+
22
+ public static MSG = 'The follow parameter were missing or invalid "';
23
+
24
+ public constructor(paramName: string) {
25
+ super(HttpStatusCodes.BAD_REQUEST, ValidationErr.GetMsg(paramName));
26
+ }
27
+
28
+ public static GetMsg(param: string) {
29
+ return ValidationErr.MSG + param + '".';
30
+ }
31
+ }
@@ -60,14 +60,13 @@ function from(param: object): IUser {
60
60
  if (!isUser(param)) {
61
61
  throw new Error(INVALID_CONSTRUCTOR_PARAM);
62
62
  }
63
- const p = param as IUser;
64
- return new_(p.name, p.email, p.created, p.id);
63
+ return new_(param.name, param.email, param.created, param.id);
65
64
  }
66
65
 
67
66
  /**
68
67
  * See if the param meets criteria to be a user.
69
68
  */
70
- function isUser(arg: unknown): boolean {
69
+ function isUser(arg: unknown): arg is IUser {
71
70
  return (
72
71
  !!arg &&
73
72
  typeof arg === 'object' &&
@@ -3,14 +3,7 @@ import SessionUtil from '@src/util/SessionUtil';
3
3
  import AuthService from '@src/services/AuthService';
4
4
 
5
5
  import { IReq, IRes } from './common/types';
6
-
7
-
8
- // **** Types **** //
9
-
10
- interface ILoginReq {
11
- email: string;
12
- password: string;
13
- }
6
+ import check from './common/check';
14
7
 
15
8
 
16
9
  // **** Functions **** //
@@ -18,10 +11,9 @@ interface ILoginReq {
18
11
  /**
19
12
  * Login a user.
20
13
  */
21
- async function login(req: IReq<ILoginReq>, res: IRes) {
22
- const { email, password } = req.body;
23
- // Login
24
- const user = await AuthService.login(email, password);
14
+ async function login(req: IReq, res: IRes) {
15
+ const [ email, password ] = check.isStr(req.body, ['email', 'password']),
16
+ user = await AuthService.login(email, password);
25
17
  // Setup Admin Cookie
26
18
  await SessionUtil.addSessionData(res, {
27
19
  id: user.id,
@@ -1,8 +1,10 @@
1
1
  import HttpStatusCodes from '@src/common/HttpStatusCodes';
2
2
 
3
3
  import UserService from '@src/services/UserService';
4
- import { IUser } from '@src/models/User';
4
+ import User from '@src/models/User';
5
+
5
6
  import { IReq, IRes } from './common/types';
7
+ import check from './common/check';
6
8
 
7
9
 
8
10
  // **** Functions **** //
@@ -18,8 +20,8 @@ async function getAll(_: IReq, res: IRes) {
18
20
  /**
19
21
  * Add one user.
20
22
  */
21
- async function add(req: IReq<{user: IUser}>, res: IRes) {
22
- const { user } = req.body;
23
+ async function add(req: IReq, res: IRes) {
24
+ const user = check.isValid(req.body, 'user', User.isUser);
23
25
  await UserService.addOne(user);
24
26
  return res.status(HttpStatusCodes.CREATED).end();
25
27
  }
@@ -27,8 +29,8 @@ async function add(req: IReq<{user: IUser}>, res: IRes) {
27
29
  /**
28
30
  * Update one user.
29
31
  */
30
- async function update(req: IReq<{user: IUser}>, res: IRes) {
31
- const { user } = req.body;
32
+ async function update(req: IReq, res: IRes) {
33
+ const user = check.isValid(req.body, 'user', User.isUser);
32
34
  await UserService.updateOne(user);
33
35
  return res.status(HttpStatusCodes.OK).end();
34
36
  }
@@ -37,7 +39,7 @@ async function update(req: IReq<{user: IUser}>, res: IRes) {
37
39
  * Delete one user.
38
40
  */
39
41
  async function delete_(req: IReq, res: IRes) {
40
- const id = +req.params.id;
42
+ const id = check.isNum(req.params, 'id');
41
43
  await UserService.delete(id);
42
44
  return res.status(HttpStatusCodes.OK).end();
43
45
  }
@@ -0,0 +1,143 @@
1
+ import { ValidationErr } from '@src/common/classes';
2
+
3
+
4
+ type TReqObj = Record<string, unknown>;
5
+
6
+
7
+ /**
8
+ * Check that param/s is a string
9
+ */
10
+ function isStr(reqObj: TReqObj, params: string): string;
11
+ function isStr(reqObj: TReqObj, params: ReadonlyArray<string>): string[];
12
+ function isStr(
13
+ reqObj: TReqObj,
14
+ params: string | ReadonlyArray<string>,
15
+ ): string | string[] {
16
+ return _checkWrapper(reqObj, params, _checkStr);
17
+ }
18
+
19
+ /**
20
+ * Check validator for string
21
+ */
22
+ function _checkStr(val: unknown): string | undefined {
23
+ if (!!val && typeof val === 'string') {
24
+ return val;
25
+ } else {
26
+ return undefined;
27
+ }
28
+ }
29
+
30
+ /**
31
+ * Check that param/s is a number.
32
+ */
33
+ function isNum(reqObj: TReqObj, params: string): number;
34
+ function isNum(reqObj: TReqObj, params: ReadonlyArray<string>): number[];
35
+ function isNum(
36
+ reqObj: TReqObj,
37
+ params: string | ReadonlyArray<string>,
38
+ ): number | number[] {
39
+ return _checkWrapper(reqObj, params, _checkNum);
40
+ }
41
+
42
+ /**
43
+ * Check validator for string
44
+ */
45
+ function _checkNum(val: unknown): number | undefined {
46
+ const valF = Number(val);
47
+ if (!isNaN(valF)) {
48
+ return valF;
49
+ } else {
50
+ return undefined;
51
+ }
52
+ }
53
+
54
+ /**
55
+ * Check that param/s is a number
56
+ */
57
+ function isBool(reqObj: TReqObj, params: string): boolean;
58
+ function isBool(reqObj: TReqObj, params: ReadonlyArray<string>): boolean[];
59
+ function isBool(
60
+ reqObj: TReqObj,
61
+ params: string | ReadonlyArray<string>,
62
+ ): boolean | boolean[] {
63
+ return _checkWrapper(reqObj, params, _checkBool);
64
+ }
65
+
66
+ /**
67
+ * Check validator for string
68
+ */
69
+ function _checkBool(val: unknown): boolean | undefined {
70
+ if (typeof val === 'boolean') {
71
+ return val;
72
+ } else if (typeof val === 'string') {
73
+ val = val.toLowerCase();
74
+ if (val === 'true') {
75
+ return true;
76
+ } else if (val === 'false') {
77
+ return false;
78
+ } else {
79
+ return undefined;
80
+ }
81
+ } else {
82
+ return undefined;
83
+ }
84
+ }
85
+
86
+ /**
87
+ * Check that param satisfies the validator function.
88
+ */
89
+ function isValid<T>(
90
+ reqObj: TReqObj,
91
+ param: string,
92
+ validatorFn: (param: unknown) => param is T,
93
+ ): T {
94
+ const val = reqObj[param];
95
+ if (validatorFn(val)) {
96
+ return val;
97
+ } else {
98
+ throw new ValidationErr(param);
99
+ }
100
+ }
101
+
102
+
103
+ // **** Shared Helpers **** //
104
+
105
+ /**
106
+ * Do stuff based on whether or not params is an array
107
+ */
108
+ function _checkWrapper<T>(
109
+ reqObj: TReqObj,
110
+ params: string | ReadonlyArray<string>,
111
+ checkFn: (val: unknown) => T | undefined,
112
+ ): T | T[] {
113
+ // If is array
114
+ if (params instanceof Array) {
115
+ const retVal: T[] = [];
116
+ for (const param of params) {
117
+ const val = checkFn(reqObj[param]);
118
+ if (val !== undefined) {
119
+ retVal.push(val);
120
+ } else {
121
+ throw new ValidationErr(param);
122
+ }
123
+ }
124
+ return retVal;
125
+ }
126
+ // If not an array
127
+ const val = checkFn(reqObj[params]);
128
+ if (val !== undefined) {
129
+ return val;
130
+ }
131
+ // Throw error
132
+ throw new ValidationErr(params);
133
+ }
134
+
135
+
136
+ // **** Export Default **** //
137
+
138
+ export default {
139
+ isStr,
140
+ isNum,
141
+ isBool,
142
+ isValid,
143
+ } as const;
@@ -1,28 +1,3 @@
1
- // import * as e from 'express';
2
- // import { Query } from 'express-serve-static-core';
3
-
4
- // import { ISessionUser } from '@src/models/User';
5
-
6
-
7
- // // **** Express **** //
8
-
9
- // export interface IReq<T = void> extends e.Request {
10
- // body: T;
11
- // }
12
-
13
- // export interface IReqQuery<T extends Query, U = void> extends e.Request {
14
- // query: T;
15
- // body: U;
16
- // }
17
-
18
- // export interface IRes extends e.Response {
19
- // locals: {
20
- // sessionUser: ISessionUser;
21
- // };
22
- // }
23
-
24
-
25
- /* eslint-disable max-len */
26
1
  /**
27
2
  * Shared types for routes.
28
3
  */
@@ -31,34 +6,17 @@ import { Response, Request } from 'express';
31
6
  import { ISessionUser } from '@src/models/User';
32
7
 
33
8
 
34
- // **** Express Request **** //
9
+ // **** Express **** //
35
10
 
36
- type TPathParams = Record<string, string>;
11
+ type TObj = Record<string, unknown>;
37
12
 
38
- interface QryObj {
39
- [key: string]: string | string[] | undefined;
13
+ export interface IReq extends Request<TObj, void, TObj, TObj> {
14
+ signedCookies: Record<string, string>;
40
15
  }
41
16
 
42
- type TQueryParams<U = void> =
43
- U extends void
44
- ? QryObj
45
- : U extends QryObj
46
- ? U
47
- : never;
48
-
49
-
50
- export interface IReq<T = void, U extends QryObj | void = void> extends Request<TPathParams, void, T, TQueryParams<U>> {
51
- body: T;
52
- }
53
-
54
-
55
- // **** Express Response **** //
56
17
 
57
18
  interface ILocals {
58
19
  sessionUser: ISessionUser;
59
20
  }
60
21
 
61
- // I know since its a type I should use 'TRes' instead of 'IRes' but I'm
62
- // leaving it as this cause it looks better alongside 'IReq'
63
22
  export type IRes = Response<unknown, ILocals>;
64
-
@@ -1,8 +1,6 @@
1
1
  import { Router } from 'express';
2
- import jetValidator from 'jet-validator';
3
2
 
4
3
  import Paths from '@src/common/Paths';
5
- import User from '@src/models/User';
6
4
 
7
5
  import adminMw from './middleware/adminMw';
8
6
  import AuthRoutes from './AuthRoutes';
@@ -11,61 +9,30 @@ import UserRoutes from './UserRoutes';
11
9
 
12
10
  // **** Variables **** //
13
11
 
14
- const apiRouter = Router(),
15
- validate = jetValidator();
12
+ const apiRouter = Router();
16
13
 
17
14
 
18
- // **** Add AuthRouter **** //
15
+ // **** AuthRouter **** //
19
16
 
20
17
  const authRouter = Router();
21
18
 
22
- // Login user
23
- authRouter.post(
24
- Paths.Auth.Login,
25
- validate('email', 'password'),
26
- AuthRoutes.login,
27
- );
28
-
29
- // Logout user
30
- authRouter.get(
31
- Paths.Auth.Logout,
32
- AuthRoutes.logout,
33
- );
19
+ // Routes
20
+ authRouter.post(Paths.Auth.Login, AuthRoutes.login);
21
+ authRouter.get(Paths.Auth.Logout, AuthRoutes.logout);
34
22
 
35
23
  // Add AuthRouter
36
24
  apiRouter.use(Paths.Auth.Base, authRouter);
37
25
 
38
26
 
39
- // ** Add UserRouter ** //
27
+ // **** UserRouter **** //
40
28
 
41
29
  const userRouter = Router();
42
30
 
43
- // Get all users
44
- userRouter.get(
45
- Paths.Users.Get,
46
- UserRoutes.getAll,
47
- );
48
-
49
- // Add one user
50
- userRouter.post(
51
- Paths.Users.Add,
52
- validate(['user', User.isUser]),
53
- UserRoutes.add,
54
- );
55
-
56
- // Update one user
57
- userRouter.put(
58
- Paths.Users.Update,
59
- validate(['user', User.isUser]),
60
- UserRoutes.update,
61
- );
62
-
63
- // Delete one user
64
- userRouter.delete(
65
- Paths.Users.Delete,
66
- validate(['id', 'number', 'params']),
67
- UserRoutes.delete,
68
- );
31
+ // User Routes
32
+ userRouter.get(Paths.Users.Get, UserRoutes.getAll);
33
+ userRouter.post(Paths.Users.Add, UserRoutes.add);
34
+ userRouter.put(Paths.Users.Update, UserRoutes.update);
35
+ userRouter.delete(Paths.Users.Delete, UserRoutes.delete);
69
36
 
70
37
  // Add UserRouter
71
38
  apiRouter.use(Paths.Users.Base, adminMw, userRouter);
@@ -17,8 +17,8 @@ import Paths from '@src/common/Paths';
17
17
  import EnvVars from '@src/common/EnvVars';
18
18
  import HttpStatusCodes from '@src/common/HttpStatusCodes';
19
19
  import { NodeEnvs } from '@src/common/misc';
20
-
21
- import RouteError from '@src/common/RouteError';
20
+ import { RouteError } from '@src/common/classes';
21
+ import { IReq, IRes } from './routes/common/types';
22
22
 
23
23
 
24
24
  // **** Variables **** //
@@ -81,7 +81,7 @@ app.get('/', (_: Request, res: Response) => {
81
81
  });
82
82
 
83
83
  // Redirect to login if not logged in.
84
- app.get('/users', (req: Request, res: Response) => {
84
+ app.get('/users', (req: IReq, res: IRes) => {
85
85
  const jwt = req.signedCookies[EnvVars.CookieProps.Key];
86
86
  if (!jwt) {
87
87
  res.redirect('/');
@@ -4,7 +4,7 @@ import PwdUtil from '@src/util/PwdUtil';
4
4
  import { tick } from '@src/util/misc';
5
5
 
6
6
  import HttpStatusCodes from '@src/common/HttpStatusCodes';
7
- import RouteError from '@src/common/RouteError';
7
+ import { RouteError } from '@src/common/classes';
8
8
 
9
9
  import { IUser } from '@src/models/User';
10
10
 
@@ -1,4 +1,4 @@
1
- import RouteError from '@src/common/RouteError';
1
+ import { RouteError } from '@src/common/classes';
2
2
  import HttpStatusCodes from '@src/common/HttpStatusCodes';
3
3
 
4
4
  import UserRepo from '@src/repos/UserRepo';
@@ -1,9 +1,9 @@
1
- import { Request, Response } from 'express';
2
1
  import jsonwebtoken from 'jsonwebtoken';
3
2
 
4
3
  import HttpStatusCodes from '@src/common/HttpStatusCodes';
5
- import RouteError from '@src/common/RouteError';
4
+ import { RouteError } from '@src/common/classes';
6
5
  import EnvVars from '@src/common/EnvVars';
6
+ import { IReq, IRes } from '@src/routes/common/types';
7
7
 
8
8
 
9
9
  // **** Variables **** //
@@ -25,7 +25,7 @@ const Options = {
25
25
  /**
26
26
  * Get session data from request object (i.e. ISessionUser)
27
27
  */
28
- function getSessionData<T>(req: Request): Promise<string | T | undefined> {
28
+ function getSessionData<T>(req: IReq): Promise<string | T | undefined> {
29
29
  const { Key } = EnvVars.CookieProps,
30
30
  jwt = req.signedCookies[Key];
31
31
  return _decode(jwt);
@@ -52,9 +52,9 @@ function _decode<T>(jwt: string): Promise<string | undefined | T> {
52
52
  * Add a JWT to the response
53
53
  */
54
54
  async function addSessionData(
55
- res: Response,
55
+ res: IRes,
56
56
  data: string | object,
57
- ): Promise<Response> {
57
+ ): Promise<IRes> {
58
58
  if (!res || !data) {
59
59
  throw new RouteError(HttpStatusCodes.BAD_REQUEST, Errors.ParamFalsey);
60
60
  }
@@ -79,7 +79,7 @@ function _sign(data: string | object | Buffer): Promise<string> {
79
79
  /**
80
80
  * Remove cookie
81
81
  */
82
- function clearCookie(res: Response): Response {
82
+ function clearCookie(res: IRes): IRes {
83
83
  const { Key, Options } = EnvVars.CookieProps;
84
84
  return res.clearCookie(Key, Options);
85
85
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "express-generator-typescript",
3
- "version": "2.4.12",
3
+ "version": "2.4.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,20 +0,0 @@
1
- import HttpStatusCodes from '@src/common/HttpStatusCodes';
2
-
3
-
4
- /**
5
- * Error with status code and message
6
- */
7
- class RouteError extends Error {
8
-
9
- public status: HttpStatusCodes;
10
-
11
- public constructor(status: HttpStatusCodes, message: string) {
12
- super(message);
13
- this.status = status;
14
- }
15
- }
16
-
17
-
18
- // **** Export default **** //
19
-
20
- export default RouteError;
@@ -1,20 +0,0 @@
1
- import HttpStatusCodes from '@src/common/HttpStatusCodes';
2
-
3
-
4
- /**
5
- * Error with status code and message
6
- */
7
- class RouteError extends Error {
8
-
9
- public status: HttpStatusCodes;
10
-
11
- public constructor(status: HttpStatusCodes, message: string) {
12
- super(message);
13
- this.status = status;
14
- }
15
- }
16
-
17
-
18
- // **** Export default **** //
19
-
20
- export default RouteError;