@fastify/compress 8.3.0 → 9.0.0

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.
@@ -27,7 +27,7 @@ jobs:
27
27
  permissions:
28
28
  contents: write
29
29
  pull-requests: write
30
- uses: fastify/workflows/.github/workflows/plugins-ci.yml@v5
30
+ uses: fastify/workflows/.github/workflows/plugins-ci.yml@v6
31
31
  with:
32
32
  license-check: true
33
33
  lint: true
@@ -0,0 +1,19 @@
1
+ name: Lock Threads
2
+
3
+ on:
4
+ schedule:
5
+ - cron: '0 0 1 * *'
6
+ workflow_dispatch:
7
+
8
+ concurrency:
9
+ group: lock
10
+
11
+ permissions:
12
+ contents: read
13
+
14
+ jobs:
15
+ lock-threads:
16
+ permissions:
17
+ issues: write
18
+ pull-requests: write
19
+ uses: fastify/workflows/.github/workflows/lock-threads.yml@v6
package/LICENSE CHANGED
@@ -1,8 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2017-present The Fastify team
4
-
5
- The Fastify team members are listed at https://github.com/fastify/fastify#team.
3
+ Copyright (c) 2017-present The Fastify team <https://github.com/fastify/fastify#team>
6
4
 
7
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
8
6
  of this software and associated documentation files (the "Software"), to deal
package/index.js CHANGED
@@ -2,14 +2,13 @@
2
2
 
3
3
  const zlib = require('node:zlib')
4
4
  const { inherits, format } = require('node:util')
5
+ const { pipeline, compose } = require('node:stream')
5
6
 
6
7
  const fp = require('fastify-plugin')
7
8
  const encodingNegotiator = require('@fastify/accept-negotiator')
8
- const pump = require('pump')
9
9
  const mimedb = require('mime-db')
10
10
  const peek = require('peek-stream')
11
11
  const { Minipass } = require('minipass')
12
- const pumpify = require('pumpify')
13
12
  const { Readable } = require('readable-stream')
14
13
 
15
14
  const { isStream, isGzip, isDeflate, intoAsyncIterator, isWebReadableStream, isFetchResponse, webStreamToNodeReadable } = require('./lib/utils')
@@ -50,11 +49,6 @@ function fastifyCompress (fastify, opts, next) {
50
49
 
51
50
  // add onSend hook onto each route as needed
52
51
  fastify.addHook('onRoute', (routeOptions) => {
53
- // If route config.compress has been set it takes precedence over compress
54
- if (routeOptions.config?.compress !== undefined) {
55
- routeOptions.compress = routeOptions.config.compress
56
- }
57
-
58
52
  // Manage compression options
59
53
  if (routeOptions.compress !== undefined) {
60
54
  if (typeof routeOptions.compress === 'object') {
@@ -79,11 +73,6 @@ function fastifyCompress (fastify, opts, next) {
79
73
  buildRouteCompress(fastify, globalCompressParams, routeOptions, true)
80
74
  }
81
75
 
82
- // If route config.decompress has been set it takes precedence over compress
83
- if (routeOptions.config?.decompress !== undefined) {
84
- routeOptions.decompress = routeOptions.config.decompress
85
- }
86
-
87
76
  // Manage decompression options
88
77
  if (routeOptions.decompress !== undefined) {
89
78
  if (typeof routeOptions.decompress === 'object') {
@@ -289,7 +278,7 @@ function buildRouteCompress (_fastify, params, routeOptions, decorateOnly) {
289
278
  encoding === undefined
290
279
  ? reply.removeHeader('Content-Encoding')
291
280
  : reply.header('Content-Encoding', 'identity')
292
- pump(stream, payload = unzipStream(params.uncompressStream), onEnd.bind(reply))
281
+ pipeline(stream, payload = unzipStream(params.uncompressStream), onEnd.bind(reply))
293
282
  }
294
283
  return next(null, payload)
295
284
  }
@@ -316,7 +305,7 @@ function buildRouteCompress (_fastify, params, routeOptions, decorateOnly) {
316
305
  }
317
306
 
318
307
  stream = zipStream(params.compressStream, encoding)
319
- pump(payload, stream, onEnd.bind(reply))
308
+ pipeline(payload, stream, onEnd.bind(reply))
320
309
  next(null, stream)
321
310
  }
322
311
  }
@@ -378,7 +367,10 @@ function buildRouteDecompress (_fastify, params, routeOptions) {
378
367
  raw.on('data', trackEncodedLength.bind(decompresser))
379
368
  raw.on('end', removeEncodedLengthTracking)
380
369
 
381
- next(null, pump(raw, decompresser))
370
+ pipeline(raw, decompresser, () => {
371
+ // Cleanup callback - decompression errors are handled by decompresser's error handler
372
+ })
373
+ next(null, decompresser)
382
374
  }
383
375
  }
384
376
 
@@ -415,7 +407,7 @@ function compress (params) {
415
407
  encoding === undefined
416
408
  ? this.removeHeader('Content-Encoding')
417
409
  : this.header('Content-Encoding', 'identity')
418
- pump(stream, payload = unzipStream(params.uncompressStream), onEnd.bind(this))
410
+ pipeline(stream, payload = unzipStream(params.uncompressStream), onEnd.bind(this))
419
411
  }
420
412
  return this.send(payload)
421
413
  }
@@ -446,8 +438,8 @@ function compress (params) {
446
438
  }
447
439
 
448
440
  stream = zipStream(params.compressStream, encoding)
449
- pump(payload, stream, onEnd.bind(this))
450
- this.send(stream)
441
+ pipeline(payload, stream, onEnd.bind(this))
442
+ return this.send(stream)
451
443
  }
452
444
  }
453
445
 
@@ -464,7 +456,13 @@ function setVaryHeader (reply) {
464
456
  }
465
457
 
466
458
  function onEnd (err) {
467
- if (err) this.log.error(err)
459
+ // Client disconnection during streaming is expected and handled by Fastify.
460
+ // Do not log "premature close" errors at error level since they are not
461
+ // actual errors - they occur when clients disconnect mid-response.
462
+ // See: https://github.com/fastify/fastify-compress/issues/382
463
+ if (err && err.message !== 'premature close') {
464
+ this.log.error(err)
465
+ }
468
466
  }
469
467
 
470
468
  function trackEncodedLength (chunk) {
@@ -565,8 +563,8 @@ function unzipStream (inflate, maxRecursion) {
565
563
  /* c8 ignore next */
566
564
  if (maxRecursion < 0) return swap(new Error('Maximum recursion reached'))
567
565
  switch (isCompressed(data)) {
568
- case 1: return swap(null, pumpify(inflate.gzip(), unzipStream(inflate, maxRecursion - 1)))
569
- case 2: return swap(null, pumpify(inflate.deflate(), unzipStream(inflate, maxRecursion - 1)))
566
+ case 1: return swap(null, compose(inflate.gzip(), unzipStream(inflate, maxRecursion - 1)))
567
+ case 2: return swap(null, compose(inflate.deflate(), unzipStream(inflate, maxRecursion - 1)))
570
568
  }
571
569
  return swap(null, new Minipass())
572
570
  })
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fastify/compress",
3
- "version": "8.3.0",
3
+ "version": "9.0.0",
4
4
  "description": "Fastify compression utils",
5
5
  "main": "index.js",
6
6
  "type": "commonjs",
@@ -11,26 +11,24 @@
11
11
  "mime-db": "^1.52.0",
12
12
  "minipass": "^7.0.4",
13
13
  "peek-stream": "^1.1.3",
14
- "pump": "^3.0.0",
15
- "pumpify": "^2.0.1",
16
14
  "readable-stream": "^4.5.2"
17
15
  },
18
16
  "devDependencies": {
19
- "@types/node": "^24.0.8",
17
+ "@types/node": "^25.0.3",
20
18
  "adm-zip": "^0.5.12",
21
- "c8": "^10.1.2",
19
+ "c8": "^11.0.0",
22
20
  "eslint": "^9.17.0",
23
21
  "fastify": "^5.0.0",
24
22
  "jsonstream": "^1.0.3",
25
- "neostandard": "^0.12.0",
26
- "tsd": "^0.33.0",
27
- "typescript": "~5.9.2"
23
+ "neostandard": "^0.13.0",
24
+ "tstyche": "^7.1.0",
25
+ "typescript": "~6.0.2"
28
26
  },
29
27
  "scripts": {
30
28
  "lint": "eslint",
31
29
  "lint:fix": "eslint --fix",
32
30
  "test": "npm run test:unit && npm run test:typescript",
33
- "test:typescript": "tsd",
31
+ "test:typescript": "tstyche",
34
32
  "test:unit": "node --test",
35
33
  "test:coverage": "c8 node --test && c8 report --reporter=html",
36
34
  "test:unit:verbose": "npm run test:unit -- -Rspec"
@@ -82,9 +80,6 @@
82
80
  "type": "git",
83
81
  "url": "git+https://github.com/fastify/fastify-compress.git"
84
82
  },
85
- "tsd": {
86
- "directory": "types"
87
- },
88
83
  "publishConfig": {
89
84
  "access": "public"
90
85
  }
@@ -2,9 +2,9 @@
2
2
 
3
3
  const { test, describe } = require('node:test')
4
4
  const { createReadStream } = require('node:fs')
5
+ const { pipeline } = require('node:stream')
5
6
  const path = require('node:path')
6
7
  const zlib = require('node:zlib')
7
- const pump = require('pump')
8
8
  const Fastify = require('fastify')
9
9
  const compressPlugin = require('../index')
10
10
 
@@ -12,7 +12,9 @@ function createPayload (compressor) {
12
12
  let payload = createReadStream(path.resolve(__dirname, '../package.json'))
13
13
 
14
14
  if (compressor) {
15
- payload = pump(payload, compressor())
15
+ const compressed = compressor()
16
+ pipeline(payload, compressed, () => {})
17
+ payload = compressed
16
18
  }
17
19
 
18
20
  return payload
@@ -0,0 +1,43 @@
1
+ 'use strict'
2
+
3
+ const { test } = require('node:test')
4
+ const zlib = require('node:zlib')
5
+ const Fastify = require('fastify')
6
+ const fastifyCompress = require('../..')
7
+
8
+ const largeJsonString = JSON.stringify({
9
+ text: 'Lorem ipsum dolor sit amet. '.repeat(2048),
10
+ })
11
+
12
+ async function routes (fastify) {
13
+ fastify.route({
14
+ method: 'GET',
15
+ url: '/api/compress-test',
16
+ handler: async function (_request, reply) {
17
+ reply.type('application/json')
18
+ return reply.compress(largeJsonString)
19
+ }
20
+ })
21
+ }
22
+
23
+ test('should compress large payload without premature close', async (t) => {
24
+ const fastify = Fastify()
25
+ await fastify.register(fastifyCompress, { encodings: ['gzip'], global: true })
26
+ await fastify.register(routes)
27
+
28
+ const response = await fastify.inject({
29
+ url: '/api/compress-test',
30
+ method: 'GET',
31
+ headers: { 'accept-encoding': 'gzip' }
32
+ })
33
+
34
+ t.assert.equal(response.statusCode, 200)
35
+ t.assert.equal(response.headers['content-encoding'], 'gzip')
36
+ t.assert.ok(
37
+ response.rawPayload.length > 0,
38
+ `Expected compressed response body, got ${response.rawPayload.length} bytes`
39
+ )
40
+
41
+ const decompressed = zlib.gunzipSync(response.rawPayload)
42
+ t.assert.equal(decompressed.toString('utf-8'), largeJsonString)
43
+ })
@@ -0,0 +1,193 @@
1
+ 'use strict'
2
+
3
+ const { test } = require('node:test')
4
+ const { setTimeout: sleep } = require('node:timers/promises')
5
+ const net = require('node:net')
6
+ const { Writable } = require('node:stream')
7
+ const Fastify = require('fastify')
8
+ const fastifyCompress = require('../..')
9
+
10
+ test('should not log "premature close" errors on client disconnect (global compression)', async (t) => {
11
+ let prematureCloseCount = 0
12
+
13
+ const fastify = Fastify({
14
+ logger: {
15
+ level: 'error',
16
+ stream: new Writable({
17
+ write (chunk, encoding, callback) {
18
+ if (chunk.toString().includes('premature close')) {
19
+ prematureCloseCount++
20
+ }
21
+ callback()
22
+ }
23
+ })
24
+ }
25
+ })
26
+
27
+ await fastify.register(fastifyCompress, {
28
+ global: true,
29
+ encodings: ['gzip'],
30
+ threshold: 1024
31
+ })
32
+
33
+ // Streaming endpoint that takes time to produce data
34
+ fastify.get('/stream', async (_request, reply) => {
35
+ let chunks = 0
36
+ const stream = new (require('node:stream').Readable)({
37
+ read () {
38
+ if (chunks >= 20) {
39
+ this.push(null)
40
+ return
41
+ }
42
+ setTimeout(() => {
43
+ this.push(JSON.stringify({ id: chunks, data: 'x'.repeat(1000) }) + '\n')
44
+ chunks++
45
+ }, 50)
46
+ }
47
+ })
48
+ reply.type('text/plain')
49
+ return stream
50
+ })
51
+
52
+ await fastify.listen({ port: 0 })
53
+ const port = fastify.server.address().port
54
+
55
+ // Simulate clients that disconnect before the full response is sent
56
+ for (let i = 0; i < 10; i++) {
57
+ await new Promise((_resolve) => {
58
+ const sock = net.connect(port, '127.0.0.1', () => {
59
+ sock.write('GET /stream HTTP/1.1\r\nHost: localhost\r\nAccept-Encoding: gzip\r\n\r\n')
60
+ // Disconnect after receiving partial response (100ms)
61
+ setTimeout(() => {
62
+ sock.destroy()
63
+ _resolve()
64
+ }, 100)
65
+ })
66
+ sock.on('error', () => _resolve())
67
+ })
68
+ }
69
+
70
+ // Allow pending callbacks to fire
71
+ await sleep(2000)
72
+ await fastify.close()
73
+
74
+ t.assert.equal(
75
+ prematureCloseCount,
76
+ 0,
77
+ `Expected no "premature close" errors, but got ${prematureCloseCount} errors from 10 client disconnects`
78
+ )
79
+ })
80
+
81
+ test('should not log "premature close" errors on client disconnect (reply.compress path)', async (t) => {
82
+ let prematureCloseCount = 0
83
+
84
+ const fastify = Fastify({
85
+ logger: {
86
+ level: 'error',
87
+ stream: new Writable({
88
+ write (chunk, encoding, callback) {
89
+ if (chunk.toString().includes('premature close')) {
90
+ prematureCloseCount++
91
+ }
92
+ callback()
93
+ }
94
+ })
95
+ }
96
+ })
97
+
98
+ await fastify.register(fastifyCompress, {
99
+ global: false,
100
+ encodings: ['gzip']
101
+ })
102
+
103
+ // Streaming endpoint using reply.compress
104
+ fastify.get('/stream', async (_request, reply) => {
105
+ let chunks = 0
106
+ const stream = new (require('node:stream').Readable)({
107
+ read () {
108
+ if (chunks >= 20) {
109
+ this.push(null)
110
+ return
111
+ }
112
+ setTimeout(() => {
113
+ this.push(JSON.stringify({ id: chunks, data: 'x'.repeat(1000) }) + '\n')
114
+ chunks++
115
+ }, 50)
116
+ }
117
+ })
118
+ reply.type('text/plain')
119
+ return reply.compress(stream)
120
+ })
121
+
122
+ await fastify.listen({ port: 0 })
123
+ const port = fastify.server.address().port
124
+
125
+ // Simulate clients that disconnect before the full response is sent
126
+ for (let i = 0; i < 10; i++) {
127
+ await new Promise((_resolve) => {
128
+ const sock = net.connect(port, '127.0.0.1', () => {
129
+ sock.write('GET /stream HTTP/1.1\r\nHost: localhost\r\nAccept-Encoding: gzip\r\n\r\n')
130
+ // Disconnect after receiving partial response (100ms)
131
+ setTimeout(() => {
132
+ sock.destroy()
133
+ _resolve()
134
+ }, 100)
135
+ })
136
+ sock.on('error', () => _resolve())
137
+ })
138
+ }
139
+
140
+ // Allow pending callbacks to fire
141
+ await sleep(2000)
142
+ await fastify.close()
143
+
144
+ t.assert.equal(
145
+ prematureCloseCount,
146
+ 0,
147
+ `Expected no "premature close" errors, but got ${prematureCloseCount} errors from 10 client disconnects`
148
+ )
149
+ })
150
+
151
+ test('should still log actual errors (not premature close)', async (t) => {
152
+ const errors = []
153
+
154
+ const fastify = Fastify({
155
+ logger: {
156
+ level: 'error',
157
+ stream: new Writable({
158
+ write (chunk, encoding, callback) {
159
+ const msg = chunk.toString()
160
+ if (msg.includes('premature close')) {
161
+ // Ignore premature close errors
162
+ } else {
163
+ errors.push(msg)
164
+ }
165
+ callback()
166
+ }
167
+ })
168
+ }
169
+ })
170
+
171
+ await fastify.register(fastifyCompress, {
172
+ global: true,
173
+ encodings: ['gzip']
174
+ })
175
+
176
+ // Route that throws an error
177
+ fastify.get('/error', async () => {
178
+ throw new Error('Test error')
179
+ })
180
+
181
+ await fastify.inject({
182
+ method: 'GET',
183
+ url: '/error',
184
+ headers: { 'accept-encoding': 'gzip' }
185
+ })
186
+
187
+ await sleep(500)
188
+
189
+ t.assert.ok(
190
+ errors.length > 0,
191
+ 'Expected actual errors to still be logged'
192
+ )
193
+ })
@@ -330,95 +330,6 @@ describe('When `compress.removeContentLengthHeader` is `false`, it should not re
330
330
  })
331
331
  })
332
332
 
333
- describe('When using the old routes `{ config: compress }` option :', async () => {
334
- test('it should compress data using the route custom provided `createGzip` method', async (t) => {
335
- t.plan(10)
336
- const equal = t.assert.equal
337
-
338
- let usedCustomGlobal = false
339
- let usedCustom = false
340
- const customZlibGlobal = { createGzip: () => (usedCustomGlobal = true) && zlib.createGzip() }
341
- const customZlib = { createGzip: () => (usedCustom = true) && zlib.createGzip() }
342
-
343
- const fastify = Fastify()
344
- await fastify.register(compressPlugin, { global: false, zlib: customZlibGlobal })
345
-
346
- fastify.get('/', (_request, reply) => {
347
- reply
348
- .type('text/plain')
349
- .compress(createReadStream('./package.json'))
350
- })
351
-
352
- fastify.get('/custom', {
353
- config: {
354
- compress: { zlib: customZlib }
355
- }
356
- }, (_request, reply) => {
357
- reply
358
- .type('text/plain')
359
- .compress(createReadStream('./package.json'))
360
- })
361
-
362
- await fastify.inject({
363
- url: '/',
364
- method: 'GET',
365
- headers: {
366
- 'accept-encoding': 'gzip'
367
- }
368
- }).then((response) => {
369
- equal(usedCustom, false)
370
- equal(usedCustomGlobal, true)
371
-
372
- const file = readFileSync('./package.json', 'utf8')
373
- const payload = zlib.gunzipSync(response.rawPayload)
374
- equal(response.headers.vary, 'accept-encoding')
375
- equal(response.headers['content-encoding'], 'gzip')
376
- equal(payload.toString('utf-8'), file)
377
-
378
- usedCustom = false
379
- usedCustomGlobal = false
380
- })
381
-
382
- const response = await fastify.inject({
383
- url: '/custom',
384
- method: 'GET',
385
- headers: {
386
- 'accept-encoding': 'gzip'
387
- }
388
- })
389
- equal(usedCustom, true)
390
- equal(usedCustomGlobal, false)
391
-
392
- const file = readFileSync('./package.json', 'utf8')
393
- const payload = zlib.gunzipSync(response.rawPayload)
394
- equal(response.headers.vary, 'accept-encoding')
395
- equal(response.headers['content-encoding'], 'gzip')
396
- equal(payload.toString('utf-8'), file)
397
- })
398
-
399
- test('it should use the old routes `{ config: compress }` options over routes `compress` options', async (t) => {
400
- t.plan(1)
401
-
402
- const fastify = Fastify()
403
- await fastify.register(compressPlugin, { global: false })
404
-
405
- try {
406
- fastify.get('/', {
407
- compress: {
408
- zlib: { createGzip: () => zlib.createGzip() }
409
- },
410
- config: {
411
- compress: 'bad config'
412
- }
413
- }, (_request, reply) => {
414
- reply.send('')
415
- })
416
- } catch (err) {
417
- t.assert.equal(err.message, 'Unknown value for route compress configuration')
418
- }
419
- })
420
- })
421
-
422
333
  test('It should avoid to trigger `onSend` hook twice', async (t) => {
423
334
  t.plan(1)
424
335
 
@@ -2,9 +2,9 @@
2
2
 
3
3
  const { test, describe } = require('node:test')
4
4
  const { createReadStream } = require('node:fs')
5
+ const { pipeline } = require('node:stream')
5
6
  const path = require('node:path')
6
7
  const zlib = require('node:zlib')
7
- const pump = require('pump')
8
8
  const Fastify = require('fastify')
9
9
  const compressPlugin = require('../index')
10
10
 
@@ -12,7 +12,9 @@ function createPayload (compressor) {
12
12
  let payload = createReadStream(path.resolve(__dirname, '../package.json'))
13
13
 
14
14
  if (compressor) {
15
- payload = pump(payload, compressor())
15
+ const compressed = compressor()
16
+ pipeline(payload, compressed, () => {})
17
+ payload = compressed
16
18
  }
17
19
 
18
20
  return payload
@@ -231,88 +233,3 @@ describe('When using routes `decompress` settings :', async () => {
231
233
  }
232
234
  })
233
235
  })
234
-
235
- describe('When using the old routes `{ config: decompress }` option :', async () => {
236
- test('it should decompress data using the route custom provided `createGunzip` method', async (t) => {
237
- t.plan(8)
238
- const equal = t.assert.equal
239
-
240
- let usedCustomGlobal = false
241
- let usedCustom = false
242
- const customZlibGlobal = { createGunzip: () => (usedCustomGlobal = true) && zlib.createGunzip() }
243
- const customZlib = { createGunzip: () => (usedCustom = true) && zlib.createGunzip() }
244
-
245
- const fastify = Fastify()
246
- await fastify.register(compressPlugin, { zlib: customZlibGlobal })
247
-
248
- fastify.post('/', (request, reply) => {
249
- reply.send(request.body.name)
250
- })
251
-
252
- fastify.post('/custom', {
253
- config: {
254
- decompress: {
255
- zlib: customZlib
256
- }
257
- }
258
- }, (request, reply) => {
259
- reply.send(request.body.name)
260
- })
261
-
262
- await fastify.inject({
263
- url: '/',
264
- method: 'POST',
265
- headers: {
266
- 'content-type': 'application/json',
267
- 'content-encoding': 'gzip'
268
- },
269
- payload: createPayload(zlib.createGzip)
270
- }).then((response) => {
271
- equal(usedCustom, false)
272
- equal(usedCustomGlobal, true)
273
-
274
- equal(response.statusCode, 200)
275
- equal(response.body, '@fastify/compress')
276
-
277
- usedCustom = false
278
- usedCustomGlobal = false
279
- })
280
-
281
- const response = await fastify.inject({
282
- url: '/custom',
283
- method: 'POST',
284
- headers: {
285
- 'content-type': 'application/json',
286
- 'content-encoding': 'gzip'
287
- },
288
- payload: createPayload(zlib.createGzip)
289
- })
290
- equal(usedCustom, true)
291
- equal(usedCustomGlobal, false)
292
-
293
- equal(response.statusCode, 200)
294
- equal(response.body, '@fastify/compress')
295
- })
296
-
297
- test('it should use the old routes `{ config: decompress }` options over routes `decompress` options', async (t) => {
298
- t.plan(1)
299
-
300
- const fastify = Fastify()
301
- await fastify.register(compressPlugin, { global: false })
302
-
303
- try {
304
- fastify.post('/', {
305
- decompress: {
306
- zlib: { createGunzip: () => zlib.createGunzip() }
307
- },
308
- config: {
309
- decompress: 'bad config'
310
- }
311
- }, (request, reply) => {
312
- reply.send(request.body.name)
313
- })
314
- } catch (err) {
315
- t.assert.equal(err.message, 'Unknown value for route decompress configuration')
316
- }
317
- })
318
- })
package/types/index.d.ts CHANGED
@@ -10,13 +10,6 @@ import { Stream } from 'node:stream'
10
10
  import { BrotliOptions, ZlibOptions } from 'node:zlib'
11
11
 
12
12
  declare module 'fastify' {
13
- export interface FastifyContextConfig {
14
- /** @deprecated `config.compress` is deprecated, use `compress` shorthand option instead */
15
- compress?: RouteCompressOptions | false;
16
- /** @deprecated `config.decompress` is deprecated, use `decompress` shorthand option instead */
17
- decompress?: RouteDecompressOptions | false;
18
- }
19
-
20
13
  export interface RouteShorthandOptions<
21
14
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
22
15
  RawServer extends RawServerBase = RawServerDefault
@@ -97,13 +90,6 @@ declare namespace fastifyCompress {
97
90
 
98
91
  export interface RouteOptions extends FastifyRouteOptions, FastifyCompressRouteOptions { }
99
92
 
100
- export interface RoutesConfigCompressOptions {
101
- /** @deprecated `config.compress` is deprecated, use `compress` shorthand option instead */
102
- compress?: RouteCompressOptions | false;
103
- /** @deprecated `config.decompress` is deprecated, use `decompress` shorthand option instead */
104
- decompress?: RouteDecompressOptions | false;
105
- }
106
-
107
93
  export const fastifyCompress: FastifyCompress
108
94
  export { fastifyCompress as default }
109
95
  }
@@ -1,6 +1,6 @@
1
1
  import fastify, { FastifyInstance } from 'fastify'
2
2
  import { createReadStream } from 'node:fs'
3
- import { expectError, expectType } from 'tsd'
3
+ import { expect } from 'tstyche'
4
4
  import * as zlib from 'node:zlib'
5
5
  import fastifyCompress, { FastifyCompressOptions } from '..'
6
6
 
@@ -39,11 +39,11 @@ app.register(fastifyCompress, {
39
39
  })
40
40
 
41
41
  app.get('/test-one', async (_request, reply) => {
42
- expectType<void>(reply.compress(stream))
42
+ expect(reply.compress(stream)).type.toBe<void>()
43
43
  })
44
44
 
45
45
  app.get('/test-two', async (_request, reply) => {
46
- expectError(reply.compress())
46
+ expect(reply.compress).type.not.toBeCallableWith()
47
47
  })
48
48
 
49
49
  // Instantiation of an app without global
@@ -64,7 +64,7 @@ appWithoutGlobal.get('/one', {
64
64
  }
65
65
  }
66
66
  }, (_request, reply) => {
67
- expectType<void>(reply.type('text/plain').compress(stream))
67
+ expect(reply.type('text/plain').compress(stream)).type.toBe<void>()
68
68
  })
69
69
 
70
70
  appWithoutGlobal.get('/two', {
@@ -82,27 +82,27 @@ appWithoutGlobal.get('/two', {
82
82
  }
83
83
  }
84
84
  }, (_request, reply) => {
85
- expectType<void>(reply.type('text/plain').compress(stream))
85
+ expect(reply.type('text/plain').compress(stream)).type.toBe<void>()
86
86
  })
87
87
 
88
- expectError(
89
- appWithoutGlobal.get('/throw-a-ts-arg-error-on-shorthand-route', {
90
- compress: 'bad compress route option value',
91
- decompress: 'bad decompress route option value'
92
- }, (_request, reply) => {
93
- expectType<void>(reply.type('text/plain').compress(stream))
94
- })
95
- )
88
+ appWithoutGlobal.get('/throw-a-ts-arg-error-on-shorthand-route', {
89
+ // @ts-expect-error Type 'string' is not assignable
90
+ compress: 'bad compress route option value',
91
+ // @ts-expect-error Type 'string' is not assignable
92
+ decompress: 'bad decompress route option value'
93
+ }, (_request, reply) => {
94
+ reply.type('text/plain').compress(stream)
95
+ })
96
96
 
97
- expectError(
98
- appWithoutGlobal.route({
99
- method: 'GET',
100
- path: '/throw-a-ts-arg-error',
101
- compress: 'bad compress route option value',
102
- decompress: 'bad decompress route option value',
103
- handler: (_request, reply) => { expectType<void>(reply.type('text/plain').compress(stream)) }
104
- })
105
- )
97
+ appWithoutGlobal.route({
98
+ method: 'GET',
99
+ path: '/throw-a-ts-arg-error',
100
+ // @ts-expect-error Type 'string' is not assignable
101
+ compress: 'bad compress route option value',
102
+ // @ts-expect-error Type 'string' is not assignable
103
+ decompress: 'bad decompress route option value',
104
+ handler: (_request, reply) => { reply.type('text/plain').compress(stream) }
105
+ })
106
106
 
107
107
  appWithoutGlobal.inject(
108
108
  {
@@ -113,29 +113,29 @@ appWithoutGlobal.inject(
113
113
  }
114
114
  },
115
115
  (err) => {
116
- expectType<Error | undefined>(err)
116
+ expect(err).type.toBe<Error | undefined>()
117
117
  }
118
118
  )
119
119
 
120
120
  // Test that invalid encoding values trigger TypeScript errors
121
- expectError(fastify().register(fastifyCompress, {
121
+ expect(fastify().register).type.not.toBeCallableWith(fastifyCompress, {
122
122
  encodings: ['invalid-encoding']
123
- }))
123
+ })
124
124
 
125
- expectError(fastify().register(fastifyCompress, {
125
+ expect(fastify().register).type.not.toBeCallableWith(fastifyCompress, {
126
126
  requestEncodings: ['another-invalid-encoding']
127
- }))
127
+ })
128
128
 
129
129
  // Instantiation of an app that should trigger a typescript error
130
130
  const appThatTriggerAnError = fastify()
131
- expectError(appThatTriggerAnError.register(fastifyCompress, {
131
+ expect(appThatTriggerAnError.register).type.not.toBeCallableWith(fastifyCompress, {
132
132
  global: true,
133
133
  thisOptionDoesNotExist: 'trigger a typescript error'
134
- }))
134
+ })
135
135
 
136
136
  app.get('/ts-fetch-response', async (_request, reply) => {
137
137
  const resp = new Response('ok', { headers: { 'content-type': 'text/plain' } })
138
- expectType<void>(reply.compress(resp))
138
+ expect(reply.compress(resp)).type.toBe<void>()
139
139
  })
140
140
 
141
141
  app.get('/ts-web-readable-stream', async (_request, reply) => {
@@ -145,5 +145,5 @@ app.get('/ts-web-readable-stream', async (_request, reply) => {
145
145
  controller.close()
146
146
  }
147
147
  })
148
- expectType<void>(reply.compress(stream))
148
+ expect(reply.compress(stream)).type.toBe<void>()
149
149
  })
package/.github/stale.yml DELETED
@@ -1,21 +0,0 @@
1
- # Number of days of inactivity before an issue becomes stale
2
- daysUntilStale: 15
3
- # Number of days of inactivity before a stale issue is closed
4
- daysUntilClose: 7
5
- # Issues with these labels will never be considered stale
6
- exemptLabels:
7
- - "discussion"
8
- - "feature request"
9
- - "bug"
10
- - "help wanted"
11
- - "plugin suggestion"
12
- - "good first issue"
13
- # Label to use when marking an issue as stale
14
- staleLabel: stale
15
- # Comment to post when marking an issue as stale. Set to `false` to disable
16
- markComment: >
17
- This issue has been automatically marked as stale because it has not had
18
- recent activity. It will be closed if no further activity occurs. Thank you
19
- for your contributions.
20
- # Comment to post when closing a stale issue. Set to `false` to disable
21
- closeComment: false