express-generator-typescript 1.10.2 → 2.0.1

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 (120) hide show
  1. package/README.md +37 -27
  2. package/bin/cli.js +2 -15
  3. package/lib/cli.js +1 -15
  4. package/lib/express-generator-typescript.js +11 -21
  5. package/lib/project-files/.eslintrc.json +16 -2
  6. package/lib/project-files/build.ts +2 -2
  7. package/lib/project-files/package.json +15 -5
  8. package/lib/project-files/spec/nodemon.json +1 -1
  9. package/lib/{auth-proj → project-files}/spec/support/login-agent.ts +6 -8
  10. package/lib/{auth-proj → project-files}/spec/tests/auth.spec.ts +18 -32
  11. package/lib/project-files/spec/tests/users.spec.ts +31 -22
  12. package/lib/project-files/spec/types/supertest/index.d.ts +14 -0
  13. package/lib/project-files/src/models/user-model.ts +17 -2
  14. package/lib/project-files/src/pre-start/env/development.env +9 -0
  15. package/lib/project-files/src/pre-start/env/production.env +10 -0
  16. package/lib/project-files/src/pre-start/env/test.env +9 -0
  17. package/lib/{auth-proj → project-files}/src/public/scripts/http.js +0 -0
  18. package/lib/{auth-proj → project-files}/src/public/scripts/login.js +0 -0
  19. package/lib/{auth-proj → project-files}/src/public/scripts/users.js +0 -0
  20. package/lib/{auth-proj → project-files}/src/public/stylesheets/login.css +0 -0
  21. package/lib/{auth-proj → project-files}/src/public/stylesheets/users.css +0 -0
  22. package/lib/project-files/src/repos/mock-orm.ts +2 -2
  23. package/lib/project-files/src/repos/user-repo.ts +1 -1
  24. package/lib/project-files/src/routes/api.ts +9 -6
  25. package/lib/{auth-proj → project-files}/src/routes/auth-router.ts +15 -7
  26. package/lib/{auth-proj → project-files}/src/routes/middleware.ts +7 -8
  27. package/lib/project-files/src/routes/user-router.ts +12 -16
  28. package/lib/project-files/src/server.ts +82 -73
  29. package/lib/{auth-proj → project-files}/src/services/auth-service.ts +0 -0
  30. package/lib/project-files/src/services/user-service.ts +8 -8
  31. package/lib/project-files/src/shared/env-vars.ts +18 -0
  32. package/lib/project-files/src/shared/errors.ts +11 -0
  33. package/lib/project-files/src/types/express/index.d.ts +27 -5
  34. package/lib/{auth-proj → project-files}/src/util/jwt-util.ts +3 -8
  35. package/lib/{auth-proj → project-files}/src/views/login.html +0 -0
  36. package/lib/{auth-proj → project-files}/src/views/users.html +0 -0
  37. package/lib/project-files/tsconfig.json +3 -0
  38. package/package.json +1 -1
  39. package/chat-screenshot.png +0 -0
  40. package/lib/auth-proj/.eslintignore +0 -1
  41. package/lib/auth-proj/.eslintrc.json +0 -27
  42. package/lib/auth-proj/build.ts +0 -64
  43. package/lib/auth-proj/gitignore +0 -3
  44. package/lib/auth-proj/package.json +0 -73
  45. package/lib/auth-proj/spec/index.ts +0 -57
  46. package/lib/auth-proj/spec/loadEnv.ts +0 -10
  47. package/lib/auth-proj/spec/nodemon.json +0 -6
  48. package/lib/auth-proj/spec/support/jasmine.json +0 -11
  49. package/lib/auth-proj/spec/tests/users.spec.ts +0 -283
  50. package/lib/auth-proj/src/index.ts +0 -14
  51. package/lib/auth-proj/src/models/user-model.ts +0 -56
  52. package/lib/auth-proj/src/pre-start/env/development.env +0 -23
  53. package/lib/auth-proj/src/pre-start/env/production.env +0 -24
  54. package/lib/auth-proj/src/pre-start/env/test.env +0 -23
  55. package/lib/auth-proj/src/pre-start/index.ts +0 -28
  56. package/lib/auth-proj/src/repos/database.json +0 -1
  57. package/lib/auth-proj/src/repos/mock-orm.ts +0 -41
  58. package/lib/auth-proj/src/repos/user-repo.ts +0 -88
  59. package/lib/auth-proj/src/routes/api.ts +0 -17
  60. package/lib/auth-proj/src/routes/user-router.ts +0 -78
  61. package/lib/auth-proj/src/server.ts +0 -82
  62. package/lib/auth-proj/src/services/user-service.ts +0 -52
  63. package/lib/auth-proj/src/shared/env-vars.ts +0 -20
  64. package/lib/auth-proj/src/shared/errors.ts +0 -45
  65. package/lib/auth-proj/src/shared/functions.ts +0 -18
  66. package/lib/auth-proj/src/types/express/index.d.ts +0 -23
  67. package/lib/auth-proj/tsconfig.json +0 -100
  68. package/lib/auth-proj/tsconfig.prod.json +0 -11
  69. package/lib/project-files/src/public/scripts/index.js +0 -183
  70. package/lib/project-files/src/public/stylesheets/style.css +0 -33
  71. package/lib/project-files/src/views/index.html +0 -31
  72. package/lib/socket-io/.eslintignore +0 -1
  73. package/lib/socket-io/.eslintrc.json +0 -27
  74. package/lib/socket-io/build.ts +0 -64
  75. package/lib/socket-io/gitignore +0 -3
  76. package/lib/socket-io/package.json +0 -75
  77. package/lib/socket-io/spec/index.ts +0 -57
  78. package/lib/socket-io/spec/loadEnv.ts +0 -10
  79. package/lib/socket-io/spec/nodemon.json +0 -6
  80. package/lib/socket-io/spec/support/jasmine.json +0 -11
  81. package/lib/socket-io/spec/support/login-agent.ts +0 -49
  82. package/lib/socket-io/spec/tests/auth.spec.ts +0 -159
  83. package/lib/socket-io/spec/tests/chat.spec.ts +0 -150
  84. package/lib/socket-io/spec/tests/users.spec.ts +0 -283
  85. package/lib/socket-io/src/index.ts +0 -14
  86. package/lib/socket-io/src/models/user-model.ts +0 -56
  87. package/lib/socket-io/src/pre-start/env/development.env +0 -23
  88. package/lib/socket-io/src/pre-start/env/production.env +0 -24
  89. package/lib/socket-io/src/pre-start/env/test.env +0 -23
  90. package/lib/socket-io/src/pre-start/index.ts +0 -28
  91. package/lib/socket-io/src/public/scripts/chat.js +0 -87
  92. package/lib/socket-io/src/public/scripts/http.js +0 -24
  93. package/lib/socket-io/src/public/scripts/index.js +0 -16
  94. package/lib/socket-io/src/public/scripts/login.js +0 -17
  95. package/lib/socket-io/src/public/scripts/users.js +0 -148
  96. package/lib/socket-io/src/public/stylesheets/chat.css +0 -43
  97. package/lib/socket-io/src/public/stylesheets/index.css +0 -13
  98. package/lib/socket-io/src/public/stylesheets/login.css +0 -20
  99. package/lib/socket-io/src/public/stylesheets/users.css +0 -40
  100. package/lib/socket-io/src/repos/database.json +0 -38
  101. package/lib/socket-io/src/repos/mock-orm.ts +0 -41
  102. package/lib/socket-io/src/repos/user-repo.ts +0 -88
  103. package/lib/socket-io/src/routes/api.ts +0 -19
  104. package/lib/socket-io/src/routes/auth-router.ts +0 -67
  105. package/lib/socket-io/src/routes/chat-router.ts +0 -88
  106. package/lib/socket-io/src/routes/middleware.ts +0 -55
  107. package/lib/socket-io/src/routes/user-router.ts +0 -76
  108. package/lib/socket-io/src/server.ts +0 -100
  109. package/lib/socket-io/src/services/auth-service.ts +0 -38
  110. package/lib/socket-io/src/services/user-service.ts +0 -52
  111. package/lib/socket-io/src/shared/env-vars.ts +0 -20
  112. package/lib/socket-io/src/shared/errors.ts +0 -56
  113. package/lib/socket-io/src/shared/functions.ts +0 -18
  114. package/lib/socket-io/src/types/express/index.d.ts +0 -23
  115. package/lib/socket-io/src/util/jwt-util.ts +0 -52
  116. package/lib/socket-io/src/views/chat.html +0 -51
  117. package/lib/socket-io/src/views/login.html +0 -35
  118. package/lib/socket-io/src/views/users.html +0 -47
  119. package/lib/socket-io/tsconfig.json +0 -100
  120. package/lib/socket-io/tsconfig.prod.json +0 -11
@@ -1,10 +1,16 @@
1
1
  // **** Types **** //
2
2
 
3
- // User schema
3
+ export enum UserRoles {
4
+ Standard,
5
+ Admin,
6
+ }
7
+
4
8
  export interface IUser {
5
9
  id: number;
6
10
  name: string;
7
11
  email: string;
12
+ pwdHash: string;
13
+ role: UserRoles;
8
14
  }
9
15
 
10
16
 
@@ -13,11 +19,18 @@ export interface IUser {
13
19
  /**
14
20
  * Get a new User object.
15
21
  */
16
- function _new(name: string, email: string): IUser {
22
+ function _new(
23
+ name: string,
24
+ email: string,
25
+ role?: UserRoles,
26
+ pwdHash?: string,
27
+ ): IUser {
17
28
  return {
18
29
  id: -1,
19
30
  email,
20
31
  name,
32
+ role: (role ?? UserRoles.Standard),
33
+ pwdHash: (pwdHash ?? ''),
21
34
  };
22
35
  }
23
36
 
@@ -29,6 +42,8 @@ function copy(user: IUser): IUser {
29
42
  id: user.id,
30
43
  email: user.email,
31
44
  name: user.name,
45
+ role: user.role,
46
+ pwdHash: user.pwdHash,
32
47
  };
33
48
  }
34
49
 
@@ -12,3 +12,12 @@ JET_LOGGER_MODE=CONSOLE
12
12
  JET_LOGGER_FILEPATH=jet-logger.log
13
13
  JET_LOGGER_TIMESTAMP=TRUE
14
14
  JET_LOGGER_FORMAT=LINE
15
+
16
+ ## Authentication ##
17
+ COOKIE_DOMAIN=localhost
18
+ COOKIE_PATH=/
19
+ SECURE_COOKIE=false
20
+ JWT_SECRET=xxxxxxxxxxxxxx
21
+ COOKIE_SECRET=xxxxxxxxxxxxxx
22
+ # expires in 3 days
23
+ COOKIE_EXP=259200000
@@ -12,3 +12,13 @@ JET_LOGGER_MODE=FILE
12
12
  JET_LOGGER_FILEPATH=jet-logger.log
13
13
  JET_LOGGER_TIMESTAMP=TRUE
14
14
  JET_LOGGER_FORMAT=LINE
15
+
16
+ ## Authentication ##
17
+ # SECURE_COOKIE 'false' here for demo-ing. But ideally should be true.
18
+ COOKIE_DOMAIN=localhost
19
+ COOKIE_PATH=/
20
+ SECURE_COOKIE=false
21
+ JWT_SECRET=xxxxxxxxxxxxxx
22
+ COOKIE_SECRET=xxxxxxxxxxxxxx
23
+ # expires in 3 days
24
+ COOKIE_EXP=259200000
@@ -12,3 +12,12 @@ JET_LOGGER_MODE=CONSOLE
12
12
  JET_LOGGER_FILEPATH=jet-logger.log
13
13
  JET_LOGGER_TIMESTAMP=TRUE
14
14
  JET_LOGGER_FORMAT=LINE
15
+
16
+ ## Authentication ##
17
+ COOKIE_DOMAIN=localhost
18
+ COOKIE_PATH=/
19
+ SECURE_COOKIE=false
20
+ JWT_SECRET=xxxxxxxxxxxxxx
21
+ COOKIE_SECRET=xxxxxxxxxxxxxx
22
+ # expires in 3 days
23
+ COOKIE_EXP=259200000
@@ -36,6 +36,6 @@ function saveDb(db: IDb): Promise<void> {
36
36
  // **** Export default **** //
37
37
 
38
38
  export default {
39
- openDb,
40
- saveDb,
39
+ openDb,
40
+ saveDb,
41
41
  } as const;
@@ -6,7 +6,7 @@ import orm from './mock-orm';
6
6
  // **** Functions **** //
7
7
 
8
8
  /**
9
- * Get one user
9
+ * Get one user.
10
10
  */
11
11
  async function getOne(email: string): Promise<IUser | null> {
12
12
  const db = await orm.openDb();
@@ -1,14 +1,17 @@
1
1
  import { Router } from 'express';
2
+ import { adminMw } from './middleware';
3
+ import authRouter from './auth-router';
2
4
  import userRouter from './user-router';
3
5
 
4
6
 
5
- // Export the base-router
6
- const baseRouter = Router();
7
+ // Init
8
+ const apiRouter = Router();
7
9
 
8
- // Setup routers
9
- baseRouter.use('/users', userRouter);
10
+ // Add api routes
11
+ apiRouter.use('/auth', authRouter);
12
+ apiRouter.use('/users', adminMw, userRouter);
10
13
 
11
14
 
12
- // *** Export default **** //
15
+ // **** Export default **** //
13
16
 
14
- export default baseRouter;
17
+ export default apiRouter;
@@ -4,13 +4,23 @@ import StatusCodes from 'http-status-codes';
4
4
  import authService from '@services/auth-service';
5
5
  import { ParamMissingError } from '@shared/errors';
6
6
  import envVars from 'src/shared/env-vars';
7
+ import { IReq } from 'src/types/express';
8
+
9
+
10
+ // **** Types **** //
11
+
12
+ interface ILoginReq {
13
+ email: string;
14
+ password: string;
15
+ }
7
16
 
8
17
 
9
18
  // **** Variables **** //
10
19
 
11
- // Misc
12
- const router = Router(),
13
- { OK } = StatusCodes;
20
+ const router = Router();
21
+
22
+ // Status codes
23
+ const { OK } = StatusCodes;
14
24
 
15
25
  // Paths
16
26
  export const p = {
@@ -24,15 +34,13 @@ export const p = {
24
34
  /**
25
35
  * Login a user.
26
36
  */
27
- router.post(p.login, async (req: Request, res: Response) => {
28
- // Check email and password present
37
+ router.post(p.login, async (req: IReq<ILoginReq>, res: Response) => {
29
38
  const { email, password } = req.body;
30
39
  if (!email || !password) {
31
40
  throw new ParamMissingError();
32
41
  }
33
- // Get jwt
34
- const jwt = await authService.login(email, password);
35
42
  // Add jwt to cookie
43
+ const jwt = await authService.login(email, password);
36
44
  const { key, options } = envVars.cookieProps;
37
45
  res.cookie(key, jwt, options);
38
46
  // Return
@@ -1,10 +1,10 @@
1
1
  import StatusCodes from 'http-status-codes';
2
2
  import { Request, Response, NextFunction } from 'express';
3
- import { JwtPayload } from 'jsonwebtoken';
4
3
 
5
4
  import { IUser, UserRoles } from '@models/user-model';
6
5
  import envVars from 'src/shared/env-vars';
7
6
  import jwtUtil from '@util/jwt-util';
7
+ import { JwtPayload } from 'jsonwebtoken';
8
8
 
9
9
 
10
10
  // **** Variables **** //
@@ -26,25 +26,24 @@ export interface ISessionUser extends JwtPayload {
26
26
  // **** Functions **** //
27
27
 
28
28
  /**
29
- * Middleware to verify if user is an admin.
29
+ * Middleware to verify if user logged in.
30
30
  */
31
31
  export async function adminMw(req: Request, res: Response, next: NextFunction) {
32
- // Try
33
32
  try {
34
33
  // Extract the token
35
- const jwt = req.signedCookies[envVars.cookieProps.key];
34
+ const cookieName = envVars.cookieProps.key,
35
+ jwt = req.signedCookies[cookieName];
36
36
  if (!jwt) {
37
37
  throw Error(jwtNotPresentErr);
38
38
  }
39
39
  // Make sure user role is an admin
40
- const clientData = await jwtUtil.decode(jwt);
41
- if (typeof clientData === 'object' && clientData.role === UserRoles.Admin) {
42
- res.locals.sessionUser = clientData as ISessionUser;
40
+ const clientData = await jwtUtil.decode<ISessionUser>(jwt);
41
+ if (clientData.role === UserRoles.Admin) {
42
+ res.locals.sessionUser = clientData;
43
43
  next();
44
44
  } else {
45
45
  throw Error(jwtNotPresentErr);
46
46
  }
47
- // Catch
48
47
  } catch (err: unknown) {
49
48
  let error;
50
49
  if (typeof err === 'string') {
@@ -3,13 +3,15 @@ import { Request, Response, Router } from 'express';
3
3
 
4
4
  import userService from '@services/user-service';
5
5
  import { ParamMissingError } from '@shared/errors';
6
+ import { IUser } from '@models/user-model';
7
+ import { IReq } from 'src/types/express';
6
8
 
7
9
 
8
10
  // **** Variables **** //
9
11
 
10
12
  // Misc
11
- const router = Router();
12
- const { CREATED, OK } = StatusCodes;
13
+ const router = Router(),
14
+ { CREATED, OK } = StatusCodes;
13
15
 
14
16
  // Paths
15
17
  export const p = {
@@ -23,51 +25,45 @@ export const p = {
23
25
  // **** Routes **** //
24
26
 
25
27
  /**
26
- * Get all users
28
+ * Get all users.
27
29
  */
28
30
  router.get(p.get, async (_: Request, res: Response) => {
29
- const users = await userService.getAll();
30
- return res.status(OK).json({users});
31
+ const users = await userService.getAll();
32
+ return res.status(OK).json({ users });
31
33
  });
32
34
 
33
35
  /**
34
- * Add one user
36
+ * Add one user.
35
37
  */
36
- router.post(p.add, async (req: Request, res: Response) => {
38
+ router.post(p.add, async (req: IReq<{user: IUser}>, res: Response) => {
37
39
  const { user } = req.body;
38
- // Check param
39
40
  if (!user) {
40
41
  throw new ParamMissingError();
41
42
  }
42
- // Fetch data
43
43
  await userService.addOne(user);
44
44
  return res.status(CREATED).end();
45
45
  });
46
46
 
47
47
  /**
48
- * Update one user
48
+ * Update one user.
49
49
  */
50
- router.put(p.update, async (req: Request, res: Response) => {
50
+ router.put(p.update, async (req: IReq<{user: IUser}>, res: Response) => {
51
51
  const { user } = req.body;
52
- // Check param
53
52
  if (!user) {
54
53
  throw new ParamMissingError();
55
54
  }
56
- // Fetch data
57
55
  await userService.updateOne(user);
58
56
  return res.status(OK).end();
59
57
  });
60
58
 
61
59
  /**
62
- * Delete one user
60
+ * Delete one user.
63
61
  */
64
62
  router.delete(p.delete, async (req: Request, res: Response) => {
65
63
  const { id } = req.params;
66
- // Check param
67
64
  if (!id) {
68
65
  throw new ParamMissingError();
69
66
  }
70
- // Fetch data
71
67
  await userService.delete(Number(id));
72
68
  return res.status(OK).end();
73
69
  });
@@ -1,73 +1,82 @@
1
- import cookieParser from 'cookie-parser';
2
- import morgan from 'morgan';
3
- import path from 'path';
4
- import helmet from 'helmet';
5
- import logger from 'jet-logger';
6
-
7
- import express, { Request, Response, NextFunction } from 'express';
8
- import StatusCodes from 'http-status-codes';
9
- import 'express-async-errors';
10
-
11
- import apiRouter from '@routes/api';
12
- import envVars from '@shared/env-vars';
13
- import { CustomError } from '@shared/errors';
14
-
15
-
16
- // **** Variables **** //
17
-
18
- const app = express();
19
-
20
-
21
- // **** Set basic express settings ****# //
22
-
23
- // Common middlewares
24
- app.use(express.json());
25
- app.use(express.urlencoded({extended: true}));
26
- app.use(cookieParser());
27
-
28
- // Show routes called in console during development
29
- if (envVars.nodeEnv === 'development') {
30
- app.use(morgan('dev'));
31
- }
32
-
33
- // Security (helmet recommended in express docs)
34
- if (envVars.nodeEnv === 'production') {
35
- app.use(helmet());
36
- }
37
-
38
-
39
- // **** Add API Routes ****# //
40
-
41
- // Add api router
42
- app.use('/api', apiRouter);
43
-
44
- // Error handling
45
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
46
- app.use((err: Error | CustomError, req: Request, res: Response, _: NextFunction) => {
47
- logger.err(err, true);
48
- const status = (err instanceof CustomError ? err.HttpStatus : StatusCodes.BAD_REQUEST);
49
- return res.status(status).json({
50
- error: err.message,
51
- });
52
- });
53
-
54
-
55
- // **** Serve front-end content **** //
56
-
57
- // Set views dir
58
- const viewsDir = path.join(__dirname, 'views');
59
- app.set('views', viewsDir);
60
-
61
- // Set static dir
62
- const staticDir = path.join(__dirname, 'public');
63
- app.use(express.static(staticDir));
64
-
65
- // Serve index.html file
66
- app.get('*', (_: Request, res: Response) => {
67
- res.sendFile('index.html', {root: viewsDir});
68
- });
69
-
70
-
71
- // **** Export default **** //
72
-
73
- export default app;
1
+ import cookieParser from 'cookie-parser';
2
+ import morgan from 'morgan';
3
+ import path from 'path';
4
+ import helmet from 'helmet';
5
+ import StatusCodes from 'http-status-codes';
6
+ import express, { Request, Response, NextFunction } from 'express';
7
+
8
+ import 'express-async-errors';
9
+
10
+ import BaseRouter from './routes/api';
11
+ import logger from 'jet-logger';
12
+ import { CustomError } from '@shared/errors';
13
+ import envVars from '@shared/env-vars';
14
+
15
+
16
+ // **** Init express **** //
17
+
18
+ const app = express();
19
+
20
+
21
+ // **** Set basic express settings **** //
22
+
23
+ app.use(express.json());
24
+ app.use(express.urlencoded({extended: true}));
25
+ app.use(cookieParser(envVars.cookieProps.secret));
26
+
27
+ // Show routes called in console during development
28
+ if (envVars.nodeEnv === 'development') {
29
+ app.use(morgan('dev'));
30
+ }
31
+
32
+ // Security
33
+ if (envVars.nodeEnv === 'production') {
34
+ app.use(helmet());
35
+ }
36
+
37
+
38
+ // **** Add API routes **** //
39
+
40
+ // Add APIs
41
+ app.use('/api', BaseRouter);
42
+
43
+ // Error handling
44
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
45
+ app.use((err: Error | CustomError, req: Request, res: Response, _: NextFunction) => {
46
+ logger.err(err, true);
47
+ const status = (err instanceof CustomError ? err.HttpStatus : StatusCodes.BAD_REQUEST);
48
+ return res.status(status).json({
49
+ error: err.message,
50
+ });
51
+ });
52
+
53
+
54
+ // **** Serve front-end content **** //
55
+
56
+ // Set views directory (html)
57
+ const viewsDir = path.join(__dirname, 'views');
58
+ app.set('views', viewsDir);
59
+
60
+ // Set static directory (js and css).
61
+ const staticDir = path.join(__dirname, 'public');
62
+ app.use(express.static(staticDir));
63
+
64
+ // Nav to login pg by default
65
+ app.get('/', (_: Request, res: Response) => {
66
+ res.sendFile('login.html', {root: viewsDir});
67
+ });
68
+
69
+ // Redirect to login if not logged in.
70
+ app.get('/users', (req: Request, res: Response) => {
71
+ const jwt = req.signedCookies[envVars.cookieProps.key];
72
+ if (!jwt) {
73
+ res.redirect('/');
74
+ } else {
75
+ res.sendFile('users.html', {root: viewsDir});
76
+ }
77
+ });
78
+
79
+
80
+ // **** Export default **** //
81
+
82
+ export default app;
@@ -6,21 +6,21 @@ import { UserNotFoundError } from '@shared/errors';
6
6
  // **** Functions **** //
7
7
 
8
8
  /**
9
- * Get all users
9
+ * Get all users.
10
10
  */
11
11
  function getAll(): Promise<IUser[]> {
12
12
  return userRepo.getAll();
13
13
  }
14
14
 
15
15
  /**
16
- * Add one user
16
+ * Add one user.
17
17
  */
18
18
  function addOne(user: IUser): Promise<void> {
19
19
  return userRepo.add(user);
20
20
  }
21
21
 
22
22
  /**
23
- * Update one user
23
+ * Update one user.
24
24
  */
25
25
  async function updateOne(user: IUser): Promise<void> {
26
26
  const persists = await userRepo.persists(user.id);
@@ -31,7 +31,7 @@ async function updateOne(user: IUser): Promise<void> {
31
31
  }
32
32
 
33
33
  /**
34
- * Delete a user by their id
34
+ * Delete a user by their id.
35
35
  */
36
36
  async function _delete(id: number): Promise<void> {
37
37
  const persists = await userRepo.persists(id);
@@ -45,8 +45,8 @@ async function _delete(id: number): Promise<void> {
45
45
  // **** Export default **** //
46
46
 
47
47
  export default {
48
- getAll,
49
- addOne,
50
- updateOne,
51
- delete: _delete,
48
+ getAll,
49
+ addOne,
50
+ updateOne,
51
+ delete: _delete,
52
52
  } as const;
@@ -1,4 +1,22 @@
1
+ /* eslint-disable node/no-process-env */
2
+
1
3
  export default {
2
4
  nodeEnv: (process.env.NODE_ENV ?? ''),
3
5
  port: (process.env.PORT ?? 0),
6
+ cookieProps: {
7
+ key: 'ExpressGeneratorTs',
8
+ secret: (process.env.COOKIE_SECRET ?? ''),
9
+ options: {
10
+ httpOnly: true,
11
+ signed: true,
12
+ path: (process.env.COOKIE_PATH ?? ''),
13
+ maxAge: Number(process.env.COOKIE_EXP ?? 0),
14
+ domain: (process.env.COOKIE_DOMAIN ?? ''),
15
+ secure: (process.env.SECURE_COOKIE === 'true'),
16
+ },
17
+ },
18
+ jwt: {
19
+ secret: (process.env.JWT_SECRET ?? ''),
20
+ exp: (process.env.COOKIE_EXP ?? ''), // exp at the same time as the cookie
21
+ },
4
22
  } as const;
@@ -32,3 +32,14 @@ export class UserNotFoundError extends CustomError {
32
32
  super(UserNotFoundError.Msg, UserNotFoundError.HttpStatus);
33
33
  }
34
34
  }
35
+
36
+
37
+ export class UnauthorizedError extends CustomError {
38
+
39
+ public static readonly Msg = 'Login failed';
40
+ public static readonly HttpStatus = HttpStatusCodes.UNAUTHORIZED;
41
+
42
+ constructor() {
43
+ super(UnauthorizedError.Msg, UnauthorizedError.HttpStatus);
44
+ }
45
+ }
@@ -1,12 +1,34 @@
1
- import { IUser } from "@models/user-model";
1
+ import 'express';
2
+ import * as e from 'express';
3
+ import { Query } from 'express-serve-static-core';
2
4
 
5
+ import { ISessionUser } from '@routes/middleware';
6
+
7
+
8
+
9
+ // **** Declaration Merging **** //
3
10
 
4
11
  declare module 'express' {
5
- export interface Request {
6
- body: {
7
- user?: IUser
8
- email?: string;
12
+
13
+ export interface Request {
14
+ signedCookies: Record<string, string>;
15
+ }
16
+
17
+ export interface Response {
18
+ locals: {
19
+ sessionUser: ISessionUser;
9
20
  };
10
21
  }
11
22
  }
12
23
 
24
+
25
+ // **** Generics for Request Object **** //
26
+
27
+ export interface IReq<T> extends e.Request {
28
+ body: T;
29
+ }
30
+
31
+ export interface IReqQuery<T extends Query, U = void> extends e.Request {
32
+ query: T;
33
+ body?: U;
34
+ }
@@ -15,11 +15,6 @@ const options = {
15
15
  };
16
16
 
17
17
 
18
- // **** Types **** //
19
-
20
- type TDecoded = string | JwtPayload | undefined;
21
-
22
-
23
18
  // **** Functions **** //
24
19
 
25
20
  /**
@@ -28,7 +23,7 @@ type TDecoded = string | JwtPayload | undefined;
28
23
  function sign(data: JwtPayload): Promise<string> {
29
24
  return new Promise((resolve, reject) => {
30
25
  jsonwebtoken.sign(data, envVars.jwt.secret, options, (err, token) => {
31
- err ? reject(err) : resolve(token || '');
26
+ return err ? reject(err) : resolve(token || '');
32
27
  });
33
28
  });
34
29
  }
@@ -36,10 +31,10 @@ function sign(data: JwtPayload): Promise<string> {
36
31
  /**
37
32
  * Decrypt JWT and extract client data.
38
33
  */
39
- function decode(jwt: string): Promise<TDecoded> {
34
+ function decode<T>(jwt: string): Promise<T> {
40
35
  return new Promise((res, rej) => {
41
36
  jsonwebtoken.verify(jwt, envVars.jwt.secret, (err, decoded) => {
42
- return err ? rej(errors.validation) : res(decoded);
37
+ return err ? rej(errors.validation) : res(decoded as T);
43
38
  });
44
39
  });
45
40
  }
@@ -83,6 +83,9 @@
83
83
  ],
84
84
  "@routes/*": [
85
85
  "src/routes/*"
86
+ ],
87
+ "@util/*": [
88
+ "src/util/*"
86
89
  ]
87
90
  },
88
91
  "useUnknownInCatchVariables": false
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "express-generator-typescript",
3
- "version": "1.10.2",
3
+ "version": "2.0.1",
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",
Binary file
@@ -1 +0,0 @@
1
- src/public/