express-generator-typescript 2.7.4 → 2.7.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/README-git +79 -0
- package/README.md +12 -79
- package/lib/project-files/eslint.config.ts +1 -1
- package/lib/project-files/gitignore +2 -1
- package/lib/project-files/package.json +5 -5
- package/lib/project-files/scripts/build.ts +7 -45
- package/lib/project-files/scripts/common/utils.ts +93 -0
- package/lib/project-files/src/common/constants/ENV.ts +3 -5
- package/lib/project-files/src/common/constants/HTTP_STATUS_CODES.ts +81 -0
- package/lib/project-files/src/common/constants/PATHS.ts +15 -0
- package/lib/project-files/src/common/constants/index.ts +6 -6
- package/lib/project-files/src/common/util/route-errors.ts +4 -3
- package/lib/project-files/src/common/util/validators.ts +0 -1
- package/lib/project-files/src/models/User.ts +5 -8
- package/lib/project-files/src/repos/MockOrm.ts +7 -6
- package/lib/project-files/src/repos/UserRepo.ts +6 -3
- package/lib/project-files/src/repos/database.json +1 -1
- package/lib/project-files/src/repos/database.test.json +1 -1
- package/lib/project-files/src/routes/UserRoutes.ts +5 -8
- package/lib/project-files/src/routes/common/types/index.ts +0 -1
- package/lib/project-files/src/routes/common/util/index.ts +0 -2
- package/lib/project-files/src/routes/index.ts +6 -8
- package/lib/project-files/src/server.ts +10 -8
- package/lib/project-files/src/services/UserService.ts +3 -6
- package/lib/project-files/tests/common/types/index.ts +2 -2
- package/lib/project-files/tests/common/util/index.ts +32 -15
- package/lib/project-files/tests/users.test.ts +25 -33
- package/package.json +1 -1
- package/README-npm +0 -20
- package/lib/project-files/src/common/constants/HttpStatusCodes.ts +0 -391
- package/lib/project-files/src/common/constants/Paths.ts +0 -11
- package/lib/project-files/tests/common/Paths.ts +0 -5
|
@@ -3,7 +3,6 @@ import { getRandomInt } from '@src/common/util/misc';
|
|
|
3
3
|
|
|
4
4
|
import orm from './MockOrm';
|
|
5
5
|
|
|
6
|
-
|
|
7
6
|
/******************************************************************************
|
|
8
7
|
Functions
|
|
9
8
|
******************************************************************************/
|
|
@@ -88,6 +87,9 @@ async function delete_(id: number): Promise<void> {
|
|
|
88
87
|
|
|
89
88
|
/**
|
|
90
89
|
* Delete every user record.
|
|
90
|
+
*
|
|
91
|
+
* @internal
|
|
92
|
+
* Test-only helper. Do not use in production code.
|
|
91
93
|
*/
|
|
92
94
|
async function deleteAllUsers(): Promise<void> {
|
|
93
95
|
const db = await orm.openDb();
|
|
@@ -98,6 +100,9 @@ async function deleteAllUsers(): Promise<void> {
|
|
|
98
100
|
/**
|
|
99
101
|
* Insert multiple users. Can't do multiple at once cause using a plain file
|
|
100
102
|
* for now.
|
|
103
|
+
*
|
|
104
|
+
* @internal
|
|
105
|
+
* Test-only helper. Do not use in production code.
|
|
101
106
|
*/
|
|
102
107
|
async function insertMult(
|
|
103
108
|
users: IUser[] | readonly IUser[],
|
|
@@ -113,7 +118,6 @@ async function insertMult(
|
|
|
113
118
|
return usersF;
|
|
114
119
|
}
|
|
115
120
|
|
|
116
|
-
|
|
117
121
|
/******************************************************************************
|
|
118
122
|
Export default
|
|
119
123
|
******************************************************************************/
|
|
@@ -128,4 +132,3 @@ export default {
|
|
|
128
132
|
deleteAllUsers,
|
|
129
133
|
insertMult,
|
|
130
134
|
} as const;
|
|
131
|
-
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"users":[{"id":366115170645,"name":"Sean Maxwell","email":"smaxwell@example.com","created":"2024-03-22T05:14:36.252Z"},{"id":310946254456,"name":"John Smith","email":"john.smith@example.com","created":"2024-03-22T05:20:55.079Z"},{"id":143027113460,"name":"Gordan Freeman","email":"nova@prospect.com","created":"2024-03-22T05:42:18.895Z"}]}
|
|
1
|
+
{"users":[{"id":366115170645,"name":"Sean Maxwell","email":"smaxwell@example.com","created":"2024-03-22T05:14:36.252Z"},{"id":310946254456,"name":"John Smith","email":"john.smith@example.com","created":"2024-03-22T05:20:55.079Z"},{"id":143027113460,"name":"Gordan Freeman","email":"nova@prospect.com","created":"2024-03-22T05:42:18.895Z"}]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"users":[{"id":
|
|
1
|
+
{"users":[{"id":967269206317,"name":"Bill","created":"2025-12-17T09:55:17.960Z","email":"sean.maxwell@gmail.com"},{"id":3025435078,"name":"John Smith","created":"2025-12-17T09:55:17.960Z","email":"john.smith@gmail.com"},{"id":786429791732,"name":"Gordan Freeman","created":"2025-12-17T09:55:17.960Z","email":"gordan.freeman@gmail.com"}]}
|
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
import { isNumber } from 'jet-validators';
|
|
2
2
|
import { transform } from 'jet-validators/utils';
|
|
3
3
|
|
|
4
|
-
import
|
|
4
|
+
import HTTP_STATUS_CODES from '@src/common/constants/HTTP_STATUS_CODES';
|
|
5
5
|
import UserService from '@src/services/UserService';
|
|
6
6
|
import User from '@src/models/User';
|
|
7
7
|
|
|
8
8
|
import { IReq, IRes } from './common/types';
|
|
9
9
|
import { parseReq } from './common/util';
|
|
10
10
|
|
|
11
|
-
|
|
12
11
|
/******************************************************************************
|
|
13
12
|
Constants
|
|
14
13
|
******************************************************************************/
|
|
@@ -19,7 +18,6 @@ const Validators = {
|
|
|
19
18
|
delete: parseReq({ id: transform(Number, isNumber) }),
|
|
20
19
|
} as const;
|
|
21
20
|
|
|
22
|
-
|
|
23
21
|
/******************************************************************************
|
|
24
22
|
Functions
|
|
25
23
|
******************************************************************************/
|
|
@@ -29,7 +27,7 @@ const Validators = {
|
|
|
29
27
|
*/
|
|
30
28
|
async function getAll(_: IReq, res: IRes) {
|
|
31
29
|
const users = await UserService.getAll();
|
|
32
|
-
res.status(
|
|
30
|
+
res.status(HTTP_STATUS_CODES.Ok).json({ users });
|
|
33
31
|
}
|
|
34
32
|
|
|
35
33
|
/**
|
|
@@ -38,7 +36,7 @@ async function getAll(_: IReq, res: IRes) {
|
|
|
38
36
|
async function add(req: IReq, res: IRes) {
|
|
39
37
|
const { user } = Validators.add(req.body);
|
|
40
38
|
await UserService.addOne(user);
|
|
41
|
-
res.status(
|
|
39
|
+
res.status(HTTP_STATUS_CODES.Created).end();
|
|
42
40
|
}
|
|
43
41
|
|
|
44
42
|
/**
|
|
@@ -47,7 +45,7 @@ async function add(req: IReq, res: IRes) {
|
|
|
47
45
|
async function update(req: IReq, res: IRes) {
|
|
48
46
|
const { user } = Validators.update(req.body);
|
|
49
47
|
await UserService.updateOne(user);
|
|
50
|
-
res.status(
|
|
48
|
+
res.status(HTTP_STATUS_CODES.Ok).end();
|
|
51
49
|
}
|
|
52
50
|
|
|
53
51
|
/**
|
|
@@ -56,10 +54,9 @@ async function update(req: IReq, res: IRes) {
|
|
|
56
54
|
async function delete_(req: IReq, res: IRes) {
|
|
57
55
|
const { id } = Validators.delete(req.params);
|
|
58
56
|
await UserService.delete(id);
|
|
59
|
-
res.status(
|
|
57
|
+
res.status(HTTP_STATUS_CODES.Ok).end();
|
|
60
58
|
}
|
|
61
59
|
|
|
62
|
-
|
|
63
60
|
/******************************************************************************
|
|
64
61
|
Export default
|
|
65
62
|
******************************************************************************/
|
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
import { parseObject, TSchema } from 'jet-validators/utils';
|
|
2
|
-
|
|
3
2
|
import { ValidationError } from '@src/common/util/route-errors';
|
|
4
3
|
|
|
5
|
-
|
|
6
4
|
/******************************************************************************
|
|
7
5
|
Functions
|
|
8
6
|
******************************************************************************/
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import { Router } from 'express';
|
|
2
2
|
|
|
3
|
-
import
|
|
3
|
+
import PATHS from '@src/common/constants/PATHS';
|
|
4
4
|
import UserRoutes from './UserRoutes';
|
|
5
5
|
|
|
6
|
-
|
|
7
6
|
/******************************************************************************
|
|
8
7
|
Setup
|
|
9
8
|
******************************************************************************/
|
|
@@ -17,14 +16,13 @@ const apiRouter = Router();
|
|
|
17
16
|
const userRouter = Router();
|
|
18
17
|
|
|
19
18
|
// Get all users
|
|
20
|
-
userRouter.get(
|
|
21
|
-
userRouter.post(
|
|
22
|
-
userRouter.put(
|
|
23
|
-
userRouter.delete(
|
|
19
|
+
userRouter.get(PATHS.Users.Get, UserRoutes.getAll);
|
|
20
|
+
userRouter.post(PATHS.Users.Add, UserRoutes.add);
|
|
21
|
+
userRouter.put(PATHS.Users.Update, UserRoutes.update);
|
|
22
|
+
userRouter.delete(PATHS.Users.Delete, UserRoutes.delete);
|
|
24
23
|
|
|
25
24
|
// Add UserRouter
|
|
26
|
-
apiRouter.use(
|
|
27
|
-
|
|
25
|
+
apiRouter.use(PATHS.Users._, userRouter);
|
|
28
26
|
|
|
29
27
|
/******************************************************************************
|
|
30
28
|
Export default
|
|
@@ -6,11 +6,13 @@ import logger from 'jet-logger';
|
|
|
6
6
|
|
|
7
7
|
import BaseRouter from '@src/routes';
|
|
8
8
|
|
|
9
|
-
import Paths from '@src/common/constants/
|
|
9
|
+
import Paths from '@src/common/constants/PATHS';
|
|
10
10
|
import ENV from '@src/common/constants/ENV';
|
|
11
|
-
import
|
|
11
|
+
import HTTP_STATUS_CODES, {
|
|
12
|
+
HttpStatusCodes,
|
|
13
|
+
} from '@src/common/constants/HTTP_STATUS_CODES';
|
|
12
14
|
import { RouteError } from '@src/common/util/route-errors';
|
|
13
|
-
import {
|
|
15
|
+
import { NODE_ENVS } from '@src/common/constants';
|
|
14
16
|
|
|
15
17
|
|
|
16
18
|
/******************************************************************************
|
|
@@ -27,12 +29,12 @@ app.use(express.json());
|
|
|
27
29
|
app.use(express.urlencoded({extended: true}));
|
|
28
30
|
|
|
29
31
|
// Show routes called in console during development
|
|
30
|
-
if (ENV.NodeEnv ===
|
|
32
|
+
if (ENV.NodeEnv === NODE_ENVS.Dev) {
|
|
31
33
|
app.use(morgan('dev'));
|
|
32
34
|
}
|
|
33
35
|
|
|
34
36
|
// Security
|
|
35
|
-
if (ENV.NodeEnv ===
|
|
37
|
+
if (ENV.NodeEnv === NODE_ENVS.Production) {
|
|
36
38
|
// eslint-disable-next-line n/no-process-env
|
|
37
39
|
if (!process.env.DISABLE_HELMET) {
|
|
38
40
|
app.use(helmet());
|
|
@@ -40,14 +42,14 @@ if (ENV.NodeEnv === NodeEnvs.Production) {
|
|
|
40
42
|
}
|
|
41
43
|
|
|
42
44
|
// Add APIs, must be after middleware
|
|
43
|
-
app.use(Paths.
|
|
45
|
+
app.use(Paths._, BaseRouter);
|
|
44
46
|
|
|
45
47
|
// Add error handler
|
|
46
48
|
app.use((err: Error, _: Request, res: Response, next: NextFunction) => {
|
|
47
|
-
if (ENV.NodeEnv !==
|
|
49
|
+
if (ENV.NodeEnv !== NODE_ENVS.Test.valueOf()) {
|
|
48
50
|
logger.err(err, true);
|
|
49
51
|
}
|
|
50
|
-
let status =
|
|
52
|
+
let status: HttpStatusCodes = HTTP_STATUS_CODES.BadRequest;
|
|
51
53
|
if (err instanceof RouteError) {
|
|
52
54
|
status = err.status;
|
|
53
55
|
res.status(status).json({ error: err.message });
|
|
@@ -1,17 +1,15 @@
|
|
|
1
1
|
import { RouteError } from '@src/common/util/route-errors';
|
|
2
|
-
import
|
|
2
|
+
import HTTP_STATUS_CODES from '@src/common/constants/HTTP_STATUS_CODES';
|
|
3
3
|
|
|
4
4
|
import UserRepo from '@src/repos/UserRepo';
|
|
5
5
|
import { IUser } from '@src/models/User';
|
|
6
6
|
|
|
7
|
-
|
|
8
7
|
/******************************************************************************
|
|
9
8
|
Constants
|
|
10
9
|
******************************************************************************/
|
|
11
10
|
|
|
12
11
|
export const USER_NOT_FOUND_ERR = 'User not found';
|
|
13
12
|
|
|
14
|
-
|
|
15
13
|
/******************************************************************************
|
|
16
14
|
Functions
|
|
17
15
|
******************************************************************************/
|
|
@@ -37,7 +35,7 @@ async function updateOne(user: IUser): Promise<void> {
|
|
|
37
35
|
const persists = await UserRepo.persists(user.id);
|
|
38
36
|
if (!persists) {
|
|
39
37
|
throw new RouteError(
|
|
40
|
-
|
|
38
|
+
HTTP_STATUS_CODES.NotFound,
|
|
41
39
|
USER_NOT_FOUND_ERR,
|
|
42
40
|
);
|
|
43
41
|
}
|
|
@@ -52,7 +50,7 @@ async function _delete(id: number): Promise<void> {
|
|
|
52
50
|
const persists = await UserRepo.persists(id);
|
|
53
51
|
if (!persists) {
|
|
54
52
|
throw new RouteError(
|
|
55
|
-
|
|
53
|
+
HTTP_STATUS_CODES.NotFound,
|
|
56
54
|
USER_NOT_FOUND_ERR,
|
|
57
55
|
);
|
|
58
56
|
}
|
|
@@ -60,7 +58,6 @@ async function _delete(id: number): Promise<void> {
|
|
|
60
58
|
return UserRepo.delete(id);
|
|
61
59
|
}
|
|
62
60
|
|
|
63
|
-
|
|
64
61
|
/******************************************************************************
|
|
65
62
|
Export default
|
|
66
63
|
******************************************************************************/
|
|
@@ -7,10 +7,10 @@ import { Response } from 'supertest';
|
|
|
7
7
|
|
|
8
8
|
// Use generics to add properties to 'body'
|
|
9
9
|
export type TRes<T = object> = Omit<Response, 'body'> & {
|
|
10
|
-
body: T & { error?: string |
|
|
10
|
+
body: T & { error?: string | IErrorObject },
|
|
11
11
|
};
|
|
12
12
|
|
|
13
|
-
interface
|
|
13
|
+
interface IErrorObject {
|
|
14
14
|
message: string;
|
|
15
15
|
[key: string]: unknown;
|
|
16
16
|
}
|
|
@@ -1,28 +1,18 @@
|
|
|
1
|
-
import { Response } from 'supertest';
|
|
2
1
|
import { IParseObjectError, parseJson } from 'jet-validators/utils';
|
|
3
2
|
import { isString } from 'jet-validators';
|
|
4
|
-
|
|
3
|
+
import { IUser } from '@src/models/User';
|
|
5
4
|
|
|
6
5
|
/******************************************************************************
|
|
7
6
|
Types
|
|
8
7
|
******************************************************************************/
|
|
9
8
|
|
|
10
|
-
|
|
11
|
-
export type TRes<T = object> = Omit<Response, 'body'> & {
|
|
12
|
-
body: T & { error?: string | IErrObj },
|
|
13
|
-
};
|
|
14
|
-
|
|
15
|
-
interface IErrObj {
|
|
16
|
-
message: string;
|
|
17
|
-
[key: string]: unknown;
|
|
18
|
-
}
|
|
9
|
+
type TUserArray = IUser[] | readonly IUser[];
|
|
19
10
|
|
|
20
|
-
interface
|
|
11
|
+
interface IValidationError {
|
|
21
12
|
message: string;
|
|
22
13
|
errors: IParseObjectError[];
|
|
23
14
|
}
|
|
24
15
|
|
|
25
|
-
|
|
26
16
|
/******************************************************************************
|
|
27
17
|
Functions
|
|
28
18
|
******************************************************************************/
|
|
@@ -30,9 +20,36 @@ interface IValidationErr {
|
|
|
30
20
|
/**
|
|
31
21
|
* JSON parse a validation error.
|
|
32
22
|
*/
|
|
33
|
-
export function
|
|
23
|
+
export function parseValidationError(arg: unknown): IValidationError {
|
|
34
24
|
if (!isString(arg)) {
|
|
35
25
|
throw new Error('Not a string');
|
|
36
26
|
}
|
|
37
|
-
return parseJson<
|
|
27
|
+
return parseJson<IValidationError>(arg);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Compare to user arrays. Order does not matter and this assumes the email
|
|
32
|
+
* field is unique
|
|
33
|
+
*/
|
|
34
|
+
export function compareUserArrays(a: TUserArray, b: TUserArray): boolean {
|
|
35
|
+
if (a.length !== b.length) return false;
|
|
36
|
+
const aSorted = sortByEmail(a);
|
|
37
|
+
const bSorted = sortByEmail(b);
|
|
38
|
+
for (let i = 0; i < aSorted.length; i++) {
|
|
39
|
+
const a = aSorted[i],
|
|
40
|
+
b = bSorted[i];
|
|
41
|
+
if (a.email !== b.email || a.name !== b.name) {
|
|
42
|
+
return false;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
return true;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Sort user array by email.
|
|
50
|
+
*/
|
|
51
|
+
function sortByEmail(arr: TUserArray): IUser[] {
|
|
52
|
+
return [...arr].sort((x, y) => {
|
|
53
|
+
return x.email.localeCompare(y.email);
|
|
54
|
+
});
|
|
38
55
|
}
|
|
@@ -1,17 +1,16 @@
|
|
|
1
1
|
import insertUrlParams from 'inserturlparams';
|
|
2
|
-
import { customDeepCompare } from 'jet-validators/utils';
|
|
3
2
|
|
|
4
3
|
import UserRepo from '@src/repos/UserRepo';
|
|
5
4
|
import User, { IUser } from '@src/models/User';
|
|
6
5
|
import { USER_NOT_FOUND_ERR } from '@src/services/UserService';
|
|
7
6
|
|
|
8
|
-
import
|
|
7
|
+
import HTTP_STATUS_CODES from '@src/common/constants/HTTP_STATUS_CODES';
|
|
9
8
|
import { ValidationError } from '@src/common/util/route-errors';
|
|
9
|
+
import { JET_PATHS as Paths } from '@src/common/constants/PATHS';
|
|
10
10
|
|
|
11
|
-
import
|
|
12
|
-
import { parseValidationErr, TRes } from './common/util';
|
|
11
|
+
import { compareUserArrays, parseValidationError } from './common/util';
|
|
13
12
|
import { agent } from './support/setup';
|
|
14
|
-
|
|
13
|
+
import { TRes } from './common/types';
|
|
15
14
|
|
|
16
15
|
/******************************************************************************
|
|
17
16
|
Constants
|
|
@@ -24,13 +23,6 @@ const DB_USERS = [
|
|
|
24
23
|
User.new({ name: 'Gordan Freeman', email: 'gordan.freeman@gmail.com' }),
|
|
25
24
|
] as const;
|
|
26
25
|
|
|
27
|
-
// Don't compare "id" and "created" cause those are set dynamically by the
|
|
28
|
-
// database
|
|
29
|
-
const compareUserArrays = customDeepCompare({
|
|
30
|
-
onlyCompareProps: ['name', 'email'],
|
|
31
|
-
});
|
|
32
|
-
|
|
33
|
-
|
|
34
26
|
/******************************************************************************
|
|
35
27
|
Tests
|
|
36
28
|
IMPORTANT: Following TypeScript best practices, we test all scenarios that
|
|
@@ -53,9 +45,9 @@ describe('UserRouter', () => {
|
|
|
53
45
|
|
|
54
46
|
// Success
|
|
55
47
|
it('should return a JSON object with all the users and a status code ' +
|
|
56
|
-
`of "${
|
|
48
|
+
`of "${HTTP_STATUS_CODES.Ok}" if the request was successful.`, async () => {
|
|
57
49
|
const res: TRes<{ users: IUser[]}> = await agent.get(Paths.Users.Get);
|
|
58
|
-
expect(res.status).toBe(
|
|
50
|
+
expect(res.status).toBe(HTTP_STATUS_CODES.Ok);
|
|
59
51
|
expect(compareUserArrays(res.body.users, DB_USERS)).toBeTruthy();
|
|
60
52
|
});
|
|
61
53
|
});
|
|
@@ -64,20 +56,20 @@ describe('UserRouter', () => {
|
|
|
64
56
|
describe(`"POST:${Paths.Users.Add}"`, () => {
|
|
65
57
|
|
|
66
58
|
// Test add user success
|
|
67
|
-
it(`should return a status code of "${
|
|
68
|
-
'request was successful.', async () => {
|
|
59
|
+
it(`should return a status code of "${HTTP_STATUS_CODES.Created}" if ` +
|
|
60
|
+
'the request was successful.', async () => {
|
|
69
61
|
const user = User.new({ name: 'a', email: 'a@a.com' }),
|
|
70
62
|
res = await agent.post(Paths.Users.Add).send({ user });
|
|
71
|
-
expect(res.status).toBe(
|
|
63
|
+
expect(res.status).toBe(HTTP_STATUS_CODES.Created);
|
|
72
64
|
});
|
|
73
65
|
|
|
74
66
|
// Missing param
|
|
75
67
|
it('should return a JSON object with an error message of and a status ' +
|
|
76
|
-
`code of "${
|
|
68
|
+
`code of "${HTTP_STATUS_CODES.BadRequest}" if the user param was ` +
|
|
77
69
|
'missing.', async () => {
|
|
78
70
|
const res: TRes = await agent.post(Paths.Users.Add).send({ user: null });
|
|
79
|
-
expect(res.status).toBe(
|
|
80
|
-
const errorObj =
|
|
71
|
+
expect(res.status).toBe(HTTP_STATUS_CODES.BadRequest);
|
|
72
|
+
const errorObj = parseValidationError(res.body.error);
|
|
81
73
|
expect(errorObj.message).toBe(ValidationError.MESSAGE);
|
|
82
74
|
expect(errorObj.errors[0].prop).toBe('user');
|
|
83
75
|
});
|
|
@@ -87,23 +79,23 @@ describe('UserRouter', () => {
|
|
|
87
79
|
describe(`"PUT:${Paths.Users.Update}"`, () => {
|
|
88
80
|
|
|
89
81
|
// Success
|
|
90
|
-
it(`should return a status code of "${
|
|
82
|
+
it(`should return a status code of "${HTTP_STATUS_CODES.Ok}" if the ` +
|
|
91
83
|
'request was successful.', async () => {
|
|
92
84
|
const user = DB_USERS[0];
|
|
93
85
|
user.name = 'Bill';
|
|
94
86
|
const res = await agent.put(Paths.Users.Update).send({ user });
|
|
95
|
-
expect(res.status).toBe(
|
|
87
|
+
expect(res.status).toBe(HTTP_STATUS_CODES.Ok);
|
|
96
88
|
});
|
|
97
89
|
|
|
98
90
|
// Id is the wrong data type
|
|
99
91
|
it('should return a JSON object with an error message and a status code ' +
|
|
100
|
-
`of "${
|
|
92
|
+
`of "${HTTP_STATUS_CODES.BadRequest}" if the user param was missing`,
|
|
101
93
|
async () => {
|
|
102
94
|
const user = User.new();
|
|
103
95
|
user.id = ('5' as unknown as number);
|
|
104
96
|
const res: TRes = await agent.put(Paths.Users.Update).send({ user });
|
|
105
|
-
expect(res.status).toBe(
|
|
106
|
-
const errorObj =
|
|
97
|
+
expect(res.status).toBe(HTTP_STATUS_CODES.BadRequest);
|
|
98
|
+
const errorObj = parseValidationError(res.body.error);
|
|
107
99
|
expect(errorObj.message).toBe(ValidationError.MESSAGE);
|
|
108
100
|
expect(errorObj.errors[0].prop).toBe('user');
|
|
109
101
|
expect(errorObj.errors[0].children?.[0].prop).toBe('id');
|
|
@@ -112,34 +104,34 @@ describe('UserRouter', () => {
|
|
|
112
104
|
// User not found
|
|
113
105
|
it('should return a JSON object with the error message of ' +
|
|
114
106
|
`"${USER_NOT_FOUND_ERR}" and a status code of ` +
|
|
115
|
-
`"${
|
|
107
|
+
`"${HTTP_STATUS_CODES.NotFound}" if the id was not found.`, async () => {
|
|
116
108
|
const user = User.new({ id: 4, name: 'a', email: 'a@a.com' }),
|
|
117
109
|
res: TRes = await agent.put(Paths.Users.Update).send({ user });
|
|
118
|
-
expect(res.status).toBe(
|
|
110
|
+
expect(res.status).toBe(HTTP_STATUS_CODES.NotFound);
|
|
119
111
|
expect(res.body.error).toBe(USER_NOT_FOUND_ERR);
|
|
120
112
|
});
|
|
121
113
|
});
|
|
122
114
|
|
|
123
115
|
// Delete User
|
|
124
|
-
describe(`"DELETE:${Paths.Users.Delete}"`, () => {
|
|
116
|
+
describe(`"DELETE:${Paths.Users.Delete()}"`, () => {
|
|
125
117
|
|
|
126
|
-
const getPath = (id: number) => insertUrlParams(Paths.Users.Delete,
|
|
118
|
+
const getPath = (id: number) => insertUrlParams(Paths.Users.Delete({ id}),
|
|
127
119
|
{ id });
|
|
128
120
|
|
|
129
121
|
// Success
|
|
130
|
-
it(`should return a status code of "${
|
|
122
|
+
it(`should return a status code of "${HTTP_STATUS_CODES.Ok}" if the ` +
|
|
131
123
|
'request was successful.', async () => {
|
|
132
124
|
const id = dbUsers[0].id,
|
|
133
125
|
res = await agent.delete(getPath(id));
|
|
134
|
-
expect(res.status).toBe(
|
|
126
|
+
expect(res.status).toBe(HTTP_STATUS_CODES.Ok);
|
|
135
127
|
});
|
|
136
128
|
|
|
137
129
|
// User not found
|
|
138
130
|
it('should return a JSON object with the error message of ' +
|
|
139
131
|
`"${USER_NOT_FOUND_ERR}" and a status code of ` +
|
|
140
|
-
`"${
|
|
132
|
+
`"${HTTP_STATUS_CODES.NotFound}" if the id was not found.`, async () => {
|
|
141
133
|
const res: TRes = await agent.delete(getPath(-1));
|
|
142
|
-
expect(res.status).toBe(
|
|
134
|
+
expect(res.status).toBe(HTTP_STATUS_CODES.NotFound);
|
|
143
135
|
expect(res.body.error).toBe(USER_NOT_FOUND_ERR);
|
|
144
136
|
});
|
|
145
137
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "express-generator-typescript",
|
|
3
|
-
"version": "2.7.
|
|
3
|
+
"version": "2.7.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",
|
package/README-npm
DELETED
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
<img alt='overnightjs' src='https://github.com/seanpmaxwell/express-generator-typescript/raw/master/express-typescript.png' border='0'>
|
|
2
|
-
|
|
3
|
-
[Express](https://www.npmjs.com/package/express) with [TypeScript's](https://www.npmjs.com/package/typescript) application generator.
|
|
4
|
-
|
|
5
|
-
<a href="https://www.npmjs.com/package/express-generator-typescript" target="_blank"><img src="https://img.shields.io/npm/v/express-generator-typescript.svg" alt="NPM Version" /></a>
|
|
6
|
-
<a href="https://www.npmjs.com/package/express-generator-typescript" target="_blank"><img src="https://img.shields.io/npm/l/express-generator-typescript.svg" alt="Package License" /></a>
|
|
7
|
-
<a href="https://www.npmjs.com/package/express-generator-typescript" target="_blank"><img src="https://img.shields.io/npm/dm/express-generator-typescript.svg" alt="NPM Downloads" /></a>
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
## What is it?
|
|
11
|
-
|
|
12
|
-
Creates a new express application similar to the _express-generator_ module. Except this new application is configured to use TypeScript instead of plain JavaScript.
|
|
13
|
-
|
|
14
|
-
This project complies with Typescript best practices listed <a href="https://github.com/seanpmaxwell/Typescript-Best-Practices/blob/main/README.md">here</a>.
|
|
15
|
-
<br/>
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
## Documenation
|
|
19
|
-
|
|
20
|
-
Please refer to the official <a href="https://github.com/seanpmaxwell/express-generator-typescript">github repo</a> for the most up-to-date documentation.
|