Skip to content

Commit 1e11978

Browse files
authored
Merge pull request #80 from waldemarnt/update-deps
Update all dependencies from chapter 1 to 9
2 parents e7e1e19 + 0a2ff85 commit 1e11978

File tree

17 files changed

+2179
-3453
lines changed

17 files changed

+2179
-3453
lines changed

.github/workflows/full-workflow.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,11 @@ jobs:
2121

2222
strategy:
2323
matrix:
24-
node-version: [14.x]
24+
node-version: [16.x]
2525

2626
services:
2727
mongodb:
28-
image: mongo:4.2
28+
image: mongo:5.0
2929
ports:
3030
- 27017
3131
options: >-

jest.config.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,5 +10,5 @@ module.exports = {
1010
moduleNameMapper: {
1111
'@src/(.*)': '<rootDir>/src/$1',
1212
'@test/(.*)': '<rootDir>/test/$1',
13-
},
13+
}
1414
};

package.json

Lines changed: 41 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
"style:fix": "prettier --write src/**/*.ts' test/**/*.ts"
1717
},
1818
"engines": {
19-
"node": "14"
19+
"node": "16"
2020
},
2121
"repository": {
2222
"type": "git",
@@ -35,53 +35,51 @@
3535
},
3636
"homepage": "https://github.com/waldemarnt/node-typescript-api#readme",
3737
"dependencies": {
38-
"@overnightjs/core": "^1.7.4",
39-
"axios": "^0.21.1",
40-
"bcrypt": "^5.0.0",
41-
"body-parser": "^1.19.0",
42-
"config": "^3.3.1",
38+
"@overnightjs/core": "^1.7.6",
39+
"@types/express": "^4.17.13",
40+
"axios": "^0.24.0",
41+
"bcrypt": "^5.0.1",
42+
"body-parser": "^1.19.1",
43+
"config": "^3.3.6",
4344
"cors": "^2.8.5",
44-
"express": "^4.17.1",
45-
"express-openapi-validator": "^3.16.1",
46-
"express-pino-logger": "^5.0.0",
47-
"express-rate-limit": "^5.1.3",
48-
"http-status-codes": "^1.4.0",
45+
"express": "^4.17.2",
46+
"express-openapi-validator": "^4.13.5",
47+
"express-pino-logger": "^7.0.0",
48+
"express-rate-limit": "^6.0.1",
49+
"http-status-codes": "^2.2.0",
4950
"jsonwebtoken": "^8.5.1",
50-
"lodash": "^4.17.19",
51+
"lodash": "^4.17.21",
5152
"module-alias": "^2.2.2",
52-
"moment": "^2.27.0",
53-
"mongoose": "^5.9.18",
53+
"moment": "^2.29.1",
54+
"mongoose": "^6.1.4",
5455
"node-cache": "^5.1.2",
55-
"pino": "^6.3.2",
56-
"swagger-ui-express": "^4.1.4"
56+
"pino": "^7.6.2",
57+
"swagger-ui-express": "^4.3.0"
5758
},
5859
"devDependencies": {
59-
"@types/bcrypt": "^3.0.0",
60-
"@types/config": "^0.0.36",
61-
"@types/cors": "^2.8.7",
62-
"@types/express": "^4.17.6",
63-
"@types/express-pino-logger": "^4.0.2",
64-
"@types/express-rate-limit": "^5.0.0",
65-
"@types/jest": "^25.2.2",
66-
"@types/jsonwebtoken": "^8.5.0",
67-
"@types/lodash": "^4.14.155",
68-
"@types/module-alias": "^2.0.0",
69-
"@types/multer": "^1.4.3",
70-
"@types/node": "14",
71-
"@types/pino": "^6.3.0",
72-
"@types/supertest": "^2.0.9",
73-
"@types/swagger-ui-express": "^4.1.2",
74-
"@typescript-eslint/eslint-plugin": "^2.29.0",
75-
"@typescript-eslint/parser": "^2.29.0",
76-
"dotenv-cli": "^3.2.0",
77-
"eslint": "^6.8.0",
78-
"jest": "^26.6.3",
79-
"nock": "^12.0.3",
80-
"pino-pretty": "^4.0.0",
81-
"prettier": "^2.0.5",
82-
"supertest": "^4.0.2",
83-
"ts-jest": "^26.4.4",
84-
"ts-node-dev": "^1.0.0-pre.61",
85-
"typescript": "^4.1.3"
60+
"@types/bcrypt": "^5.0.0",
61+
"@types/config": "^0.0.40",
62+
"@types/cors": "^2.8.12",
63+
"@types/express-pino-logger": "^4.0.3",
64+
"@types/jest": "^27.0.3",
65+
"@types/jsonwebtoken": "^8.5.6",
66+
"@types/lodash": "^4.14.178",
67+
"@types/module-alias": "^2.0.1",
68+
"@types/node": "16",
69+
"@types/supertest": "^2.0.11",
70+
"@types/swagger-ui-express": "^4.1.3",
71+
"@typescript-eslint/eslint-plugin": "^5.8.1",
72+
"@typescript-eslint/parser": "^5.8.1",
73+
"dotenv-cli": "^4.1.1",
74+
"eslint": "^8.5.0",
75+
"is-typedarray": "^1.0.0",
76+
"jest": "^27.4.5",
77+
"nock": "^13.2.1",
78+
"pino-pretty": "^7.3.0",
79+
"prettier": "^2.5.1",
80+
"supertest": "^6.1.6",
81+
"ts-jest": "^27.1.2",
82+
"ts-node-dev": "^1.1.8",
83+
"typescript": "^4.5.4"
8684
}
8785
}

src/api-schema.json

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,21 @@
6161
}
6262
}
6363
}
64+
},
65+
"409": {
66+
"description": "Conflict",
67+
"content": {
68+
"application/json": {
69+
"schema": {
70+
"$ref": "#/components/schemas/Error"
71+
},
72+
"example": {
73+
"message": "Conflict",
74+
"code": "409",
75+
"error": "Conflict"
76+
}
77+
}
78+
}
6479
}
6580
}
6681
}

src/clients/__test__/stormGlass.test.ts

Lines changed: 18 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -78,35 +78,42 @@ describe('StormGlass client', () => {
7878
const lat = -33.792726;
7979
const lng = 151.289824;
8080

81-
mockedRequest.get.mockRejectedValue({ message: 'Network Error' });
81+
mockedRequest.get.mockRejectedValue('Network Error');
8282

8383
MockedCacheUtil.get.mockReturnValue(undefined);
8484

8585
const stormGlass = new StormGlass(mockedRequest, MockedCacheUtil);
8686

8787
await expect(stormGlass.fetchPoints(lat, lng)).rejects.toThrow(
88-
'Unexpected error when trying to communicate to StormGlass: Network Error'
88+
'Unexpected error when trying to communicate to StormGlass: "Network Error"'
8989
);
9090
});
9191

9292
it('should get an StormGlassResponseError when the StormGlass service responds with error', async () => {
9393
const lat = -33.792726;
9494
const lng = 151.289824;
9595

96-
mockedRequest.get.mockRejectedValue({
97-
response: {
96+
class FakeAxiosError extends Error {
97+
constructor(public response: object) {
98+
super();
99+
}
100+
}
101+
102+
mockedRequest.get.mockRejectedValue(
103+
new FakeAxiosError({
98104
status: 429,
99105
data: { errors: ['Rate Limit reached'] },
100-
},
101-
});
102-
/**
103-
* Mock static function return
104-
*/
106+
})
107+
);
108+
105109
MockedRequestClass.isRequestError.mockReturnValue(true);
106110

107-
MockedCacheUtil.get.mockReturnValue(undefined);
111+
MockedRequestClass.extractErrorData.mockReturnValue({
112+
status: 429,
113+
data: { errors: ['Rate Limit reached'] },
114+
});
108115

109-
const stormGlass = new StormGlass(mockedRequest, MockedCacheUtil);
116+
const stormGlass = new StormGlass(mockedRequest);
110117

111118
await expect(stormGlass.fetchPoints(lat, lng)).rejects.toThrow(
112119
'Unexpected error returned by the StormGlass service: Error: {"errors":["Rate Limit reached"]} Code: 429'

src/clients/stormGlass.ts

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -116,17 +116,18 @@ export class StormGlass {
116116
);
117117
return this.normalizeResponse(response.data);
118118
} catch (err) {
119-
/**
120-
* This is handling the Axios errors specifically
121-
*/
122-
if (HTTPUtil.Request.isRequestError(err)) {
119+
//@Updated 2022 to support Error as unknown
120+
//https://devblogs.microsoft.com/typescript/announcing-typescript-4-4/#use-unknown-catch-variables
121+
if (err instanceof Error && HTTPUtil.Request.isRequestError(err)) {
122+
const error = HTTPUtil.Request.extractErrorData(err);
123123
throw new StormGlassResponseError(
124-
`Error: ${JSON.stringify(err.response.data)} Code: ${
125-
err.response.status
126-
}`
124+
`Error: ${JSON.stringify(error.data)} Code: ${error.status}`
127125
);
128126
}
129-
throw new ClientRequestError(err.message);
127+
/**
128+
* All the other errors will fallback to a generic client error
129+
*/
130+
throw new ClientRequestError(JSON.stringify(err));
130131
}
131132
}
132133

src/controllers/index.ts

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,7 @@ import logger from '@src/logger';
55
import ApiError, { APIError } from '@src/util/errors/api-error';
66

77
export abstract class BaseController {
8-
protected sendCreateUpdateErrorResponse(
9-
res: Response,
10-
error: mongoose.Error.ValidationError | Error
11-
): void {
8+
protected sendCreateUpdateErrorResponse(res: Response, error: unknown): void {
129
if (error instanceof mongoose.Error.ValidationError) {
1310
const clientErrors = this.handleClientErrors(error);
1411
res.status(clientErrors.code).send(
@@ -18,18 +15,21 @@ export abstract class BaseController {
1815
})
1916
);
2017
} else {
21-
logger.error(error);
18+
logger.error(JSON.stringify(error));
2219
res
2320
.status(500)
2421
.send(ApiError.format({ code: 500, message: 'Something went wrong!' }));
2522
}
2623
}
2724

28-
private handleClientErrors(
29-
error: mongoose.Error.ValidationError
30-
): { code: number; error: string } {
25+
private handleClientErrors(error: mongoose.Error.ValidationError): {
26+
code: number;
27+
error: string;
28+
} {
3129
const duplicatedKindErrors = Object.values(error.errors).filter(
32-
(err) => err.kind === CUSTOM_VALIDATION.DUPLICATED
30+
(err) =>
31+
err.name === 'ValidatorError' &&
32+
err.kind === CUSTOM_VALIDATION.DUPLICATED
3333
);
3434
if (duplicatedKindErrors.length) {
3535
return { code: 409, error: error.message };

src/database.ts

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,10 @@
11
import config, { IConfig } from 'config';
2-
import mongoose, { Mongoose } from 'mongoose';
2+
import { connect as mongooseConnect, connection } from 'mongoose';
33

44
const dbConfig: IConfig = config.get('App.database');
55

6-
export const connect = async (): Promise<Mongoose> =>
7-
await mongoose.connect(dbConfig.get('mongoUrl'), {
8-
useCreateIndex: true,
9-
useNewUrlParser: true,
10-
useUnifiedTopology: true,
11-
});
6+
export const connect = async (): Promise<void> => {
7+
await mongooseConnect(dbConfig.get('mongoUrl'));
8+
};
129

13-
export const close = (): Promise<void> => mongoose.connection.close();
10+
export const close = (): Promise<void> => connection.close();

src/middlewares/auth.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,10 @@ export function authMiddleware(
1212
req.context = { userId: claims.sub };
1313
next();
1414
} catch (err) {
15-
res.status?.(401).send({ code: 401, error: err.message });
15+
if (err instanceof Error) {
16+
res.status?.(401).send({ code: 401, error: err.message });
17+
} else {
18+
res.status?.(401).send({ code: 401, error: 'Unknown auth error' });
19+
}
1620
}
1721
}

src/models/user.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ const schema = new mongoose.Schema(
2121
email: {
2222
type: String,
2323
required: true,
24-
unique: [true, 'Email must be unique'],
2524
},
2625
password: { type: String, required: true },
2726
},

0 commit comments

Comments
 (0)