express-generator-typescript 1.10.3 → 2.0.2

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 (121) 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 +18 -3
  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/{socket-io → project-files}/src/routes/auth-router.ts +14 -15
  26. package/lib/{auth-proj → project-files}/src/routes/middleware.ts +10 -8
  27. package/lib/project-files/src/routes/user-router.ts +9 -15
  28. package/lib/project-files/src/server.ts +82 -73
  29. package/lib/{auth-proj → project-files}/src/services/auth-service.ts +1 -1
  30. package/lib/project-files/src/services/user-service.ts +9 -9
  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/shared/types.ts +14 -0
  34. package/lib/project-files/src/types/express/index.d.ts +16 -8
  35. package/lib/{socket-io → project-files}/src/util/jwt-util.ts +10 -9
  36. package/lib/{auth-proj → project-files}/src/views/login.html +0 -0
  37. package/lib/{auth-proj → project-files}/src/views/users.html +0 -0
  38. package/lib/project-files/tsconfig.json +3 -0
  39. package/package.json +1 -1
  40. package/chat-screenshot.png +0 -0
  41. package/lib/auth-proj/.eslintignore +0 -1
  42. package/lib/auth-proj/.eslintrc.json +0 -27
  43. package/lib/auth-proj/build.ts +0 -64
  44. package/lib/auth-proj/gitignore +0 -3
  45. package/lib/auth-proj/package.json +0 -73
  46. package/lib/auth-proj/spec/index.ts +0 -57
  47. package/lib/auth-proj/spec/loadEnv.ts +0 -10
  48. package/lib/auth-proj/spec/nodemon.json +0 -6
  49. package/lib/auth-proj/spec/support/jasmine.json +0 -11
  50. package/lib/auth-proj/spec/tests/users.spec.ts +0 -283
  51. package/lib/auth-proj/src/index.ts +0 -14
  52. package/lib/auth-proj/src/models/user-model.ts +0 -56
  53. package/lib/auth-proj/src/pre-start/env/development.env +0 -23
  54. package/lib/auth-proj/src/pre-start/env/production.env +0 -24
  55. package/lib/auth-proj/src/pre-start/env/test.env +0 -23
  56. package/lib/auth-proj/src/pre-start/index.ts +0 -28
  57. package/lib/auth-proj/src/repos/database.json +0 -1
  58. package/lib/auth-proj/src/repos/mock-orm.ts +0 -41
  59. package/lib/auth-proj/src/repos/user-repo.ts +0 -88
  60. package/lib/auth-proj/src/routes/api.ts +0 -17
  61. package/lib/auth-proj/src/routes/auth-router.ts +0 -63
  62. package/lib/auth-proj/src/routes/user-router.ts +0 -80
  63. package/lib/auth-proj/src/server.ts +0 -82
  64. package/lib/auth-proj/src/services/user-service.ts +0 -52
  65. package/lib/auth-proj/src/shared/env-vars.ts +0 -20
  66. package/lib/auth-proj/src/shared/errors.ts +0 -45
  67. package/lib/auth-proj/src/shared/functions.ts +0 -18
  68. package/lib/auth-proj/src/types/express/index.d.ts +0 -32
  69. package/lib/auth-proj/src/util/jwt-util.ts +0 -47
  70. package/lib/auth-proj/tsconfig.json +0 -100
  71. package/lib/auth-proj/tsconfig.prod.json +0 -11
  72. package/lib/project-files/src/public/scripts/index.js +0 -183
  73. package/lib/project-files/src/public/stylesheets/style.css +0 -33
  74. package/lib/project-files/src/views/index.html +0 -31
  75. package/lib/socket-io/.eslintignore +0 -1
  76. package/lib/socket-io/.eslintrc.json +0 -27
  77. package/lib/socket-io/build.ts +0 -64
  78. package/lib/socket-io/gitignore +0 -3
  79. package/lib/socket-io/package.json +0 -75
  80. package/lib/socket-io/spec/index.ts +0 -57
  81. package/lib/socket-io/spec/loadEnv.ts +0 -10
  82. package/lib/socket-io/spec/nodemon.json +0 -6
  83. package/lib/socket-io/spec/support/jasmine.json +0 -11
  84. package/lib/socket-io/spec/support/login-agent.ts +0 -49
  85. package/lib/socket-io/spec/tests/auth.spec.ts +0 -159
  86. package/lib/socket-io/spec/tests/chat.spec.ts +0 -150
  87. package/lib/socket-io/spec/tests/users.spec.ts +0 -283
  88. package/lib/socket-io/src/index.ts +0 -14
  89. package/lib/socket-io/src/models/user-model.ts +0 -56
  90. package/lib/socket-io/src/pre-start/env/development.env +0 -23
  91. package/lib/socket-io/src/pre-start/env/production.env +0 -24
  92. package/lib/socket-io/src/pre-start/env/test.env +0 -23
  93. package/lib/socket-io/src/pre-start/index.ts +0 -28
  94. package/lib/socket-io/src/public/scripts/chat.js +0 -87
  95. package/lib/socket-io/src/public/scripts/http.js +0 -24
  96. package/lib/socket-io/src/public/scripts/index.js +0 -16
  97. package/lib/socket-io/src/public/scripts/login.js +0 -17
  98. package/lib/socket-io/src/public/scripts/users.js +0 -148
  99. package/lib/socket-io/src/public/stylesheets/chat.css +0 -43
  100. package/lib/socket-io/src/public/stylesheets/index.css +0 -13
  101. package/lib/socket-io/src/public/stylesheets/login.css +0 -20
  102. package/lib/socket-io/src/public/stylesheets/users.css +0 -40
  103. package/lib/socket-io/src/repos/database.json +0 -38
  104. package/lib/socket-io/src/repos/mock-orm.ts +0 -41
  105. package/lib/socket-io/src/repos/user-repo.ts +0 -88
  106. package/lib/socket-io/src/routes/api.ts +0 -19
  107. package/lib/socket-io/src/routes/chat-router.ts +0 -97
  108. package/lib/socket-io/src/routes/middleware.ts +0 -55
  109. package/lib/socket-io/src/routes/user-router.ts +0 -77
  110. package/lib/socket-io/src/server.ts +0 -100
  111. package/lib/socket-io/src/services/auth-service.ts +0 -38
  112. package/lib/socket-io/src/services/user-service.ts +0 -52
  113. package/lib/socket-io/src/shared/env-vars.ts +0 -20
  114. package/lib/socket-io/src/shared/errors.ts +0 -56
  115. package/lib/socket-io/src/shared/functions.ts +0 -18
  116. package/lib/socket-io/src/types/express/index.d.ts +0 -34
  117. package/lib/socket-io/src/views/chat.html +0 -51
  118. package/lib/socket-io/src/views/login.html +0 -35
  119. package/lib/socket-io/src/views/users.html +0 -47
  120. package/lib/socket-io/tsconfig.json +0 -100
  121. package/lib/socket-io/tsconfig.prod.json +0 -11
package/README.md CHANGED
@@ -13,7 +13,6 @@ Creates a new express application similar to the _express-generator_ module. Exc
13
13
  application is configured to use TypeScript instead of plain JavaScript.
14
14
 
15
15
 
16
-
17
16
  ## Why express-generator-typescript?
18
17
 
19
18
  NodeJS is great for the rapid development of web-projects, but is often neglected because of the lack of
@@ -36,24 +35,11 @@ and `_moduleAliases` in _package.json_ if you want to add/edit the relative path
36
35
 
37
36
  ## Sample-project
38
37
 
39
- When you run _express-generator-typescript_, it sets up a very simple application with routes for
38
+ When you run _express-generator-typescript_, it sets up a simple application with routes for
40
39
  adding, updating, deleting, and fetching user objects. This is just to demonstrate how routing is done
41
- with express.
42
-
43
- If you want a fully-secure application, you can pass the `--with-auth` option and you will have an
44
- application which requires you to login before calling APIs on user objects. The app is
40
+ with express. You will have to login before calling APIs on user objects. The app is
45
41
  configured with production quality client-side security and uses signed-cookies and jsonwebtokens
46
- to store user-session data. If you're new to web-development and still learning about securing websites,
47
- I highly encourage to use this option.
48
-
49
- To have a chat app within your application, use the `--socket-io` option. This option will include
50
- everything from the `--with-auth` option, plus will create a mini-chat app which displays the
51
- sender name for the message of whoever the logged in user is. Without a login user we can't display
52
- a sender name, that's why the `--socket-io` option must used in conjunction with `--with-auth`.
53
- To create a socket-io sample app, you can pass `--socket-io` or `--with-auth --socket-io`; it won't
54
- make a difference.
55
-
56
- <img alt='chat-screenshot' src='https://github.com/seanpmaxwell/express-generator-typescript/raw/master/chat-screenshot.png' border='0'>
42
+ to store user-session data.
57
43
 
58
44
 
59
45
  ## Installation
@@ -75,14 +61,12 @@ Create the app:
75
61
 
76
62
  ```bash
77
63
  $ npx express-generator-typescript "project name (default is express-gen-ts)"
78
- with all options
79
- $ npx express-generator-typescript --with-auth --socket-io --use-yarn "project name (default is express-gen-ts)"
80
64
  ```
81
65
 
82
66
  Start your express-generator-typescript app in development mode at `http://localhost:3000/`:
83
67
 
84
68
  ```bash
85
- $ cd "project name" && npm run start:dev
69
+ $ cd "project name" && npm run dev
86
70
  ```
87
71
 
88
72
 
@@ -106,6 +90,34 @@ This is located under `nodemonConfig:` in `package.json` for the server and `./s
106
90
  unit-testing. For the `exec` property, replace `ts-node` with `node --inspect -r ts-node/register`.
107
91
 
108
92
 
93
+ ## If you don't want authentication:
94
+
95
+ In previous version of __express-generator-typescript__ you could disregard authentication through the
96
+ command line options. But maintaining two separate project folders which contained and didn't contain
97
+ authentication started to get messy.
98
+
99
+ - Remove the following modules from `package.json`:
100
+ - `jsonwebtoken`
101
+ - `@types/jsonwebtoken`
102
+ - `bcrypt`
103
+ - `@types/bcrypt`
104
+
105
+ - Delete the files:
106
+ - `src/routes/middleware.ts`
107
+ - `src/routes/auth-router.ts`
108
+ - `spec/tests/auth.spec.ts`
109
+ - `spec/support/login-agent.ts`
110
+ - `public/scripts/login.js`
111
+ - `public/stylesheets/login.css`
112
+ - `public/views/login.html`
113
+
114
+ - Update the files:
115
+ - In `src/routes/api`, delete the line: `apiRouter.use('/auth', authRouter);` and
116
+ remove the `adminMw,` from line 12. Remove the `adminMw` and `authRouter` imports as well.
117
+ - In `spec/tests/users.spec.ts`, remove all lines containing `loginAgent` and `setCookie`
118
+ - In `public/views/users.html` remove the `Logout` button.
119
+
120
+
109
121
  ## Note for VS-Code users
110
122
 
111
123
  A lot of users have asked about _launch.json_ configurations for running this in VS-Code, so
@@ -136,14 +148,12 @@ VS-Code.
136
148
 
137
149
  ## Note for windows users
138
150
 
139
- If you use the `--with-auth` option and are on Windows, the `bcrypt` module tends to be fussy. To
140
- use this module on Windows you need to make sure you have the node Windows build tools installed.
141
- I don't want to post instructions because they might change frequently. I would search the Microsoft
142
- docs on how to setup Node for Windows. To be able to debug in VSCODE on windows I also had to install
143
- the `node-gyp` module globally as well.
144
-
145
- Happy web-deving :)
151
+ If you are on Windows, the `bcrypt` module tends to be fussy. To use this module on Windows you
152
+ need to make sure you have the node Windows build tools installed. I don't want to post instructions
153
+ because they might change frequently. I would search the Microsoft docs on how to setup Node for Windows.
154
+ To be able to debug in VSCODE on windows I also had to install the `node-gyp` module globally as well.
146
155
 
156
+ Happy web deving :)
147
157
 
148
158
 
149
159
  ## License
package/bin/cli.js CHANGED
@@ -15,34 +15,21 @@ const expressGenTs = require('../lib/express-generator-typescript');
15
15
  // const opts = processOptions(process.argv.slice(2));
16
16
  // Process options
17
17
  let destination = 'express-gen-ts';
18
- let withAuth = false;
19
18
  let useYarn = false;
20
- let useSocketIo = false;
21
19
  const args = process.argv.slice(2);
22
20
  let idx = -1;
23
- idx = args.indexOf('--with-auth');
24
- if (idx > -1) {
25
- withAuth = true;
26
- args.splice(idx, 1);
27
- }
28
21
  idx = args.indexOf('--use-yarn');
29
22
  if (idx > -1) {
30
23
  useYarn = true;
31
24
  args.splice(idx, 1);
32
25
  }
33
- idx = args.indexOf('--socket-io');
34
- if (idx > -1) {
35
- useSocketIo = true;
36
- withAuth = true;
37
- args.splice(idx, 1);
38
- }
39
26
  if (args.length > 0) {
40
27
  destination = args[0];
41
28
  }
42
29
  destination = path.join(process.cwd(), destination);
43
30
  // Creating new project finished
44
- expressGenTs(destination, withAuth, useYarn, useSocketIo).then(() => {
31
+ expressGenTs(destination, useYarn).then(() => {
45
32
  console.log('Project setup complete!');
46
33
  });
47
- })();
34
+ })();
48
35
 
package/lib/cli.js CHANGED
@@ -10,39 +10,25 @@ const path = require('path');
10
10
  const expressGenTs = require('../lib/express-generator-typescript');
11
11
 
12
12
 
13
- // Start
14
13
  (() => {
15
14
  console.log('Setting up new Express/TypeScript project...');
16
15
  // const opts = processOptions(process.argv.slice(2));
17
16
  // Process options
18
17
  let destination = 'express-gen-ts';
19
- let withAuth = false;
20
18
  let useYarn = false;
21
- let useSocketIo = false;
22
19
  const args = process.argv.slice(2);
23
20
  let idx = -1;
24
- idx = args.indexOf('--with-auth');
25
- if (idx > -1) {
26
- withAuth = true;
27
- args.splice(idx, 1);
28
- }
29
21
  idx = args.indexOf('--use-yarn');
30
22
  if (idx > -1) {
31
23
  useYarn = true;
32
24
  args.splice(idx, 1);
33
25
  }
34
- idx = args.indexOf('--socket-io');
35
- if (idx > -1) {
36
- useSocketIo = true;
37
- withAuth = true;
38
- args.splice(idx, 1);
39
- }
40
26
  if (args.length > 0) {
41
27
  destination = args[0];
42
28
  }
43
29
  destination = path.join(process.cwd(), destination);
44
30
  // Creating new project finished
45
- expressGenTs(destination, withAuth, useYarn, useSocketIo).then(() => {
31
+ expressGenTs(destination, useYarn).then(() => {
46
32
  console.log('Project setup complete!');
47
33
  });
48
34
  })();
@@ -13,6 +13,8 @@ const fs = require('fs');
13
13
 
14
14
  // **** Variables **** //
15
15
 
16
+ const prjFolder = './project-files';
17
+
16
18
  const ncpOpts = {
17
19
  filter: (fileName) => {
18
20
  return !(fileName === 'package-lock.json' || fileName === 'node_modules');
@@ -25,12 +27,12 @@ const ncpOpts = {
25
27
  /**
26
28
  * Entry point
27
29
  */
28
- async function expressGenTs(destination, withAuth, useYarn, useSocketIo) {
30
+ async function expressGenTs(destination, useYarn) {
29
31
  try {
30
- await copyProjectFiles(destination, withAuth, useSocketIo);
32
+ await copyProjectFiles(destination);
31
33
  updatePackageJson(destination);
32
34
  await renameGitigoreFile(destination);
33
- const depStrings = getDepStrings(withAuth, useSocketIo);
35
+ const depStrings = getDepStrings();
34
36
  downloadNodeModules(destination, depStrings, useYarn);
35
37
  } catch (err) {
36
38
  console.error(err);
@@ -40,15 +42,8 @@ async function expressGenTs(destination, withAuth, useYarn, useSocketIo) {
40
42
  /**
41
43
  * Copy project files
42
44
  */
43
- function copyProjectFiles(destination, withAuth, useSocketIo) {
44
- let prjFolder = './project-files';
45
- if (useSocketIo) {
46
- prjFolder = './socket-io';
47
- } else if (withAuth) {
48
- prjFolder = './auth-proj';
49
- }
45
+ function copyProjectFiles(destination) {
50
46
  const source = path.join(__dirname, prjFolder);
51
- // Return
52
47
  return new Promise((res, rej) => {
53
48
  ncp.limit = 16;
54
49
  return ncp(source, destination, ncpOpts, (err) => {
@@ -83,21 +78,16 @@ function renameGitigoreFile(destination) {
83
78
  /**
84
79
  * Setup dependency strings. This way gets you the latest version of everything.
85
80
  */
86
- function getDepStrings(withAuth, useSocketIo) {
81
+ function getDepStrings() {
87
82
  let dependencies = 'express dotenv http-status-codes morgan cookie-parser jet-logger ' +
88
- 'module-alias command-line-args express-async-errors helmet jsonfile';
83
+ 'module-alias command-line-args express-async-errors helmet jsonfile bcrypt ' +
84
+ 'jsonwebtoken';
89
85
  let devDependencies = 'ts-node typescript nodemon find jasmine supertest ' +
90
86
  '@types/node @types/express @types/jasmine @types/find @types/morgan ' +
91
87
  '@types/cookie-parser @types/supertest fs-extra tsconfig-paths @types/jsonfile ' +
92
88
  '@types/command-line-args @typescript-eslint/eslint-plugin @typescript-eslint/parser ' +
93
- 'eslint @types/fs-extra';
94
- if (withAuth || useSocketIo) {
95
- dependencies += ' bcrypt randomstring jsonwebtoken';
96
- devDependencies += ' @types/bcrypt @types/randomstring @types/jsonwebtoken';
97
- }
98
- if (useSocketIo) {
99
- dependencies += ' socket.io socket.io-client';
100
- }
89
+ 'eslint @types/fs-extra @types/bcrypt @types/jsonwebtoken ' +
90
+ 'eslint-plugin-node';
101
91
  // Return
102
92
  return { dependencies, devDependencies };
103
93
  }
@@ -6,7 +6,8 @@
6
6
  "extends": [
7
7
  "eslint:recommended",
8
8
  "plugin:@typescript-eslint/recommended",
9
- "plugin:@typescript-eslint/recommended-requiring-type-checking"
9
+ "plugin:@typescript-eslint/recommended-requiring-type-checking",
10
+ "plugin:node/recommended"
10
11
  ],
11
12
  "parserOptions": {
12
13
  "project": "./tsconfig.json"
@@ -21,7 +22,20 @@
21
22
  "no-console": 1,
22
23
  "no-extra-boolean-cast": 0,
23
24
  "semi": 1,
25
+ "indent": ["warn", 2],
24
26
  "@typescript-eslint/no-misused-promises": 0,
25
- "@typescript-eslint/no-floating-promises": 0
27
+ "@typescript-eslint/no-floating-promises": 0,
28
+ "node/no-process-env": 1,
29
+ "node/no-unsupported-features/es-syntax": [
30
+ "error",
31
+ { "ignores" : ["modules"] }
32
+ ],
33
+ "node/no-missing-import": 0,
34
+ "node/no-unpublished-import": 0
35
+ },
36
+ "settings": {
37
+ "node": {
38
+ "tryExtensions": [".js", ".json", ".node", ".ts"]
39
+ }
26
40
  }
27
41
  }
@@ -36,7 +36,7 @@ function remove(loc: string): Promise<void> {
36
36
  }
37
37
 
38
38
  /**
39
- * Copy file
39
+ * Copy file.
40
40
  */
41
41
  function copy(src: string, dest: string): Promise<void> {
42
42
  return new Promise((res, rej) => {
@@ -47,7 +47,7 @@ function copy(src: string, dest: string): Promise<void> {
47
47
  }
48
48
 
49
49
  /**
50
- * Execute system command
50
+ * Do command line command.
51
51
  */
52
52
  function exec(cmd: string, loc: string): Promise<void> {
53
53
  return new Promise((res, rej) => {
@@ -1,13 +1,14 @@
1
1
  {
2
- "name": "express-gen-ts",
2
+ "name": "express-typescript-example",
3
3
  "version": "0.0.0",
4
4
  "scripts": {
5
5
  "build": "npx ts-node build.ts",
6
- "lint": "eslint . --ext .ts",
6
+ "lint": "npx eslint --ext .ts src/",
7
+ "lint:tests": "npx eslint --ext .ts spec/",
7
8
  "start": "node -r module-alias/register ./dist --env=production",
8
9
  "dev": "nodemon",
9
10
  "test": "nodemon --config ./spec/nodemon.json",
10
- "test:no-reloading": "npx ts-node -r tsconfig-paths/register ./spec"
11
+ "test:no-reloading": "npx ts-node --files -r tsconfig-paths/register ./spec"
11
12
  },
12
13
  "nodemonConfig": {
13
14
  "watch": [
@@ -17,7 +18,7 @@
17
18
  "ignore": [
18
19
  "src/public"
19
20
  ],
20
- "exec": "./node_modules/.bin/ts-node -r tsconfig-paths/register ./src"
21
+ "exec": "./node_modules/.bin/ts-node --files -r tsconfig-paths/register ./src"
21
22
  },
22
23
  "_moduleAliases": {
23
24
  "@services": "dist/services",
@@ -25,9 +26,14 @@
25
26
  "@entities": "dist/entities",
26
27
  "@shared": "dist/shared",
27
28
  "@server": "dist/server",
28
- "@routes": "dist/routes"
29
+ "@routes": "dist/routes",
30
+ "@util": "dist/util"
31
+ },
32
+ "engines": {
33
+ "node": ">=8.10.0"
29
34
  },
30
35
  "dependencies": {
36
+ "bcrypt": "^5.0.1",
31
37
  "command-line-args": "^5.2.1",
32
38
  "cookie-parser": "^1.4.6",
33
39
  "dotenv": "^16.0.2",
@@ -37,10 +43,12 @@
37
43
  "http-status-codes": "^2.2.0",
38
44
  "jet-logger": "^1.2.3",
39
45
  "jsonfile": "^6.1.0",
46
+ "jsonwebtoken": "^8.5.1",
40
47
  "module-alias": "^2.2.2",
41
48
  "morgan": "^1.10.0"
42
49
  },
43
50
  "devDependencies": {
51
+ "@types/bcrypt": "^5.0.0",
44
52
  "@types/command-line-args": "^5.2.0",
45
53
  "@types/cookie-parser": "^1.4.3",
46
54
  "@types/express": "^4.17.13",
@@ -48,12 +56,14 @@
48
56
  "@types/fs-extra": "^9.0.13",
49
57
  "@types/jasmine": "^4.3.0",
50
58
  "@types/jsonfile": "^6.1.0",
59
+ "@types/jsonwebtoken": "^8.5.9",
51
60
  "@types/morgan": "^1.9.3",
52
61
  "@types/node": "^18.7.14",
53
62
  "@types/supertest": "^2.0.12",
54
63
  "@typescript-eslint/eslint-plugin": "^5.36.1",
55
64
  "@typescript-eslint/parser": "^5.36.1",
56
65
  "eslint": "^8.23.0",
66
+ "eslint-plugin-node": "^11.1.0",
57
67
  "find": "^0.3.0",
58
68
  "fs-extra": "^10.1.0",
59
69
  "jasmine": "^4.3.0",
@@ -2,5 +2,5 @@
2
2
  "watch": ["spec"],
3
3
  "ext": "spec.ts",
4
4
  "ignore": ["spec/support"],
5
- "exec": "./node_modules/.bin/ts-node -r tsconfig-paths/register ./spec"
5
+ "exec": "./node_modules/.bin/ts-node --files -r tsconfig-paths/register ./spec"
6
6
  }
@@ -1,5 +1,5 @@
1
1
  import bcrypt from 'bcrypt';
2
- import { SuperTest, Test } from 'supertest';
2
+ import { SuperTest, Test, Response } from 'supertest';
3
3
 
4
4
  import User, { UserRoles } from '@models/user-model';
5
5
  import userRepo from '@repos/user-repo';
@@ -19,9 +19,6 @@ const creds = {
19
19
 
20
20
  /**
21
21
  * Login a user.
22
- *
23
- * @param beforeAgent
24
- * @param done
25
22
  */
26
23
  function login(beforeAgent: SuperTest<Test>, done: (arg: string) => void) {
27
24
  // Setup dummy data
@@ -34,17 +31,18 @@ function login(beforeAgent: SuperTest<Test>, done: (arg: string) => void) {
34
31
  .post('/api/auth/login')
35
32
  .type('form')
36
33
  .send(creds)
37
- .end((err: Error, res: any) => {
34
+ .end((err: Error, res: Response) => {
38
35
  if (err) {
39
36
  throw err;
40
37
  }
41
- done(res.headers['set-cookie']);
38
+ const cookie = res.headers['set-cookie'][0];
39
+ return done(cookie);
42
40
  });
43
- };
41
+ }
44
42
 
45
43
 
46
44
  // **** Export default **** //
47
45
 
48
46
  export default {
49
- login,
47
+ login,
50
48
  } as const;
@@ -31,7 +31,13 @@ const msgs = {
31
31
  fallbackErr: `should return a response with a status of ${BAD_REQUEST} and a json with an error
32
32
  for all other bad responses.`,
33
33
  goodLogout: `should return a response with a status of ${OK}.`,
34
- }
34
+ } as const;
35
+
36
+ // Login credentials
37
+ const loginCreds = {
38
+ email: 'jsmith@gmail.com',
39
+ password: 'Password@1',
40
+ } as const;
35
41
 
36
42
 
37
43
  // **** Types **** //
@@ -60,35 +66,25 @@ describe('auth-router', () => {
60
66
 
61
67
  // Good login
62
68
  it(msgs.goodLogin, (done) => {
63
- // Setup Dummy Data
64
- const creds = {
65
- email: 'jsmith@gmail.com',
66
- password: 'Password@1',
67
- };
68
69
  const role = UserRoles.Standard;
69
- const pwdHash = hashPwd(creds.password);
70
- const loginUser = User.new('john smith', creds.email, role, pwdHash);
70
+ const pwdHash = hashPwd(loginCreds.password);
71
+ const loginUser = User.new('john smith', loginCreds.email, role, pwdHash);
71
72
  spyOn(userRepo, 'getOne').and.returnValue(Promise.resolve(loginUser));
72
73
  // Call API
73
- callApi(creds)
74
+ callApi(loginCreds)
74
75
  .end((err: Error, res: Response) => {
75
76
  pErr(err);
76
77
  expect(res.status).toBe(OK);
77
- expect(res.headers['set-cookie'][0]).toContain(envVars.cookieProps.key);
78
+ const cookie = res.headers['set-cookie'][0];
79
+ expect(cookie).toContain(envVars.cookieProps.key);
78
80
  done();
79
81
  });
80
82
  });
81
83
 
82
84
  // Email not found error
83
85
  it(msgs.emailNotFound, (done) => {
84
- // Setup Dummy Data
85
- const creds = {
86
- email: 'jsmith@gmail.com',
87
- password: 'Password@1',
88
- };
89
86
  spyOn(userRepo, 'getOne').and.returnValue(Promise.resolve(null));
90
- // Call API
91
- callApi(creds)
87
+ callApi(loginCreds)
92
88
  .end((err: Error, res: Response) => {
93
89
  pErr(err);
94
90
  expect(res.status).toBe(UNAUTHORIZED);
@@ -99,17 +95,12 @@ describe('auth-router', () => {
99
95
 
100
96
  // Password failed
101
97
  it(msgs.pwdFailed, (done) => {
102
- // Setup Dummy Data
103
- const creds = {
104
- email: 'jsmith@gmail.com',
105
- password: 'someBadPassword',
106
- };
107
98
  const role = UserRoles.Standard;
108
- const pwdHash = hashPwd('Password@1');
109
- const loginUser = User.new('john smith', creds.email, role, pwdHash);
99
+ const pwdHash = hashPwd('bad password');
100
+ const loginUser = User.new('john smith', loginCreds.email, role, pwdHash);
110
101
  spyOn(userRepo, 'getOne').and.returnValue(Promise.resolve(loginUser));
111
102
  // Call API
112
- callApi(creds)
103
+ callApi(loginCreds)
113
104
  .end((err: Error, res: Response) => {
114
105
  pErr(err);
115
106
  expect(res.status).toBe(UNAUTHORIZED);
@@ -120,14 +111,8 @@ describe('auth-router', () => {
120
111
 
121
112
  // Fallback error
122
113
  it(msgs.fallbackErr, (done) => {
123
- // Setup Dummy Data
124
- const creds = {
125
- email: 'jsmith@gmail.com',
126
- password: 'someBadPassword',
127
- };
128
114
  spyOn(userRepo, 'getOne').and.throwError('Database query failed.');
129
- // Call API
130
- callApi(creds)
115
+ callApi(loginCreds)
131
116
  .end((err: Error, res: Response) => {
132
117
  pErr(err);
133
118
  expect(res.status).toBe(BAD_REQUEST);
@@ -140,6 +125,7 @@ describe('auth-router', () => {
140
125
  // Test logout
141
126
  describe(`"GET:${logoutPath}"`, () => {
142
127
 
128
+ // Successful logout
143
129
  it(msgs.goodLogout, (done) => {
144
130
  agent.get(logoutPath)
145
131
  .end((err: Error, res: Response) => {
@@ -7,6 +7,7 @@ import userRepo from '@repos/user-repo';
7
7
  import User, { IUser } from '@models/user-model';
8
8
  import { pErr } from '@shared/functions';
9
9
  import { p as userPaths } from '@routes/user-router';
10
+ import loginAgent from '../support/login-agent';
10
11
  import { ParamMissingError, UserNotFoundError } from '@shared/errors';
11
12
 
12
13
 
@@ -72,33 +73,40 @@ type TReqBody = string | object | undefined;
72
73
  describe('user-router', () => {
73
74
 
74
75
  let agent: SuperTest<Test>;
76
+ let jwtCookie: string;
75
77
 
76
78
 
77
79
  // Run before all tests
78
80
  beforeAll((done) => {
79
81
  agent = supertest.agent(app);
80
- done();
82
+ loginAgent.login(agent, (cookie: string) => {
83
+ jwtCookie = cookie;
84
+ done();
85
+ });
81
86
  });
82
87
 
83
- // Test get users
88
+ // Test get users
84
89
  describe(`"GET:${getUsersPath}"`, () => {
85
90
 
91
+ const callApi = () =>
92
+ agent.get(getUsersPath)
93
+ .set('Cookie', jwtCookie);
94
+
86
95
  // Get all users
87
96
  it(msgs.getUsersSuccess, (done) => {
88
97
  const ret = Promise.resolve([...dummyGetAllUsers]);
89
98
  spyOn(userRepo, 'getAll').and.returnValue(ret);
90
99
  // Call API
91
- agent.get(getUsersPath)
92
- .end((err: Error, res: Response) => {
93
- pErr(err);
94
- expect(res.status).toBe(OK);
95
- // Caste instance-objects to 'User' objects
96
- const respUsers = res.body.users;
97
- const retUsers: IUser[] = respUsers.map((user: IUser) => User.copy(user));
98
- expect(retUsers).toEqual(dummyGetAllUsers);
99
- expect(res.body.error).toBeUndefined();
100
- done();
101
- });
100
+ callApi().end((err: Error, res: Response) => {
101
+ pErr(err);
102
+ expect(res.status).toBe(OK);
103
+ // Caste instance-objects to 'User' objects
104
+ const respUsers = res.body.users;
105
+ const retUsers = respUsers.map((user: IUser) => User.copy(user));
106
+ expect(retUsers).toEqual(dummyGetAllUsers);
107
+ expect(res.body.error).toBeUndefined();
108
+ done();
109
+ });
102
110
  });
103
111
 
104
112
  // Get all users bad
@@ -106,7 +114,7 @@ describe('user-router', () => {
106
114
  const errMsg = 'Could not fetch users.';
107
115
  spyOn(userRepo, 'getAll').and.throwError(errMsg);
108
116
  // Call API
109
- agent.get(getUsersPath)
117
+ callApi()
110
118
  .end((err: Error, res: Response) => {
111
119
  pErr(err);
112
120
  expect(res.status).toBe(BAD_REQUEST);
@@ -119,9 +127,10 @@ describe('user-router', () => {
119
127
  // Test add user
120
128
  describe(`"POST:${addUsersPath}"`, () => {
121
129
 
130
+ // Consts
122
131
  const callApi = (reqBody: TReqBody) => {
123
- return agent
124
- .post(addUsersPath)
132
+ return agent.post(addUsersPath)
133
+ .set('Cookie', jwtCookie)
125
134
  .type('form').send(reqBody);
126
135
  };
127
136
 
@@ -166,11 +175,10 @@ describe('user-router', () => {
166
175
  // Test update users
167
176
  describe(`"PUT:${updateUserPath}"`, () => {
168
177
 
169
- const callApi = (reqBody: TReqBody) => {
170
- return agent.put(updateUserPath)
171
- .type('form')
172
- .send(reqBody);
173
- };
178
+ const callApi = (reqBody: TReqBody) =>
179
+ agent.put(updateUserPath)
180
+ .set('Cookie', jwtCookie)
181
+ .type('form').send(reqBody);
174
182
 
175
183
  // Test updating a user success
176
184
  it(msgs.updateSuccess, (done) => {
@@ -229,7 +237,8 @@ describe('user-router', () => {
229
237
 
230
238
  const callApi = (id: number) => {
231
239
  const path = deleteUserPath.replace(':id', id.toString());
232
- return agent.delete(path);
240
+ return agent.delete(path)
241
+ .set('Cookie', jwtCookie);
233
242
  };
234
243
 
235
244
  // Delete user successful
@@ -0,0 +1,14 @@
1
+ import { IUser } from '@models/user-model';
2
+ import 'supertest';
3
+
4
+
5
+ declare module 'supertest' {
6
+
7
+ export interface Response {
8
+ headers: Record<string, string[]>;
9
+ body: {
10
+ error: string;
11
+ users: IUser[];
12
+ };
13
+ }
14
+ }