Skip to content

Commit 015beb2

Browse files
committed
chore: Updated dependencies and toolchain.
1 parent 70bb13f commit 015beb2

File tree

11 files changed

+100
-70
lines changed

11 files changed

+100
-70
lines changed

.github/workflows/ci.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ jobs:
2121
with:
2222
version: latest
2323
- name: Install dependencies
24-
run: pnpm install
24+
run: pnpm install --shamefully-hoist
2525
- name: Run Tests
2626
run: pnpm run ci
2727
- name: Upload coverage to Codecov

package.json

Lines changed: 24 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -27,38 +27,42 @@
2727
"types": "./dist/index.d.ts",
2828
"scripts": {
2929
"dev": "swc --delete-dir-on-start -s -w -d dist src",
30-
"prebuild": "rm -rf dist && npm run lint",
31-
"build": "swc -d dist src",
32-
"postbuild": "tsc -p . --emitDeclarationOnly",
30+
"build": "swc --delete-dir-on-start -d dist src",
31+
"postbuild": "concurrently npm:lint npm:typecheck",
3332
"format": "prettier -w src test",
34-
"lint": "eslint src test",
35-
"test": "c8 -c test/config/c8-local.json tap --rcfile=test/config/tap.yml test/*.test.ts",
36-
"test:ci": "c8 -c test/config/c8-ci.json tap --rcfile=test/config/tap.yml --no-color test/*.test.ts",
33+
"lint": "eslint --cache --ext .js,.jsx,.ts,.tsx src test",
34+
"typecheck": "tsc -p . --emitDeclarationOnly",
35+
"test": "c8 -c test/config/c8-local.json tap test/*.test.ts",
36+
"test:ci": "c8 -c test/config/c8-ci.json tap --no-color test/*.test.ts",
3737
"ci": "npm run build && npm run test:ci",
3838
"prepublishOnly": "npm run ci",
3939
"postpublish": "git push origin && git push origin -f --tags"
4040
},
4141
"dependencies": {
42-
"ajv": "^8.11.2",
43-
"fastify-plugin": "^4.3.0",
44-
"http-errors-enhanced": "^1.0.13"
42+
"ajv": "^8.12.0",
43+
"fastify-plugin": "^4.5.1",
44+
"http-errors-enhanced": "^1.1.2"
4545
},
4646
"devDependencies": {
47-
"@cowtech/eslint-config": "^8.8.0",
48-
"@swc/cli": "^0.1.57",
49-
"@swc/core": "^1.3.19",
50-
"@types/node": "^18.11.9",
51-
"@types/tap": "^15.0.7",
47+
"@cowtech/eslint-config": "^8.10.0",
48+
"@swc/cli": "^0.1.62",
49+
"@swc/core": "^1.3.94",
50+
"@types/node": "^20.8.7",
51+
"@types/tap": "^15.0.10",
5252
"ajv-formats": "^2.1.1",
53-
"c8": "^7.12.0",
53+
"c8": "^8.0.1",
5454
"chokidar": "^3.5.3",
55-
"fastify": "^4.10.2",
56-
"prettier": "^2.8.0",
57-
"tap": "^16.3.2",
55+
"concurrently": "^8.2.2",
56+
"fastify": "^4.24.3",
57+
"prettier": "^3.0.3",
58+
"tap": "^18.5.2",
5859
"ts-node": "^10.9.1",
59-
"typescript": "^4.9.3"
60+
"typescript": "^5.2.2"
6061
},
6162
"engines": {
62-
"node": ">=14.15.0"
63+
"node": ">= 18.18.0"
64+
},
65+
"tap": {
66+
"extends": "./test/config/tap.yml"
6367
}
6468
}

src/handlers.ts

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,24 @@
1-
import { FastifyError, FastifyReply, FastifyRequest } from 'fastify'
1+
import { type FastifyError, type FastifyReply, type FastifyRequest } from 'fastify'
22
import {
33
BadRequestError,
4-
HttpError,
54
INTERNAL_SERVER_ERROR,
65
InternalServerError,
76
NotFoundError,
87
UnprocessableEntityError,
98
UnsupportedMediaTypeError,
109
addAdditionalProperties,
1110
messagesByCodes,
12-
serializeError
11+
serializeError,
12+
type HttpError
1313
} from 'http-errors-enhanced'
14-
import { GenericObject, NodeError, RequestSection, kHttpErrorsEnhancedConfiguration } from './interfaces.js'
14+
import {
15+
kHttpErrorsEnhancedConfiguration,
16+
type GenericObject,
17+
type NodeError,
18+
type RequestSection
19+
} from './interfaces.js'
1520
import { upperFirst } from './utils.js'
16-
import { ValidationResult, convertValidationErrors, validationMessagesFormatters } from './validation.js'
21+
import { convertValidationErrors, validationMessagesFormatters, type ValidationResult } from './validation.js'
1722

1823
export function handleNotFoundError(request: FastifyRequest, reply: FastifyReply): void {
1924
handleErrors(new NotFoundError('Not found.'), request, reply)
@@ -65,7 +70,12 @@ export function handleErrors(error: FastifyError | Error, request: FastifyReques
6570
error = new UnsupportedMediaTypeError(upperFirst(validationMessagesFormatters.contentType()))
6671
} else if (code === 'FST_ERR_CTP_EMPTY_JSON_BODY') {
6772
error = new BadRequestError(upperFirst(validationMessagesFormatters.jsonEmpty()))
68-
} else if (code === 'MALFORMED_JSON' || error.message === 'Invalid JSON' || error.stack!.includes('at JSON.parse')) {
73+
} else if (
74+
code === 'MALFORMED_JSON' ||
75+
error.name === 'SyntaxError' ||
76+
error.message === 'Invalid JSON' ||
77+
error.stack!.includes('at JSON.parse')
78+
) {
6979
error = new BadRequestError(upperFirst(validationMessagesFormatters.json()))
7080
}
7181

src/index.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
import { FastifyError, FastifyInstance, FastifyPluginOptions } from 'fastify'
1+
import { type FastifyError, type FastifyInstance, type FastifyPluginOptions } from 'fastify'
22
import fastifyPlugin from 'fastify-plugin'
33
import { handleErrors, handleNotFoundError } from './handlers.js'
44
import {
5-
Configuration,
5+
type Configuration,
66
kHttpErrorsEnhancedConfiguration,
77
kHttpErrorsEnhancedResponseValidations
88
} from './interfaces.js'

src/interfaces.ts

Lines changed: 6 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1-
import Ajv, { ValidateFunction } from 'ajv'
2-
import { FastifyError } from 'fastify'
1+
import { type ValidateFunction } from 'ajv'
2+
import type Ajv from 'ajv'
3+
import { type FastifyError } from 'fastify'
34

45
export const kHttpErrorsEnhancedConfiguration = Symbol('fastify-http-errors-enhanced-configuration')
56
export const kHttpErrorsEnhancedResponseValidations = Symbol('fastify-http-errors-enhanced-response-validation')
@@ -23,22 +24,14 @@ declare module 'fastify' {
2324
}
2425
}
2526

26-
export interface GenericObject {
27-
[key: string]: any
28-
}
27+
export type GenericObject = Record<string, any>
2928

3029
export type NodeError = NodeJS.ErrnoException
3130

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

34-
export interface ResponseSchemas {
35-
[key: string]: ValidateFunction
36-
}
33+
export type ResponseSchemas = Record<string, ValidateFunction>
3734

38-
export interface Validations {
39-
[key: string]: {
40-
[key: string]: string
41-
}
42-
}
35+
export type Validations = Record<string, Record<string, string>>
4336

4437
export type ValidationFormatter = (...args: any[]) => string

src/validation.ts

Lines changed: 28 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,24 @@
11
import Ajv from 'ajv'
2-
import * as fastify from 'fastify'
3-
import { FastifyInstance, FastifyReply, FastifyRequest, RouteOptions } from 'fastify'
4-
import { InternalServerError, INTERNAL_SERVER_ERROR } from 'http-errors-enhanced'
52
import {
6-
Configuration,
3+
type FastifyInstance,
4+
type FastifyReply,
5+
type FastifyRequest,
6+
type ValidationResult as FastifyValidationResult,
7+
type RouteOptions
8+
} from 'fastify'
9+
import { INTERNAL_SERVER_ERROR, InternalServerError } from 'http-errors-enhanced'
10+
import {
711
kHttpErrorsEnhancedConfiguration,
812
kHttpErrorsEnhancedResponseValidations,
9-
RequestSection,
10-
ResponseSchemas,
11-
ValidationFormatter,
12-
Validations
13+
type Configuration,
14+
type RequestSection,
15+
type ResponseSchemas,
16+
type ValidationFormatter,
17+
type Validations
1318
} from './interfaces.js'
1419
import { get } from './utils.js'
1520

16-
export interface ValidationResult extends fastify.ValidationResult {
21+
export interface ValidationResult extends FastifyValidationResult {
1722
dataPath: any
1823
instancePath: string
1924
}
@@ -31,7 +36,7 @@ export function niceJoin(array: string[], lastSeparator: string = ' and ', separ
3136
}
3237
}
3338

34-
export const validationMessagesFormatters: { [key: string]: ValidationFormatter } = {
39+
export const validationMessagesFormatters: Record<string, ValidationFormatter> = {
3540
contentType: () =>
3641
'only JSON payloads are accepted. Please set the "Content-Type" header to start with "application/json"',
3742
json: () => 'the body payload is not a valid JSON',
@@ -91,10 +96,10 @@ export const validationMessagesFormatters: { [key: string]: ValidationFormatter
9196

9297
export function convertValidationErrors(
9398
section: RequestSection,
94-
data: { [key: string]: unknown },
99+
data: Record<string, unknown>,
95100
validationErrors: ValidationResult[]
96101
): Validations {
97-
const errors: { [key: string]: string } = {}
102+
const errors: Record<string, string> = {}
98103

99104
if (section === 'querystring') {
100105
section = 'query'
@@ -217,7 +222,7 @@ export function addResponseValidation(this: FastifyInstance, route: RouteOptions
217222
this[kHttpErrorsEnhancedResponseValidations].push([
218223
this,
219224
validators,
220-
Object.entries(route.schema.response as { [key: string]: object })
225+
Object.entries(route.schema.response as Record<string, object>)
221226
])
222227

223228
// Note that this hook is not called for non JSON payloads therefore validation is not possible in such cases
@@ -232,29 +237,33 @@ export function addResponseValidation(this: FastifyInstance, route: RouteOptions
232237

233238
// Never validate error 500
234239
if (statusCode === INTERNAL_SERVER_ERROR) {
235-
return done(null, payload)
240+
done(null, payload)
241+
return
236242
}
237243

238244
// No validator, it means the HTTP status is not allowed
239245
const validator = validators[statusCode]
240246

241247
if (!validator) {
242248
if (request[kHttpErrorsEnhancedConfiguration]!.allowUndeclaredResponses) {
243-
return done(null, payload)
249+
done(null, payload)
250+
return
244251
}
245252

246-
return done(new InternalServerError(validationMessagesFormatters.invalidResponseCode(statusCode)))
253+
done(new InternalServerError(validationMessagesFormatters.invalidResponseCode(statusCode)))
254+
return
247255
}
248256

249257
// Now validate the payload
250258
const valid = validator(payload)
251259

252260
if (!valid) {
253-
return done(
261+
done(
254262
new InternalServerError(validationMessagesFormatters.invalidResponse(statusCode), {
255263
failedValidations: convertValidationErrors('response', payload, validator.errors as ValidationResult[])
256264
})
257265
)
266+
return
258267
}
259268

260269
done(null, payload)
@@ -263,7 +272,7 @@ export function addResponseValidation(this: FastifyInstance, route: RouteOptions
263272

264273
export function compileResponseValidationSchema(this: FastifyInstance, configuration: Configuration): void {
265274
// Fix CJS/ESM interoperability
266-
// @ts-expect-error
275+
// @ts-expect-error Fix types
267276
let AjvConstructor = Ajv as Ajv & { default?: Ajv }
268277

269278
if (AjvConstructor.default) {
@@ -273,7 +282,7 @@ export function compileResponseValidationSchema(this: FastifyInstance, configura
273282
const hasCustomizer = typeof configuration.responseValidatorCustomizer === 'function'
274283

275284
for (const [instance, validators, schemas] of this[kHttpErrorsEnhancedResponseValidations]) {
276-
// @ts-expect-error
285+
// @ts-expect-error Fix types
277286
const compiler = new AjvConstructor({
278287
// The fastify defaults, with the exception of removeAdditional and coerceTypes, which have been reversed
279288
removeAdditional: false,

test/config/tap.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
---
22
jobs: 5
33
timeout: 60
4-
reporter: spec
5-
coverage: false
4+
disable-coverage: true
5+
allow-empty-coverage: true
66
node-arg:
77
- --loader=ts-node/esm

test/hooks.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/* eslint-disable @typescript-eslint/no-floating-promises */
22

3-
import fastify, { FastifyError, FastifyInstance, FastifyPluginOptions } from 'fastify'
3+
import fastify, { type FastifyError, type FastifyInstance, type FastifyPluginOptions } from 'fastify'
44
import { INTERNAL_SERVER_ERROR } from 'http-errors-enhanced'
55
import t from 'tap'
66
import { plugin as fastifyHttpErrorsEnhanced } from '../src/index.js'

test/index.test.ts

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
/* eslint-disable @typescript-eslint/no-floating-promises */
22

3-
import fastify, { FastifyInstance, FastifyPluginOptions, FastifyReply, FastifyRequest } from 'fastify'
3+
import fastify, {
4+
type FastifyInstance,
5+
type FastifyPluginOptions,
6+
type FastifyReply,
7+
type FastifyRequest
8+
} from 'fastify'
49
import {
510
BAD_GATEWAY,
611
BAD_REQUEST,
@@ -560,7 +565,8 @@ t.test('Plugin', t => {
560565

561566
t.same(payload, {
562567
error: 'Internal Server Error',
563-
message: '[Error] params/id must be number',
568+
message: '[FST_ERR_VALIDATION] params/id must be number',
569+
code: 'FST_ERR_VALIDATION',
564570
statusCode: INTERNAL_SERVER_ERROR,
565571
validation: [
566572
{
@@ -631,7 +637,8 @@ t.test('Plugin', t => {
631637

632638
t.same(payload, {
633639
error: 'Internal Server Error',
634-
message: '[Error] params/id must be number',
640+
message: '[FST_ERR_VALIDATION] params/id must be number',
641+
code: 'FST_ERR_VALIDATION',
635642
statusCode: INTERNAL_SERVER_ERROR,
636643
validation: [
637644
{

test/validation.test.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,16 @@
22

33
import Ajv from 'ajv'
44
import addFormats from 'ajv-formats'
5-
import fastify, { FastifyInstance, FastifyPluginOptions, FastifyReply, FastifyRequest } from 'fastify'
5+
import fastify, {
6+
type FastifyInstance,
7+
type FastifyPluginOptions,
8+
type FastifyReply,
9+
type FastifyRequest
10+
} from 'fastify'
611
import { ACCEPTED, INTERNAL_SERVER_ERROR, OK } from 'http-errors-enhanced'
712
import t from 'tap'
813
import { convertValidationErrors, niceJoin, plugin as fastifyErrorProperties } from '../src/index.js'
9-
import { ValidationResult } from '../src/validation.js'
14+
import { type ValidationResult } from '../src/validation.js'
1015

1116
async function buildServer(options: FastifyPluginOptions = {}): Promise<FastifyInstance> {
1217
const server = fastify()

tsconfig.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,5 +17,7 @@
1717
"strictNullChecks": true,
1818
"useUnknownInCatchVariables": false
1919
},
20-
"include": ["src/*.ts"]
20+
"include": [
21+
"src/*.ts"
22+
]
2123
}

0 commit comments

Comments
 (0)