Skip to content

Commit 023f8fe

Browse files
author
Shogun
committed
feat: Improve types, only support Node LTS, replaced jest with tap.
1 parent 4afce95 commit 023f8fe

22 files changed

+378
-4281
lines changed

.eslintrc.json

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"parser": "@typescript-eslint/parser",
3+
"parserOptions": {
4+
"project": "tsconfig.test.json"
5+
},
6+
"extends": ["@cowtech/eslint-config/typescript"]
7+
}

lib/handlers.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ function handleErrors(error, request, reply) {
8888
// Send the error back
8989
reply
9090
.code(statusCode)
91-
.headers(headers || {})
91+
.headers(headers !== null && headers !== void 0 ? headers : {})
9292
.type('application/json')
9393
.send(body);
9494
}

lib/index.js

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,9 @@ exports.validationMessagesFormatters = validation_2.validationMessagesFormatters
2121
exports.plugin = fastify_plugin_1.default(function (instance, options, done) {
2222
var _a, _b, _c;
2323
const isProduction = process.env.NODE_ENV === 'production';
24-
const hideUnhandledErrors = (_a = options.hideUnhandledErrors, (_a !== null && _a !== void 0 ? _a : isProduction));
25-
const convertValidationErrors = (_b = options.convertValidationErrors, (_b !== null && _b !== void 0 ? _b : true));
26-
const convertResponsesValidationErrors = (_c = options.convertResponsesValidationErrors, (_c !== null && _c !== void 0 ? _c : !isProduction));
24+
const hideUnhandledErrors = (_a = options.hideUnhandledErrors) !== null && _a !== void 0 ? _a : isProduction;
25+
const convertValidationErrors = (_b = options.convertValidationErrors) !== null && _b !== void 0 ? _b : true;
26+
const convertResponsesValidationErrors = (_c = options.convertResponsesValidationErrors) !== null && _c !== void 0 ? _c : !isProduction;
2727
instance.decorateRequest('errorProperties', { hideUnhandledErrors, convertValidationErrors });
2828
instance.setErrorHandler(handlers_1.handleErrors);
2929
instance.setNotFoundHandler(handlers_1.handleNotFoundError);
@@ -40,5 +40,6 @@ exports.plugin = fastify_plugin_1.default(function (instance, options, done) {
4040
}
4141
done();
4242
}, { name: 'fastify-errors-properties' });
43+
exports.default = exports.plugin;
4344
module.exports = exports.plugin;
4445
Object.assign(module.exports, exports);

lib/properties.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,10 @@ function addAdditionalProperties(target, source) {
1111
}
1212
exports.addAdditionalProperties = addAdditionalProperties;
1313
function serializeError(error) {
14+
var _a, _b;
1415
const serialized = {
15-
message: `[${error.code || error.name}] ${error.message}`,
16-
stack: (error.stack || '')
16+
message: `[${(_a = error.code) !== null && _a !== void 0 ? _a : error.name}] ${error.message}`,
17+
stack: ((_b = error.stack) !== null && _b !== void 0 ? _b : '')
1718
.split('\n')
1819
.slice(1)
1920
.map((s) => s

lib/utils.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ function upperFirst(source) {
99
}
1010
exports.upperFirst = upperFirst;
1111
function get(target, path) {
12+
var _a;
1213
const tokens = path.split('.').map((t) => t.trim());
1314
for (const token of tokens) {
1415
if (typeof target === 'undefined' || target === null) {
@@ -18,7 +19,7 @@ function get(target, path) {
1819
}
1920
const index = token.match(/^(\d+)|(?:\[(\d+)\])$/);
2021
if (index) {
21-
target = target[parseInt(index[1] || index[2], 10)];
22+
target = target[parseInt((_a = index[1]) !== null && _a !== void 0 ? _a : index[2], 10)];
2223
}
2324
else {
2425
target = target[token];

lib/validation.js

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ exports.validationMessagesFormatters = {
6464
return max === 0 ? 'must be a empty array' : `must be an array with at most ${max} items`;
6565
},
6666
enum: (values) => `must be one of the following values: ${niceJoin(values.map((f) => `"${f}"`), ' or ')}`,
67-
pattern: (pattern) => `must match pattern "${pattern.replace(/\(\?\:/g, '(')}"`,
67+
pattern: (pattern) => `must match pattern "${pattern.replace(/\(\?:/g, '(')}"`,
6868
invalidResponseCode: (code) => `This endpoint cannot respond with HTTP status ${code}.`,
6969
invalidResponse: (code) => `The response returned from the endpoint violates its specification for the HTTP status ${code}.`,
7070
invalidFormat: (format) => `must match format "${format}" (format)`
@@ -77,6 +77,9 @@ function convertValidationErrors(section, data, validationErrors) {
7777
// For each error
7878
for (const e of validationErrors) {
7979
let message = '';
80+
let pattern;
81+
let value;
82+
let reason;
8083
// Normalize the key
8184
let key = e.dataPath;
8285
if (key.startsWith('.')) {
@@ -121,8 +124,8 @@ function convertValidationErrors(section, data, validationErrors) {
121124
message = exports.validationMessagesFormatters.enum(e.params.allowedValues);
122125
break;
123126
case 'pattern':
124-
const pattern = e.params.pattern;
125-
const value = utils_1.get(data, key);
127+
pattern = e.params.pattern;
128+
value = utils_1.get(data, key);
126129
if (pattern === '.+' && !value) {
127130
message = exports.validationMessagesFormatters.presentString();
128131
}
@@ -131,7 +134,7 @@ function convertValidationErrors(section, data, validationErrors) {
131134
}
132135
break;
133136
case 'format':
134-
let reason = e.params.format;
137+
reason = e.params.format;
135138
// Normalize the key
136139
if (reason === 'date-time') {
137140
reason = 'timestamp';
@@ -140,15 +143,15 @@ function convertValidationErrors(section, data, validationErrors) {
140143
break;
141144
}
142145
// No custom message was found, default to input one replacing the starting verb and adding some path info
143-
if (!message) {
146+
if (!message.length) {
144147
message = `${e.message.replace(/^should/, 'must')} (${e.keyword})`;
145148
}
146149
// Find the property to add
147150
let property = key
148151
.replace(/\[(\d+)\]/g, '.$1') // Array path
149152
.replace(/\[([^\]]+)\]/g, '.$1'); // Object path
150153
// Remove useless quotes
151-
if (property.match(/(?:^['"])(?:[^\.]+)(?:['"]$)/)) {
154+
if (property.match(/(?:^['"])(?:[^.]+)(?:['"]$)/)) {
152155
property = property.substring(1, property.length - 1);
153156
}
154157
// Fix empty properties

package.json

Lines changed: 13 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -25,37 +25,32 @@
2525
"typings": "types/index.d.ts",
2626
"types": "types/index.d.ts",
2727
"scripts": {
28-
"lint": "tslint --project tsconfig.test.json -t stylish src/*.ts test/*.ts",
29-
"test": "jest test --verbose --coverage --coverageReporters=html --coverageReporters=text",
30-
"ci": "yarn lint && jest --coverage --coverageThreshold='{\"global\":{\"branches\":90,\"functions\":90,\"lines\":90,\"statements\":90}}' --ci --coverageReporters=json",
28+
"lint": "eslint src/*.ts test/*.ts",
29+
"test": "tap --reporter=spec --coverage-report=html --coverage-report=text --no-browser test/*.test.ts",
30+
"ci": "yarn lint && tap --no-color --reporter=spec --coverage-report=json --coverage-report=text --branches 90 --functions 90 --lines 90 --statements 90 test/*.test.ts",
3131
"prebuild": "rm -rf lib/* types/* && yarn lint",
3232
"build": "tsc -p .",
3333
"prepublishOnly": "yarn ci",
3434
"postpublish": "git push origin && git push origin -f --tags"
3535
},
3636
"dependencies": {
37-
"ajv": "^6.10.2",
38-
"fastify-plugin": "^1.6.0",
37+
"ajv": "^6.12.0",
38+
"fastify-plugin": "^1.6.1",
3939
"http-errors": "^1.7.3",
4040
"http-status-codes": "^1.4.0",
4141
"statuses": "^1.5.0"
4242
},
4343
"devDependencies": {
44-
"@cowtech/tslint-config": "^5.13.0",
45-
"@types/http-errors": "^1.6.2",
46-
"@types/jest": "^24.0.23",
47-
"@types/node": "^12.12.8",
44+
"@cowtech/eslint-config": "^6.8.4",
45+
"@types/http-errors": "^1.6.3",
46+
"@types/node": "^13.9.0",
4847
"@types/statuses": "^1.5.0",
49-
"fastify": "^2.10.0",
50-
"jest": "^24.9.0",
51-
"jest-additional-expectations": "^0.1.0",
48+
"fastify": "^2.12.1",
5249
"prettier": "^1.19.1",
53-
"ts-jest": "^24.1.0",
54-
"tslint": "^5.20.1",
55-
"typescript": "^3.7.2"
50+
"tap": "^14.10.6",
51+
"typescript": "^3.8.3"
5652
},
57-
"jest": {
58-
"preset": "ts-jest",
59-
"watchman": false
53+
"engines": {
54+
"node": ">=12.15.0"
6055
}
6156
}

src/handlers.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ export function handleErrors(
8282
// Send the error back
8383
reply
8484
.code(statusCode)
85-
.headers(headers || {})
85+
.headers(headers ?? {})
8686
.type('application/json')
8787
.send(body)
8888
}

src/index.ts

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
import Ajv from 'ajv'
22
import { FastifyInstance, RegisterOptions } from 'fastify'
33
import fastifyPlugin from 'fastify-plugin'
4-
import { IncomingMessage, Server, ServerResponse } from 'http'
4+
import { IncomingMessage, Server as HttpServer, ServerResponse } from 'http'
5+
import { Http2Server, Http2ServerRequest, Http2ServerResponse } from 'http2'
6+
import { Server as HttpsServer } from 'https'
57
import { handleErrors, handleNotFoundError } from './handlers'
68
import { addResponseValidation } from './validation'
79

@@ -10,10 +12,26 @@ export * from './interfaces'
1012
export { addAdditionalProperties, serializeError } from './properties'
1113
export { convertValidationErrors, niceJoin, validationMessagesFormatters } from './validation'
1214

15+
export interface Options<
16+
S extends HttpServer | HttpsServer | Http2Server = HttpServer,
17+
I extends IncomingMessage | Http2ServerRequest = IncomingMessage,
18+
R extends ServerResponse | Http2ServerResponse = ServerResponse
19+
> extends RegisterOptions<S, I, R> {
20+
hideUnhandledErrors?: boolean
21+
convertValidationErrors?: boolean
22+
convertResponsesValidationErrors?: boolean
23+
}
24+
25+
export type Plugin<
26+
S extends HttpServer | HttpsServer | Http2Server = HttpServer,
27+
I extends IncomingMessage | Http2ServerRequest = IncomingMessage,
28+
R extends ServerResponse | Http2ServerResponse = ServerResponse
29+
> = (fastify: FastifyInstance<S, I, R>, options: Options<S, I, R>) => void
30+
1331
export const plugin = fastifyPlugin(
14-
function<S = Server, I = IncomingMessage, R = ServerResponse>(
15-
instance: FastifyInstance,
16-
options: RegisterOptions<S, I, R>,
32+
function(
33+
instance: FastifyInstance<HttpServer, IncomingMessage, ServerResponse>,
34+
options: Options<HttpServer, IncomingMessage, ServerResponse>,
1735
done: () => void
1836
): void {
1937
const isProduction = process.env.NODE_ENV === 'production'
@@ -46,5 +64,6 @@ export const plugin = fastifyPlugin(
4664
{ name: 'fastify-errors-properties' }
4765
)
4866

67+
export default plugin as Plugin
4968
module.exports = plugin
5069
Object.assign(module.exports, exports)

src/interfaces.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,10 @@ import { Ajv, ValidateFunction } from 'ajv'
22
import { FastifyInstance, FastifyReply, FastifyRequest } from 'fastify'
33
import { ServerResponse } from 'http'
44

5-
export type GenericObject = { [key: string]: any }
5+
export interface GenericObject {
6+
[key: string]: any
7+
}
8+
69
export type NodeError = NodeJS.ErrnoException
710

811
export type RequestSection = 'params' | 'query' | 'querystring' | 'headers' | 'body' | 'response'

0 commit comments

Comments
 (0)