express-generator-typescript 2.0.3 → 2.0.6

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/bin/cli.js CHANGED
@@ -10,26 +10,27 @@ const path = require('path');
10
10
  const expressGenTs = require('../lib/express-generator-typescript');
11
11
 
12
12
 
13
- (() => {
14
- console.log('Setting up new Express/TypeScript project...');
15
- // const opts = processOptions(process.argv.slice(2));
16
- // Process options
17
- let destination = 'express-gen-ts';
18
- let useYarn = false;
19
- const args = process.argv.slice(2);
20
- let idx = -1;
21
- idx = args.indexOf('--use-yarn');
22
- if (idx > -1) {
23
- useYarn = true;
24
- args.splice(idx, 1);
25
- }
26
- if (args.length > 0) {
27
- destination = args[0];
28
- }
29
- destination = path.join(process.cwd(), destination);
30
- // Creating new project finished
31
- expressGenTs(destination, useYarn).then(() => {
32
- console.log('Project setup complete!');
33
- });
34
- })();
35
-
13
+ // Start
14
+ console.log('Setting up new Express/TypeScript project...');
15
+
16
+ // Setup use yarn
17
+ let useYarn = false;
18
+ const args = process.argv.slice(2);
19
+ let idx = -1;
20
+ idx = args.indexOf('--use-yarn');
21
+ if (idx > -1) {
22
+ useYarn = true;
23
+ args.splice(idx, 1);
24
+ }
25
+
26
+ // Setup destination
27
+ let destination = 'express-gen-ts';
28
+ if (args.length > 0) {
29
+ destination = args[0];
30
+ }
31
+ destination = path.join(process.cwd(), destination);
32
+
33
+ // Creating new project finished
34
+ expressGenTs(destination, useYarn).then(() => {
35
+ console.log('Project setup complete!');
36
+ });
package/lib/cli.js CHANGED
@@ -10,25 +10,27 @@ const path = require('path');
10
10
  const expressGenTs = require('../lib/express-generator-typescript');
11
11
 
12
12
 
13
- (() => {
14
- console.log('Setting up new Express/TypeScript project...');
15
- // const opts = processOptions(process.argv.slice(2));
16
- // Process options
17
- let destination = 'express-gen-ts';
18
- let useYarn = false;
19
- const args = process.argv.slice(2);
20
- let idx = -1;
21
- idx = args.indexOf('--use-yarn');
22
- if (idx > -1) {
23
- useYarn = true;
24
- args.splice(idx, 1);
25
- }
26
- if (args.length > 0) {
27
- destination = args[0];
28
- }
29
- destination = path.join(process.cwd(), destination);
30
- // Creating new project finished
31
- expressGenTs(destination, useYarn).then(() => {
32
- console.log('Project setup complete!');
33
- });
34
- })();
13
+ // Start
14
+ console.log('Setting up new Express/TypeScript project...');
15
+
16
+ // Setup use yarn
17
+ let useYarn = false;
18
+ const args = process.argv.slice(2);
19
+ let idx = -1;
20
+ idx = args.indexOf('--use-yarn');
21
+ if (idx > -1) {
22
+ useYarn = true;
23
+ args.splice(idx, 1);
24
+ }
25
+
26
+ // Setup destination
27
+ let destination = 'express-gen-ts';
28
+ if (args.length > 0) {
29
+ destination = args[0];
30
+ }
31
+ destination = path.join(process.cwd(), destination);
32
+
33
+ // Creating new project finished
34
+ expressGenTs(destination, useYarn).then(() => {
35
+ console.log('Project setup complete!');
36
+ });
@@ -9,8 +9,8 @@ export interface IUser {
9
9
  id: number;
10
10
  name: string;
11
11
  email: string;
12
- pwdHash: string;
13
- role: UserRoles;
12
+ pwdHash?: string;
13
+ role?: UserRoles;
14
14
  }
15
15
 
16
16
 
@@ -47,10 +47,24 @@ function copy(user: IUser): IUser {
47
47
  };
48
48
  }
49
49
 
50
+ /**
51
+ * See if an object is an instance of User.
52
+ */
53
+ function instanceOf(arg: object): boolean {
54
+ return (
55
+ typeof arg === 'object' &&
56
+ 'id' in arg &&
57
+ 'email' in arg &&
58
+ 'name' in arg &&
59
+ 'role' in arg
60
+ );
61
+ }
62
+
50
63
 
51
64
  // **** Export default **** //
52
65
 
53
66
  export default {
54
67
  new: _new,
55
68
  copy,
69
+ instanceOf,
56
70
  };
@@ -34,7 +34,7 @@ function getUserDisplayEle(user) {
34
34
  <div class="normal-view">
35
35
  <div>Name: ${user.name}</div>
36
36
  <div>Email: ${user.email}</div>
37
- <button class="edit-user-btn" data-user-id="${user.id}">
37
+ <button class="edit-user-btn" data-user-id="${user.id}" data-user-role="${user.role}">
38
38
  Edit
39
39
  </button>
40
40
  <button class="delete-user-btn" data-user-id="${user.id}">
@@ -90,8 +90,10 @@ function addUser() {
90
90
  var emailInput = document.getElementById('email-input');
91
91
  var data = {
92
92
  user: {
93
+ id: -1,
93
94
  name: nameInput.value,
94
95
  email: emailInput.value,
96
+ role: 0,
95
97
  },
96
98
  };
97
99
  // Call api
@@ -128,11 +130,13 @@ function submitEdit(ele) {
128
130
  var nameInput = userEle.getElementsByClassName('name-edit-input')[0];
129
131
  var emailInput = userEle.getElementsByClassName('email-edit-input')[0];
130
132
  var id = ele.getAttribute('data-user-id');
133
+ var role = ele.getAttribute('data-user-role');
131
134
  var data = {
132
135
  user: {
136
+ id: Number(id),
133
137
  name: nameInput.value,
134
138
  email: emailInput.value,
135
- id: Number(id),
139
+ role: Number(role),
136
140
  },
137
141
  };
138
142
  Http
@@ -1,10 +1,10 @@
1
- import { Request, Response, Router } from 'express';
1
+ import { Router } from 'express';
2
2
  import StatusCodes from 'http-status-codes';
3
3
 
4
4
  import authService from '@services/auth-service';
5
- import { ParamMissingError } from '@shared/errors';
6
5
  import envVars from 'src/shared/env-vars';
7
- import { IReq } from '@shared/types';
6
+ import { IReq, IRes } from '@shared/types';
7
+ import validate from './validators';
8
8
 
9
9
 
10
10
  // **** Types **** //
@@ -34,11 +34,9 @@ export const p = {
34
34
  /**
35
35
  * Login a user.
36
36
  */
37
- router.post(p.login, async (req: IReq<ILoginReq>, res: Response) => {
37
+ router.post(p.login, async (req: IReq<ILoginReq>, res: IRes) => {
38
38
  const { email, password } = req.body;
39
- if (!email || !password) {
40
- throw new ParamMissingError();
41
- }
39
+ validate(email, password);
42
40
  // Add jwt to cookie
43
41
  const jwt = await authService.login(email, password);
44
42
  const { key, options } = envVars.cookieProps;
@@ -50,7 +48,7 @@ router.post(p.login, async (req: IReq<ILoginReq>, res: Response) => {
50
48
  /**
51
49
  * Logout the user.
52
50
  */
53
- router.get(p.logout, (_: Request, res: Response) => {
51
+ router.get(p.logout, (_: IReq, res: IRes) => {
54
52
  const { key, options } = envVars.cookieProps;
55
53
  res.clearCookie(key, options);
56
54
  return res.status(OK).end();
@@ -1,10 +1,10 @@
1
1
  import StatusCodes from 'http-status-codes';
2
- import { Request, Response, Router } from 'express';
2
+ import { Router } from 'express';
3
3
 
4
4
  import userService from '@services/user-service';
5
- import { ParamMissingError } from '@shared/errors';
6
- import { IUser } from '@models/user-model';
7
- import { IReq } from '@shared/types';
5
+ import User, { IUser } from '@models/user-model';
6
+ import { IReq, IRes } from '@shared/types';
7
+ import validate from './validators';
8
8
 
9
9
 
10
10
  // **** Variables **** //
@@ -27,7 +27,7 @@ export const p = {
27
27
  /**
28
28
  * Get all users.
29
29
  */
30
- router.get(p.get, async (_: Request, res: Response) => {
30
+ router.get(p.get, async (_: IReq, res: IRes) => {
31
31
  const users = await userService.getAll();
32
32
  return res.status(OK).json({ users });
33
33
  });
@@ -35,11 +35,10 @@ router.get(p.get, async (_: Request, res: Response) => {
35
35
  /**
36
36
  * Add one user.
37
37
  */
38
- router.post(p.add, async (req: IReq<{user: IUser}>, res: Response) => {
38
+ router.post(p.add, async (req: IReq<{user: IUser}>, res: IRes) => {
39
39
  const { user } = req.body;
40
- if (!user) {
41
- throw new ParamMissingError();
42
- }
40
+ validate([user, User.instanceOf]);
41
+ // Add user
43
42
  await userService.addOne(user);
44
43
  return res.status(CREATED).end();
45
44
  });
@@ -47,11 +46,10 @@ router.post(p.add, async (req: IReq<{user: IUser}>, res: Response) => {
47
46
  /**
48
47
  * Update one user.
49
48
  */
50
- router.put(p.update, async (req: IReq<{user: IUser}>, res: Response) => {
49
+ router.put(p.update, async (req: IReq<{user: IUser}>, res: IRes) => {
51
50
  const { user } = req.body;
52
- if (!user) {
53
- throw new ParamMissingError();
54
- }
51
+ validate([user, User.instanceOf]);
52
+ // Edit user
55
53
  await userService.updateOne(user);
56
54
  return res.status(OK).end();
57
55
  });
@@ -59,12 +57,11 @@ router.put(p.update, async (req: IReq<{user: IUser}>, res: Response) => {
59
57
  /**
60
58
  * Delete one user.
61
59
  */
62
- router.delete(p.delete, async (req: Request, res: Response) => {
63
- const { id } = req.params;
64
- if (!id) {
65
- throw new ParamMissingError();
66
- }
67
- await userService.delete(Number(id));
60
+ router.delete(p.delete, async (req: IReq, res: IRes) => {
61
+ const id = Number(req.params.id);
62
+ validate([id, 'number']);
63
+ // Delete user
64
+ await userService.delete(id);
68
65
  return res.status(OK).end();
69
66
  });
70
67
 
@@ -0,0 +1,60 @@
1
+ /**
2
+ * Put other validator functions here too that may be passed to the validate() function
3
+ */
4
+
5
+ import { ParamInvalidError } from '@shared/errors';
6
+
7
+
8
+ // **** Types **** //
9
+
10
+ type TParam = string | number | boolean | null | object;
11
+ type TValidatorFn = ((arg: TParam) => boolean);
12
+ type TParamFull = TParam | TValidatorFn;
13
+
14
+
15
+ // **** Functions **** //
16
+
17
+ /**
18
+ * Make sure parameter is of the specified type. If the type is not provided then 'string' is
19
+ * used as the default type. Instead of a type you can also pass a validator function
20
+ * which must return 'true' or 'false'. Return false if invalid.
21
+ *
22
+ * Example argument: [id, 'number], id is the incoming variable, 'number' is the type.
23
+ *
24
+ * Example 1: validate(email, [user, 'object'], [isAdmin, 'boolean'])
25
+ * Example 2: validate(password) // will check that password is a string
26
+ * Example 3: validate([isAdmin, 'boolean'])
27
+ * Example 4: validate([user, isInstanceOfUser])
28
+ */
29
+ function validate(...params: Array<TParam | TParamFull[]>): void {
30
+ for (const param of params) {
31
+ // If param is array check provided type
32
+ if (param instanceof Array) {
33
+ // Validator function provided
34
+ if (typeof param[1] === 'function') {
35
+ const fn = param[1];
36
+ if (!fn(param[0])) {
37
+ throw new Error(`Validator function ${fn.name} failed.`);
38
+ }
39
+ // If type is a number, need to do isNaN, cause type NaN is a 'number'.
40
+ // This could be an issue if you do Number(undefined)
41
+ } else if (param[1] === 'number') {
42
+ if (isNaN(param[0] as number)) {
43
+ throw new ParamInvalidError();
44
+ }
45
+ } else if (typeof param[0] !== param[1]) {
46
+ throw new ParamInvalidError();
47
+ }
48
+ // String is default if type is not provided
49
+ } else {
50
+ if (typeof param !== 'string') {
51
+ throw new ParamInvalidError();
52
+ }
53
+ }
54
+ }
55
+ }
56
+
57
+
58
+ // **** Export default **** //
59
+
60
+ export default validate;
@@ -17,7 +17,8 @@ async function login(email: string, password: string): Promise<string> {
17
17
  throw new UnauthorizedError();
18
18
  }
19
19
  // Check password
20
- const pwdPassed = await bcrypt.compare(password, user.pwdHash);
20
+ const hash = (user.pwdHash ?? '');
21
+ const pwdPassed = await bcrypt.compare(password, hash);
21
22
  if (!pwdPassed) {
22
23
  throw new UnauthorizedError();
23
24
  }
@@ -11,7 +11,6 @@ export abstract class CustomError extends Error {
11
11
  }
12
12
  }
13
13
 
14
-
15
14
  export class ParamMissingError extends CustomError {
16
15
 
17
16
  public static readonly Msg = 'One or more of the required parameters was missing.';
@@ -22,6 +21,15 @@ export class ParamMissingError extends CustomError {
22
21
  }
23
22
  }
24
23
 
24
+ export class ParamInvalidError extends CustomError {
25
+
26
+ public static readonly Msg = 'One or more of the required was missing or invalid.';
27
+ public static readonly HttpStatus = HttpStatusCodes.BAD_REQUEST;
28
+
29
+ constructor() {
30
+ super(ParamMissingError.Msg, ParamMissingError.HttpStatus);
31
+ }
32
+ }
25
33
 
26
34
  export class UserNotFoundError extends CustomError {
27
35
 
@@ -33,7 +41,6 @@ export class UserNotFoundError extends CustomError {
33
41
  }
34
42
  }
35
43
 
36
-
37
44
  export class UnauthorizedError extends CustomError {
38
45
 
39
46
  public static readonly Msg = 'Login failed';
@@ -42,4 +49,4 @@ export class UnauthorizedError extends CustomError {
42
49
  constructor() {
43
50
  super(UnauthorizedError.Msg, UnauthorizedError.HttpStatus);
44
51
  }
45
- }
52
+ }
@@ -1,6 +1,8 @@
1
1
  import logger from 'jet-logger';
2
2
 
3
3
 
4
+ // **** Functions **** //
5
+
4
6
  /**
5
7
  * Print an error object if it's truthy. Useful for testing.
6
8
  */
@@ -1,14 +1,22 @@
1
1
  import * as e from 'express';
2
2
  import { Query } from 'express-serve-static-core';
3
3
 
4
+ import { ISessionUser } from '@routes/middleware';
4
5
 
5
- // **** Generics for Request Object **** //
6
6
 
7
- export interface IReq<T> extends e.Request {
7
+ // **** Express **** //
8
+
9
+ export interface IReq<T = void> extends e.Request {
8
10
  body: T;
9
11
  }
10
12
 
11
13
  export interface IReqQuery<T extends Query, U = void> extends e.Request {
12
14
  query: T;
13
15
  body: U;
14
- }
16
+ }
17
+
18
+ export interface IRes extends e.Response {
19
+ locals: {
20
+ sessionUser: ISessionUser;
21
+ };
22
+ }
@@ -1,8 +1,5 @@
1
1
  import 'express';
2
2
 
3
- import { ISessionUser } from '@routes/middleware';
4
-
5
-
6
3
 
7
4
  // **** Declaration Merging **** //
8
5
 
@@ -11,10 +8,4 @@ declare module 'express' {
11
8
  export interface Request {
12
9
  signedCookies: Record<string, string>;
13
10
  }
14
-
15
- export interface Response {
16
- locals: {
17
- sessionUser: ISessionUser;
18
- };
19
- }
20
11
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "express-generator-typescript",
3
- "version": "2.0.3",
3
+ "version": "2.0.6",
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",