express-generator-typescript 2.4.6 → 2.4.8

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 (33) hide show
  1. package/lib/express-generator-typescript.js +1 -1
  2. package/lib/project-files/package.json +4 -3
  3. package/lib/project-files/spec/support/apiCb.ts +76 -0
  4. package/lib/project-files/spec/tests/users.spec.ts +102 -127
  5. package/lib/project-files/spec/types/misc.ts +18 -0
  6. package/lib/project-files/src/models/User.ts +13 -27
  7. package/lib/project-files/src/public/scripts/http.js +3 -1
  8. package/lib/project-files/src/public/scripts/users.js +31 -65
  9. package/lib/project-files/src/public/stylesheets/users.css +4 -6
  10. package/lib/project-files/src/repos/UserRepo.ts +6 -1
  11. package/lib/project-files/src/repos/database.json +22 -1
  12. package/lib/project-files/src/routes/types/express/misc.ts +1 -5
  13. package/lib/project-files/src/routes/types/types.ts +0 -8
  14. package/lib/project-files/src/views/users.html +100 -5
  15. package/lib/project-files-auth/package.json +4 -3
  16. package/lib/project-files-auth/spec/support/apiCb.ts +76 -0
  17. package/lib/project-files-auth/spec/support/login.ts +6 -8
  18. package/lib/project-files-auth/spec/tests/auth.spec.ts +52 -59
  19. package/lib/project-files-auth/spec/tests/users.spec.ts +101 -133
  20. package/lib/project-files-auth/spec/types/misc.ts +18 -0
  21. package/lib/project-files-auth/src/models/User.ts +17 -12
  22. package/lib/project-files-auth/src/public/scripts/http.js +3 -1
  23. package/lib/project-files-auth/src/public/scripts/login.js +1 -3
  24. package/lib/project-files-auth/src/public/scripts/users.js +31 -63
  25. package/lib/project-files-auth/src/public/stylesheets/users.css +4 -11
  26. package/lib/project-files-auth/src/repos/UserRepo.ts +6 -1
  27. package/lib/project-files-auth/src/repos/database.json +1 -1
  28. package/lib/project-files-auth/src/services/UserService.ts +2 -8
  29. package/lib/project-files-auth/src/views/login.html +26 -3
  30. package/lib/project-files-auth/src/views/users.html +106 -8
  31. package/package.json +1 -1
  32. package/lib/project-files/spec/support/types.ts +0 -1
  33. package/lib/project-files-auth/spec/support/types.ts +0 -1
@@ -1,4 +1,5 @@
1
- import supertest, { SuperTest, Test, Response } from 'supertest';
1
+ import supertest, { Test, Response } from 'supertest';
2
+ import TestAgent from 'supertest/lib/agent';
2
3
 
3
4
  import app from '@src/server';
4
5
 
@@ -11,29 +12,21 @@ import EnvVars from '@src/constants/EnvVars';
11
12
  import HttpStatusCodes from '@src/constants/HttpStatusCodes';
12
13
 
13
14
  import Paths from 'spec/support/Paths';
14
- import { TReqBody } from 'spec/support/types';
15
+ import apiCb from 'spec/support/apiCb';
16
+ import { TApiCb } from 'spec/types/misc';
15
17
 
16
18
 
17
- // **** Variables **** //
18
-
19
- // StatusCodes
20
- const {
21
- OK,
22
- UNAUTHORIZED,
23
- } = HttpStatusCodes;
24
-
25
- // Login credentials
19
+ // Login Creds
26
20
  const LoginCreds = {
27
21
  email: 'jsmith@gmail.com',
28
22
  password: 'Password@1',
29
23
  } as const;
30
24
 
31
25
 
32
- // **** Tests **** //
33
-
26
+ // Tests
34
27
  describe('AuthRouter', () => {
35
28
 
36
- let agent: SuperTest<Test>;
29
+ let agent: TestAgent<Test>;
37
30
 
38
31
  // Run before all tests
39
32
  beforeAll((done) => {
@@ -41,82 +34,82 @@ describe('AuthRouter', () => {
41
34
  done();
42
35
  });
43
36
 
44
- // ** Test login ** //
37
+ // Login
45
38
  describe(`"POST:${Paths.Auth.Login}"`, () => {
46
39
 
47
40
  const EMAIL_NOT_FOUND_ERR = Errors.EmailNotFound(LoginCreds.email);
48
41
 
49
- const callApi = (reqBody: TReqBody) =>
42
+ // Setup API
43
+ const callApi = (creds: typeof LoginCreds, cb: TApiCb) =>
50
44
  agent
51
45
  .post(Paths.Auth.Login)
52
- .type('form')
53
- .send(reqBody);
46
+ .send(creds)
47
+ .end(apiCb(cb));
54
48
 
55
49
  // Success
56
- it(`should return a response with a status of "${OK}" and a cookie with ` +
57
- 'a jwt if the login was successful.', (done) => {
50
+ it(`should return a response with a status of "${HttpStatusCodes.OK}" ` +
51
+ 'and a cookie with a jwt if the login was successful.', done => {
58
52
  // Setup data
59
- const role = UserRoles.Standard,
60
- pwdHash = PwdUtil.hashSync(LoginCreds.password),
61
- loginUser = User.new('john smith', LoginCreds.email, role, pwdHash);
53
+ const pwdHash = PwdUtil.hashSync(LoginCreds.password),
54
+ loginUser = User.new('john smith', LoginCreds.email, new Date(),
55
+ UserRoles.Standard, pwdHash);
62
56
  // Add spy
63
57
  spyOn(UserRepo, 'getOne').and.resolveTo(loginUser);
64
58
  // Call API
65
- callApi(LoginCreds)
66
- .end((_: Error, res: Response) => {
67
- expect(res.status).toBe(OK);
68
- const cookie = res.headers['set-cookie'][0];
69
- expect(cookie).toContain(EnvVars.CookieProps.Key);
70
- done();
71
- });
59
+ callApi(LoginCreds, res => {
60
+ expect(res.status).toBe(HttpStatusCodes.OK);
61
+ const cookie = res.headers['set-cookie'][0];
62
+ expect(cookie).toContain(EnvVars.CookieProps.Key);
63
+ done();
64
+ });
72
65
  });
73
66
 
74
67
  // Email not found error
75
- it(`should return a response with a status of "${UNAUTHORIZED}" and a ` +
76
- `json with an error message of "${EMAIL_NOT_FOUND_ERR}" if the email ` +
77
- 'was not found.', (done) => {
68
+ it('should return a response with a status of ' +
69
+ `"${HttpStatusCodes.UNAUTHORIZED}" and a json with an error message of ` +
70
+ `"${EMAIL_NOT_FOUND_ERR}" if the email was not found.`, done => {
78
71
  // Spy
79
72
  spyOn(UserRepo, 'getOne').and.resolveTo(null);
80
73
  // Call
81
- callApi(LoginCreds)
82
- .end((_: Error, res: Response) => {
83
- expect(res.status).toBe(UNAUTHORIZED);
84
- expect(res.body.error).toBe(EMAIL_NOT_FOUND_ERR);
85
- done();
86
- });
74
+ callApi(LoginCreds, res => {
75
+ expect(res.status).toBe(HttpStatusCodes.UNAUTHORIZED);
76
+ expect(res.body.error).toBe(EMAIL_NOT_FOUND_ERR);
77
+ done();
78
+ });
87
79
  });
88
80
 
89
81
  // Password failed
90
- it(`should return a response with a status of "${UNAUTHORIZED}" and a ` +
91
- `json with the error "${Errors.Unauth}" if the password failed.`,
92
- (done) => {
82
+ it('should return a response with a status of ' +
83
+ `"${HttpStatusCodes.UNAUTHORIZED}" and a json with the error ` +
84
+ `"${Errors.Unauth}" if the password failed.`, done => {
93
85
  // Setup data
94
- const role = UserRoles.Standard,
95
- pwdHash = PwdUtil.hashSync('bad password'),
96
- loginUser = User.new('john smith', LoginCreds.email, role, pwdHash);
86
+ const pwdHash = PwdUtil.hashSync('bad password'),
87
+ loginUser = User.new('john smith', LoginCreds.email, new Date(),
88
+ UserRoles.Standard, pwdHash);
97
89
  // Add spy
98
90
  spyOn(UserRepo, 'getOne').and.resolveTo(loginUser);
99
91
  // Call API
100
- callApi(LoginCreds)
101
- .end((_: Error, res: Response) => {
102
- expect(res.status).toBe(UNAUTHORIZED);
103
- expect(res.body.error).toBe(Errors.Unauth);
104
- done();
105
- });
92
+ callApi(LoginCreds, res => {
93
+ expect(res.status).toBe(HttpStatusCodes.UNAUTHORIZED);
94
+ expect(res.body.error).toBe(Errors.Unauth);
95
+ done();
96
+ });
106
97
  });
107
98
 
108
99
  });
109
100
 
110
- // ** Test logout ** //
101
+ // Test logout
111
102
  describe(`"GET:${Paths.Auth.Logout}"`, () => {
112
103
 
113
104
  // Successful logout
114
- it(`should return a response with a status of ${OK}`, (done) => {
115
- agent.get(Paths.Auth.Logout)
116
- .end((_: Error, res: Response) => {
117
- expect(res.status).toBe(HttpStatusCodes.OK);
118
- done();
119
- });
120
- });
105
+ it(`should return a response with a status of ${HttpStatusCodes.OK}`,
106
+ done => {
107
+ agent
108
+ .get(Paths.Auth.Logout)
109
+ .end((_: Error, res: Response) => {
110
+ expect(res.status).toBe(HttpStatusCodes.OK);
111
+ done();
112
+ });
113
+ });
121
114
  });
122
115
  });
@@ -1,222 +1,190 @@
1
- import supertest, { SuperTest, Test, Response } from 'supertest';
1
+ import supertest, { Test } from 'supertest';
2
+ import TestAgent from 'supertest/lib/agent';
2
3
  import { defaultErrMsg as ValidatorErr } from 'jet-validator';
3
4
  import insertUrlParams from 'inserturlparams';
4
5
 
5
6
  import app from '@src/server';
6
7
 
7
8
  import UserRepo from '@src/repos/UserRepo';
8
- import User from '@src/models/User';
9
+ import User, { IUser } from '@src/models/User';
9
10
  import HttpStatusCodes from '@src/constants/HttpStatusCodes';
10
11
  import { USER_NOT_FOUND_ERR } from '@src/services/UserService';
11
12
 
12
- import login from '../support/login';
13
13
  import Paths from 'spec/support/Paths';
14
- import { TReqBody } from 'spec/support/types';
14
+ import apiCb from 'spec/support/apiCb';
15
+ import login from 'spec/support/login';
16
+ import { TApiCb } from 'spec/types/misc';
15
17
 
16
18
 
17
- // **** Variables **** //
18
-
19
- // StatusCodes
20
- const {
21
- OK,
22
- CREATED,
23
- NOT_FOUND,
24
- BAD_REQUEST,
25
- } = HttpStatusCodes;
26
-
27
19
  // Dummy users for GET req
28
- const DummyGetAllUsers = [
29
- User.new('Sean Maxwell', 'sean.maxwell@gmail.com'),
30
- User.new('John Smith', 'john.smith@gmail.com'),
31
- User.new('Gordan Freeman', 'gordan.freeman@gmail.com'),
32
- ] as const;
33
-
34
- // Dummy update user
35
- const DummyUserData = {
36
- user: User.new('Gordan Freeman', 'gordan.freeman@gmail.com'),
37
- } as const;
20
+ const getDummyUsers = () => {
21
+ return [
22
+ User.new('Sean Maxwell', 'sean.maxwell@gmail.com'),
23
+ User.new('John Smith', 'john.smith@gmail.com'),
24
+ User.new('Gordan Freeman', 'gordan.freeman@gmail.com'),
25
+ ];
26
+ };
38
27
 
39
28
 
40
- // **** Tests **** //
41
-
29
+ // Tests
42
30
  describe('UserRouter', () => {
43
31
 
44
- let agent: SuperTest<Test>,
45
- jwtCookie: string;
32
+ let agent: TestAgent<Test>;
46
33
 
47
34
  // Run before all tests
48
35
  beforeAll((done) => {
49
36
  agent = supertest.agent(app);
50
- login(agent, (cookie: string) => {
51
- jwtCookie = cookie;
37
+ login(agent, cookie => {
38
+ agent.set('Cookie', cookie);
52
39
  done();
53
40
  });
54
41
  });
55
42
 
56
- // ** Get all users ** //
43
+ // Get all users
57
44
  describe(`"GET:${Paths.Users.Get}"`, () => {
58
45
 
59
- const callApi = () =>
46
+ // Setup API
47
+ const api = (cb: TApiCb) =>
60
48
  agent
61
49
  .get(Paths.Users.Get)
62
- .set('Cookie', jwtCookie);
50
+ .end(apiCb(cb));
63
51
 
64
52
  // Success
65
53
  it('should return a JSON object with all the users and a status code ' +
66
- `of "${OK}" if the request was successful.`, (done) => {
54
+ `of "${HttpStatusCodes.OK}" if the request was successful.`, (done) => {
67
55
  // Add spy
68
- spyOn(UserRepo, 'getAll').and.resolveTo([...DummyGetAllUsers]);
56
+ const data = getDummyUsers();
57
+ spyOn(UserRepo, 'getAll').and.resolveTo(data);
69
58
  // Call API
70
- callApi()
71
- .end((_: Error, res: Response) => {
72
- expect(res.status).toBe(OK);
73
- for (let i = 0; i < res.body.users.length; i++) {
74
- const user = res.body.users[i];
75
- expect(user).toEqual(DummyGetAllUsers[i]);
76
- }
77
- done();
78
- });
59
+ api(res => {
60
+ expect(res.status).toBe(HttpStatusCodes.OK);
61
+ expect(res.body).toEqual({ users: data });
62
+ done();
63
+ });
79
64
  });
80
65
  });
81
66
 
82
67
  // Test add user
83
68
  describe(`"POST:${Paths.Users.Add}"`, () => {
84
69
 
85
- const ERROR_MSG = `${ValidatorErr}"user".`;
70
+ const ERROR_MSG = `${ValidatorErr}"user".`,
71
+ DUMMY_USER = getDummyUsers()[0];
86
72
 
87
- const callApi = (reqBody: TReqBody) =>
73
+ // Setup API
74
+ const callApi = (user: IUser | null, cb: TApiCb) =>
88
75
  agent
89
76
  .post(Paths.Users.Add)
90
- .set('Cookie', jwtCookie)
91
- .type('form').send(reqBody);
77
+ .send({ user })
78
+ .end(apiCb(cb));
92
79
 
93
80
  // Test add user success
94
- it(`should return a status code of "${CREATED}" if the request was ` +
95
- 'successful.', (done) => {
81
+ it(`should return a status code of "${HttpStatusCodes.CREATED}" if the ` +
82
+ 'request was successful.', (done) => {
96
83
  // Spy
97
84
  spyOn(UserRepo, 'add').and.resolveTo();
98
85
  // Call api
99
- callApi(DummyUserData)
100
- .end((_: Error, res: Response) => {
101
- expect(res.status).toBe(CREATED);
102
- expect(res.body.error).toBeUndefined();
103
- done();
104
- });
86
+ callApi(DUMMY_USER, res => {
87
+ expect(res.status).toBe(HttpStatusCodes.CREATED);
88
+ done();
89
+ });
105
90
  });
106
91
 
107
92
  // Missing param
108
- it('should return a JSON object with an error message of ' +
109
- `"${ERROR_MSG}" and a status code of "${BAD_REQUEST}" if the user ` +
93
+ it(`should return a JSON object with an error message of "${ERROR_MSG}" ` +
94
+ `and a status code of "${HttpStatusCodes.BAD_REQUEST}" if the user ` +
110
95
  'param was missing.', (done) => {
111
96
  // Call api
112
- callApi({})
113
- .end((_: Error, res: Response) => {
114
- expect(res.status).toBe(BAD_REQUEST);
115
- expect(res.body.error).toBe(ERROR_MSG);
116
- done();
117
- });
97
+ callApi(null, res => {
98
+ expect(res.status).toBe(HttpStatusCodes.BAD_REQUEST);
99
+ expect(res.body.error).toBe(ERROR_MSG);
100
+ done();
101
+ });
118
102
  });
119
103
  });
120
104
 
121
- // ** Update users ** //
105
+ // Update users
122
106
  describe(`"PUT:${Paths.Users.Update}"`, () => {
123
107
 
124
- const ERROR_MSG = `${ValidatorErr}"user".`;
108
+ const ERROR_MSG = `${ValidatorErr}"user".`,
109
+ DUMMY_USER = getDummyUsers()[0];
125
110
 
126
- const callApi = (reqBody: TReqBody) =>
111
+ // Setup API
112
+ const callApi = (user: IUser | null, cb: TApiCb) =>
127
113
  agent
128
114
  .put(Paths.Users.Update)
129
- .set('Cookie', jwtCookie)
130
- .type('form').send(reqBody);
115
+ .send({ user })
116
+ .end(apiCb(cb));
131
117
 
132
118
  // Success
133
- it(`should return a status code of "${OK}" if the request was successful.`,
134
- (done) => {
135
- // Setup spies
136
- spyOn(UserRepo, 'update').and.resolveTo();
137
- spyOn(UserRepo, 'persists').and.resolveTo(true);
138
- // Call api
139
- callApi(DummyUserData)
140
- .end((_: Error, res: Response) => {
141
- expect(res.status).toBe(OK);
142
- expect(res.body.error).toBeUndefined();
143
- done();
144
- });
119
+ it(`should return a status code of "${HttpStatusCodes.OK}" if the ` +
120
+ 'request was successful.', (done) => {
121
+ // Setup spies
122
+ spyOn(UserRepo, 'update').and.resolveTo();
123
+ spyOn(UserRepo, 'persists').and.resolveTo(true);
124
+ // Call api
125
+ callApi(DUMMY_USER, res => {
126
+ expect(res.status).toBe(HttpStatusCodes.OK);
127
+ done();
145
128
  });
129
+ });
146
130
 
147
131
  // Param missing
148
- it('should return a JSON object with an error message of ' +
149
- `"${ERROR_MSG}" and a status code of "${BAD_REQUEST}" if the user ` +
132
+ it(`should return a JSON object with an error message of "${ERROR_MSG}" ` +
133
+ `and a status code of "${HttpStatusCodes.BAD_REQUEST}" if the user ` +
150
134
  'param was missing.', (done) => {
151
135
  // Call api
152
- callApi({})
153
- .end((_: Error, res: Response) => {
154
- expect(res.status).toBe(BAD_REQUEST);
155
- expect(res.body.error).toBe(ERROR_MSG);
156
- done();
157
- });
136
+ callApi(null, res => {
137
+ expect(res.status).toBe(HttpStatusCodes.BAD_REQUEST);
138
+ expect(res.body.error).toBe(ERROR_MSG);
139
+ done();
140
+ });
158
141
  });
159
142
 
160
143
  // User not found
161
144
  it('should return a JSON object with the error message of ' +
162
- `"${USER_NOT_FOUND_ERR}" and a status code of "${NOT_FOUND}" if the id ` +
163
- 'was not found.', (done) => {
145
+ `"${USER_NOT_FOUND_ERR}" and a status code of ` +
146
+ `"${HttpStatusCodes.NOT_FOUND}" if the id was not found.`, (done) => {
164
147
  // Call api
165
- callApi(DummyUserData)
166
- .end((_: Error, res: Response) => {
167
- expect(res.status).toBe(NOT_FOUND);
168
- expect(res.body.error).toBe(USER_NOT_FOUND_ERR);
169
- done();
170
- });
148
+ callApi(DUMMY_USER, res => {
149
+ expect(res.status).toBe(HttpStatusCodes.NOT_FOUND);
150
+ expect(res.body.error).toBe(USER_NOT_FOUND_ERR);
151
+ done();
152
+ });
171
153
  });
172
154
  });
173
155
 
174
- // ** Delete user ** //
156
+ // Delete User
175
157
  describe(`"DELETE:${Paths.Users.Delete}"`, () => {
176
158
 
177
- const VALIDATOR_ERR = `${ValidatorErr}"id".`;
178
-
179
- const callApi = (id: number) =>
159
+ // Call API
160
+ const callApi = (id: number, cb: TApiCb) =>
180
161
  agent
181
162
  .delete(insertUrlParams(Paths.Users.Delete, { id }))
182
- .set('Cookie', jwtCookie);
163
+ .end(apiCb(cb));
183
164
 
184
165
  // Success
185
- it(`should return a status code of "${OK}" if the request was successful.`,
186
- (done) => {
187
- // Setup spies
188
- spyOn(UserRepo, 'delete').and.resolveTo();
189
- spyOn(UserRepo, 'persists').and.resolveTo(true);
190
- // Call api
191
- callApi(5)
192
- .end((_: Error, res: Response) => {
193
- expect(res.status).toBe(OK);
194
- expect(res.body.error).toBeUndefined();
195
- done();
196
- });
166
+ it(`should return a status code of "${HttpStatusCodes.OK}" if the ` +
167
+ 'request was successful.', (done) => {
168
+ // Setup spies
169
+ spyOn(UserRepo, 'delete').and.resolveTo();
170
+ spyOn(UserRepo, 'persists').and.resolveTo(true);
171
+ // Call api
172
+ callApi(5, res => {
173
+ expect(res.status).toBe(HttpStatusCodes.OK);
174
+ done();
197
175
  });
176
+ });
198
177
 
199
178
  // User not found
200
179
  it('should return a JSON object with the error message of ' +
201
- `"${USER_NOT_FOUND_ERR}" and a status code of "${NOT_FOUND}" if the id ` +
202
- 'was not found.', (done) => {
203
- callApi(-1)
204
- .end((_: Error, res: Response) => {
205
- expect(res.status).toBe(NOT_FOUND);
206
- expect(res.body.error).toBe(USER_NOT_FOUND_ERR);
207
- done();
208
- });
209
- });
210
-
211
- // Invalid param
212
- it(`should return a status code of "${BAD_REQUEST}" and return an error ` +
213
- `message of "${VALIDATOR_ERR}" if the id was not a valid number`, (done) => {
214
- callApi('horse' as unknown as number)
215
- .end((_: Error, res: Response) => {
216
- expect(res.status).toBe(BAD_REQUEST);
217
- expect(res.body.error).toBe(VALIDATOR_ERR);
218
- done();
219
- });
180
+ `"${USER_NOT_FOUND_ERR}" and a status code of ` +
181
+ `"${HttpStatusCodes.NOT_FOUND}" if the id was not found.`, done => {
182
+ // Setup spies
183
+ callApi(-1, res => {
184
+ expect(res.status).toBe(HttpStatusCodes.NOT_FOUND);
185
+ expect(res.body.error).toBe(USER_NOT_FOUND_ERR);
186
+ done();
187
+ });
220
188
  });
221
189
  });
222
190
  });
@@ -0,0 +1,18 @@
1
+ import { Response } from 'supertest';
2
+
3
+ import { IUser } from '@src/models/User';
4
+
5
+
6
+ // Misc
7
+ export type TReqBody = Record<string, unknown>;
8
+ export type TRes = Omit<Response, 'body'> & { body: TBody };
9
+ export type TApiCb = (res: TRes) => void;
10
+
11
+
12
+ // Response Body: Add things to the body here over time to prevent
13
+ // typescript errors.
14
+ type TBody = {
15
+ [key: string]: unknown;
16
+ user?: IUser;
17
+ users?: IUser[];
18
+ }
@@ -1,7 +1,10 @@
1
+ import moment from 'moment';
2
+
3
+
1
4
  // **** Variables **** //
2
5
 
3
- const INVALID_CONSTRUCTOR_PARAM = 'nameOrObj arg must a string or an ' +
4
- 'object with the appropriate user keys.';
6
+ const INVALID_CONSTRUCTOR_PARAM = 'nameOrObj arg must a string or an object ' +
7
+ 'with the appropriate user keys.';
5
8
 
6
9
  export enum UserRoles {
7
10
  Standard,
@@ -15,15 +18,15 @@ export interface IUser {
15
18
  id: number;
16
19
  name: string;
17
20
  email: string;
21
+ created: Date;
22
+ role: UserRoles;
18
23
  pwdHash?: string;
19
- role?: UserRoles;
20
24
  }
21
25
 
22
26
  export interface ISessionUser {
23
27
  id: number;
24
28
  email: string;
25
29
  name: string;
26
- role: IUser['role'];
27
30
  }
28
31
 
29
32
 
@@ -35,6 +38,7 @@ export interface ISessionUser {
35
38
  function new_(
36
39
  name?: string,
37
40
  email?: string,
41
+ created?: Date,
38
42
  role?: UserRoles,
39
43
  pwdHash?: string,
40
44
  id?: number, // id last cause usually set by db
@@ -43,8 +47,9 @@ function new_(
43
47
  id: (id ?? -1),
44
48
  name: (name ?? ''),
45
49
  email: (email ?? ''),
50
+ created: (created ? new Date(created) : new Date()),
46
51
  role: (role ?? UserRoles.Standard),
47
- pwdHash: (pwdHash ?? ''),
52
+ ...( pwdHash ? { pwdHash } : {}),
48
53
  };
49
54
  }
50
55
 
@@ -52,13 +57,11 @@ function new_(
52
57
  * Get user instance from object.
53
58
  */
54
59
  function from(param: object): IUser {
55
- // Check is user
56
60
  if (!isUser(param)) {
57
61
  throw new Error(INVALID_CONSTRUCTOR_PARAM);
58
62
  }
59
- // Get user instance
60
63
  const p = param as IUser;
61
- return new_(p.name, p.email, p.role, p.pwdHash, p.id);
64
+ return new_(p.name, p.email, p.created, p.id);
62
65
  }
63
66
 
64
67
  /**
@@ -68,14 +71,16 @@ function isUser(arg: unknown): boolean {
68
71
  return (
69
72
  !!arg &&
70
73
  typeof arg === 'object' &&
71
- 'id' in arg &&
72
- 'email' in arg &&
73
- 'name' in arg &&
74
- 'role' in arg
74
+ 'id' in arg && typeof arg.id === 'number' &&
75
+ 'email' in arg && typeof arg.email === 'string' &&
76
+ 'name' in arg && typeof arg.name === 'string' &&
77
+ 'created' in arg && moment(arg.created as string | Date).isValid()
75
78
  );
76
79
  }
77
80
 
78
81
 
82
+
83
+
79
84
  // **** Export default **** //
80
85
 
81
86
  export default {
@@ -1,4 +1,5 @@
1
1
  var Http = (() => {
2
+
2
3
  // Setup request for json
3
4
  var getOptions = (verb, data) => {
4
5
  var options = {
@@ -9,11 +10,12 @@ var Http = (() => {
9
10
  'Content-Type': 'application/json',
10
11
  },
11
12
  };
12
- if (data) {
13
+ if (!!data) {
13
14
  options.body = JSON.stringify(data);
14
15
  }
15
16
  return options;
16
17
  };
18
+
17
19
  // Set Http methods
18
20
  return {
19
21
  get: (path) => fetch(path, getOptions('GET')),
@@ -10,8 +10,6 @@ document.addEventListener('click', (event) => {
10
10
  };
11
11
  Http
12
12
  .post('/api/auth/login', data)
13
- .then(() => {
14
- window.location.href = '/users';
15
- });
13
+ .then(() => (window.location.href = '/users'));
16
14
  }
17
15
  }, false);