🚀. Socket Launch Week Day 3:Socket Firewall Now Blocks Malicious VS Code and Open VSX Extensions.Learn more
Sign In

@fastify/compress

Package Overview
Dependencies
Maintainers
18
Versions
24
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@fastify/compress - npm Package Compare versions

Comparing version
8.3.1
to
9.0.0
+19
.github/workflows/lock-threads.yml
name: Lock Threads
on:
schedule:
- cron: '0 0 1 * *'
workflow_dispatch:
concurrency:
group: lock
permissions:
contents: read
jobs:
lock-threads:
permissions:
issues: write
pull-requests: write
uses: fastify/workflows/.github/workflows/lock-threads.yml@v6
'use strict'
const { test } = require('node:test')
const { setTimeout: sleep } = require('node:timers/promises')
const net = require('node:net')
const { Writable } = require('node:stream')
const Fastify = require('fastify')
const fastifyCompress = require('../..')
test('should not log "premature close" errors on client disconnect (global compression)', async (t) => {
let prematureCloseCount = 0
const fastify = Fastify({
logger: {
level: 'error',
stream: new Writable({
write (chunk, encoding, callback) {
if (chunk.toString().includes('premature close')) {
prematureCloseCount++
}
callback()
}
})
}
})
await fastify.register(fastifyCompress, {
global: true,
encodings: ['gzip'],
threshold: 1024
})
// Streaming endpoint that takes time to produce data
fastify.get('/stream', async (_request, reply) => {
let chunks = 0
const stream = new (require('node:stream').Readable)({
read () {
if (chunks >= 20) {
this.push(null)
return
}
setTimeout(() => {
this.push(JSON.stringify({ id: chunks, data: 'x'.repeat(1000) }) + '\n')
chunks++
}, 50)
}
})
reply.type('text/plain')
return stream
})
await fastify.listen({ port: 0 })
const port = fastify.server.address().port
// Simulate clients that disconnect before the full response is sent
for (let i = 0; i < 10; i++) {
await new Promise((_resolve) => {
const sock = net.connect(port, '127.0.0.1', () => {
sock.write('GET /stream HTTP/1.1\r\nHost: localhost\r\nAccept-Encoding: gzip\r\n\r\n')
// Disconnect after receiving partial response (100ms)
setTimeout(() => {
sock.destroy()
_resolve()
}, 100)
})
sock.on('error', () => _resolve())
})
}
// Allow pending callbacks to fire
await sleep(2000)
await fastify.close()
t.assert.equal(
prematureCloseCount,
0,
`Expected no "premature close" errors, but got ${prematureCloseCount} errors from 10 client disconnects`
)
})
test('should not log "premature close" errors on client disconnect (reply.compress path)', async (t) => {
let prematureCloseCount = 0
const fastify = Fastify({
logger: {
level: 'error',
stream: new Writable({
write (chunk, encoding, callback) {
if (chunk.toString().includes('premature close')) {
prematureCloseCount++
}
callback()
}
})
}
})
await fastify.register(fastifyCompress, {
global: false,
encodings: ['gzip']
})
// Streaming endpoint using reply.compress
fastify.get('/stream', async (_request, reply) => {
let chunks = 0
const stream = new (require('node:stream').Readable)({
read () {
if (chunks >= 20) {
this.push(null)
return
}
setTimeout(() => {
this.push(JSON.stringify({ id: chunks, data: 'x'.repeat(1000) }) + '\n')
chunks++
}, 50)
}
})
reply.type('text/plain')
return reply.compress(stream)
})
await fastify.listen({ port: 0 })
const port = fastify.server.address().port
// Simulate clients that disconnect before the full response is sent
for (let i = 0; i < 10; i++) {
await new Promise((_resolve) => {
const sock = net.connect(port, '127.0.0.1', () => {
sock.write('GET /stream HTTP/1.1\r\nHost: localhost\r\nAccept-Encoding: gzip\r\n\r\n')
// Disconnect after receiving partial response (100ms)
setTimeout(() => {
sock.destroy()
_resolve()
}, 100)
})
sock.on('error', () => _resolve())
})
}
// Allow pending callbacks to fire
await sleep(2000)
await fastify.close()
t.assert.equal(
prematureCloseCount,
0,
`Expected no "premature close" errors, but got ${prematureCloseCount} errors from 10 client disconnects`
)
})
test('should still log actual errors (not premature close)', async (t) => {
const errors = []
const fastify = Fastify({
logger: {
level: 'error',
stream: new Writable({
write (chunk, encoding, callback) {
const msg = chunk.toString()
if (msg.includes('premature close')) {
// Ignore premature close errors
} else {
errors.push(msg)
}
callback()
}
})
}
})
await fastify.register(fastifyCompress, {
global: true,
encodings: ['gzip']
})
// Route that throws an error
fastify.get('/error', async () => {
throw new Error('Test error')
})
await fastify.inject({
method: 'GET',
url: '/error',
headers: { 'accept-encoding': 'gzip' }
})
await sleep(500)
t.assert.ok(
errors.length > 0,
'Expected actual errors to still be logged'
)
})
import fastify, { FastifyInstance } from 'fastify'
import { createReadStream } from 'node:fs'
import { expect } from 'tstyche'
import * as zlib from 'node:zlib'
import fastifyCompress, { FastifyCompressOptions } from '..'
const stream = createReadStream('./package.json')
const withGlobalOptions: FastifyCompressOptions = {
global: true,
threshold: 10,
zlib,
brotliOptions: {
params: {
[zlib.constants.BROTLI_PARAM_MODE]: zlib.constants.BROTLI_MODE_TEXT,
[zlib.constants.BROTLI_PARAM_QUALITY]: 4
}
},
zlibOptions: { level: 1 },
inflateIfDeflated: true,
customTypes: /x-protobuf$/,
encodings: ['gzip', 'br', 'identity', 'deflate'],
requestEncodings: ['gzip', 'br', 'identity', 'deflate'],
forceRequestEncoding: 'gzip',
removeContentLengthHeader: true
}
const withZstdOptions: FastifyCompressOptions = {
encodings: ['zstd', 'br', 'gzip', 'deflate', 'identity'],
requestEncodings: ['zstd', 'br', 'gzip', 'deflate', 'identity']
}
const app: FastifyInstance = fastify()
app.register(fastifyCompress, withGlobalOptions)
app.register(fastifyCompress, withZstdOptions)
app.register(fastifyCompress, {
customTypes: value => value === 'application/json'
})
app.get('/test-one', async (_request, reply) => {
expect(reply.compress(stream)).type.toBe<void>()
})
app.get('/test-two', async (_request, reply) => {
expect(reply.compress).type.not.toBeCallableWith()
})
// Instantiation of an app without global
const appWithoutGlobal: FastifyInstance = fastify()
appWithoutGlobal.register(fastifyCompress, { global: false })
appWithoutGlobal.get('/one', {
compress: {
zlib: {
createGzip: () => zlib.createGzip()
},
removeContentLengthHeader: false
},
decompress: {
forceRequestEncoding: 'gzip',
zlib: {
createGunzip: () => zlib.createGunzip()
}
}
}, (_request, reply) => {
expect(reply.type('text/plain').compress(stream)).type.toBe<void>()
})
appWithoutGlobal.get('/two', {
config: {
compress: {
zlib: {
createGzip: () => zlib.createGzip()
}
},
decompress: {
forceRequestEncoding: 'gzip',
zlib: {
createGunzip: () => zlib.createGunzip()
}
}
}
}, (_request, reply) => {
expect(reply.type('text/plain').compress(stream)).type.toBe<void>()
})
appWithoutGlobal.get('/throw-a-ts-arg-error-on-shorthand-route', {
// @ts-expect-error Type 'string' is not assignable
compress: 'bad compress route option value',
// @ts-expect-error Type 'string' is not assignable
decompress: 'bad decompress route option value'
}, (_request, reply) => {
reply.type('text/plain').compress(stream)
})
appWithoutGlobal.route({
method: 'GET',
path: '/throw-a-ts-arg-error',
// @ts-expect-error Type 'string' is not assignable
compress: 'bad compress route option value',
// @ts-expect-error Type 'string' is not assignable
decompress: 'bad decompress route option value',
handler: (_request, reply) => { reply.type('text/plain').compress(stream) }
})
appWithoutGlobal.inject(
{
method: 'GET',
path: '/throw-a-ts-arg-error',
headers: {
'accept-encoding': 'gzip'
}
},
(err) => {
expect(err).type.toBe<Error | undefined>()
}
)
// Test that invalid encoding values trigger TypeScript errors
expect(fastify().register).type.not.toBeCallableWith(fastifyCompress, {
encodings: ['invalid-encoding']
})
expect(fastify().register).type.not.toBeCallableWith(fastifyCompress, {
requestEncodings: ['another-invalid-encoding']
})
// Instantiation of an app that should trigger a typescript error
const appThatTriggerAnError = fastify()
expect(appThatTriggerAnError.register).type.not.toBeCallableWith(fastifyCompress, {
global: true,
thisOptionDoesNotExist: 'trigger a typescript error'
})
app.get('/ts-fetch-response', async (_request, reply) => {
const resp = new Response('ok', { headers: { 'content-type': 'text/plain' } })
expect(reply.compress(resp)).type.toBe<void>()
})
app.get('/ts-web-readable-stream', async (_request, reply) => {
const stream = new ReadableStream({
start (controller) {
controller.enqueue(new Uint8Array([1, 2, 3]))
controller.close()
}
})
expect(reply.compress(stream)).type.toBe<void>()
})
+1
-1

@@ -30,5 +30,5 @@ name: CI

pull-requests: write
uses: fastify/workflows/.github/workflows/plugins-ci.yml@v5
uses: fastify/workflows/.github/workflows/plugins-ci.yml@v6
with:
license-check: true
lint: true
+18
-20

@@ -5,10 +5,9 @@ 'use strict'

const { inherits, format } = require('node:util')
const { pipeline, compose } = require('node:stream')
const fp = require('fastify-plugin')
const encodingNegotiator = require('@fastify/accept-negotiator')
const pump = require('pump')
const mimedb = require('mime-db')
const peek = require('peek-stream')
const { Minipass } = require('minipass')
const pumpify = require('pumpify')
const { Readable } = require('readable-stream')

@@ -54,7 +53,2 @@

fastify.addHook('onRoute', (routeOptions) => {
// If route config.compress has been set it takes precedence over compress
if (routeOptions.config?.compress !== undefined) {
routeOptions.compress = routeOptions.config.compress
}
// Manage compression options

@@ -84,7 +78,2 @@ if (routeOptions.compress !== undefined) {

// If route config.decompress has been set it takes precedence over compress
if (routeOptions.config?.decompress !== undefined) {
routeOptions.decompress = routeOptions.config.decompress
}
// Manage decompression options

@@ -295,3 +284,3 @@ if (routeOptions.decompress !== undefined) {

: reply.header('Content-Encoding', 'identity')
pump(stream, payload = unzipStream(params.uncompressStream), onEnd.bind(reply))
pipeline(stream, payload = unzipStream(params.uncompressStream), onEnd.bind(reply))
}

@@ -323,3 +312,3 @@ return next(null, payload)

stream = zipStream(params.compressStream, encoding)
pump(payload, stream, onEnd.bind(reply))
pipeline(payload, stream, onEnd.bind(reply))
next(null, stream)

@@ -386,3 +375,6 @@ }

next(null, pump(raw, decompresser))
pipeline(raw, decompresser, () => {
// Cleanup callback - decompression errors are handled by decompresser's error handler
})
next(null, decompresser)
}

@@ -424,3 +416,3 @@ }

: this.header('Content-Encoding', 'identity')
pump(stream, payload = unzipStream(params.uncompressStream), onEnd.bind(this))
pipeline(stream, payload = unzipStream(params.uncompressStream), onEnd.bind(this))
}

@@ -456,3 +448,3 @@ return this.send(payload)

stream = zipStream(params.compressStream, encoding)
pump(payload, stream, onEnd.bind(this))
pipeline(payload, stream, onEnd.bind(this))
return this.send(stream)

@@ -475,3 +467,9 @@ }

function onEnd (err) {
if (err) this.log.error(err)
// Client disconnection during streaming is expected and handled by Fastify.
// Do not log "premature close" errors at error level since they are not
// actual errors - they occur when clients disconnect mid-response.
// See: https://github.com/fastify/fastify-compress/issues/382
if (err && err.message !== 'premature close') {
this.log.error(err)
}
}

@@ -577,4 +575,4 @@

switch (isCompressed(data)) {
case 1: return swap(null, pumpify(inflate.gzip(), unzipStream(inflate, maxRecursion - 1)))
case 2: return swap(null, pumpify(inflate.deflate(), unzipStream(inflate, maxRecursion - 1)))
case 1: return swap(null, compose(inflate.gzip(), unzipStream(inflate, maxRecursion - 1)))
case 2: return swap(null, compose(inflate.deflate(), unzipStream(inflate, maxRecursion - 1)))
}

@@ -581,0 +579,0 @@ return swap(null, new Minipass())

MIT License
Copyright (c) 2017-present The Fastify team
Copyright (c) 2017-present The Fastify team <https://github.com/fastify/fastify#team>
The Fastify team members are listed at https://github.com/fastify/fastify#team.
Permission is hereby granted, free of charge, to any person obtaining a copy

@@ -8,0 +6,0 @@ of this software and associated documentation files (the "Software"), to deal

{
"name": "@fastify/compress",
"version": "8.3.1",
"version": "9.0.0",
"description": "Fastify compression utils",

@@ -14,16 +14,14 @@ "main": "index.js",

"peek-stream": "^1.1.3",
"pump": "^3.0.0",
"pumpify": "^2.0.1",
"readable-stream": "^4.5.2"
},
"devDependencies": {
"@types/node": "^24.0.8",
"@types/node": "^25.0.3",
"adm-zip": "^0.5.12",
"c8": "^10.1.2",
"c8": "^11.0.0",
"eslint": "^9.17.0",
"fastify": "^5.0.0",
"jsonstream": "^1.0.3",
"neostandard": "^0.12.0",
"tsd": "^0.33.0",
"typescript": "~5.9.2"
"neostandard": "^0.13.0",
"tstyche": "^7.1.0",
"typescript": "~6.0.2"
},

@@ -34,3 +32,3 @@ "scripts": {

"test": "npm run test:unit && npm run test:typescript",
"test:typescript": "tsd",
"test:typescript": "tstyche",
"test:unit": "node --test",

@@ -87,5 +85,2 @@ "test:coverage": "c8 node --test && c8 report --reporter=html",

},
"tsd": {
"directory": "types"
},
"publishConfig": {

@@ -92,0 +87,0 @@ "access": "public"

@@ -5,5 +5,5 @@ 'use strict'

const { createReadStream } = require('node:fs')
const { pipeline } = require('node:stream')
const path = require('node:path')
const zlib = require('node:zlib')
const pump = require('pump')
const Fastify = require('fastify')

@@ -16,3 +16,5 @@ const compressPlugin = require('../index')

if (compressor) {
payload = pump(payload, compressor())
const compressed = compressor()
pipeline(payload, compressed, () => {})
payload = compressed
}

@@ -19,0 +21,0 @@

@@ -333,91 +333,2 @@ 'use strict'

describe('When using the old routes `{ config: compress }` option :', async () => {
test('it should compress data using the route custom provided `createGzip` method', async (t) => {
t.plan(10)
const equal = t.assert.equal
let usedCustomGlobal = false
let usedCustom = false
const customZlibGlobal = { createGzip: () => (usedCustomGlobal = true) && zlib.createGzip() }
const customZlib = { createGzip: () => (usedCustom = true) && zlib.createGzip() }
const fastify = Fastify()
await fastify.register(compressPlugin, { global: false, zlib: customZlibGlobal })
fastify.get('/', (_request, reply) => {
reply
.type('text/plain')
.compress(createReadStream('./package.json'))
})
fastify.get('/custom', {
config: {
compress: { zlib: customZlib }
}
}, (_request, reply) => {
reply
.type('text/plain')
.compress(createReadStream('./package.json'))
})
await fastify.inject({
url: '/',
method: 'GET',
headers: {
'accept-encoding': 'gzip'
}
}).then((response) => {
equal(usedCustom, false)
equal(usedCustomGlobal, true)
const file = readFileSync('./package.json', 'utf8')
const payload = zlib.gunzipSync(response.rawPayload)
equal(response.headers.vary, 'accept-encoding')
equal(response.headers['content-encoding'], 'gzip')
equal(payload.toString('utf-8'), file)
usedCustom = false
usedCustomGlobal = false
})
const response = await fastify.inject({
url: '/custom',
method: 'GET',
headers: {
'accept-encoding': 'gzip'
}
})
equal(usedCustom, true)
equal(usedCustomGlobal, false)
const file = readFileSync('./package.json', 'utf8')
const payload = zlib.gunzipSync(response.rawPayload)
equal(response.headers.vary, 'accept-encoding')
equal(response.headers['content-encoding'], 'gzip')
equal(payload.toString('utf-8'), file)
})
test('it should use the old routes `{ config: compress }` options over routes `compress` options', async (t) => {
t.plan(1)
const fastify = Fastify()
await fastify.register(compressPlugin, { global: false })
try {
fastify.get('/', {
compress: {
zlib: { createGzip: () => zlib.createGzip() }
},
config: {
compress: 'bad config'
}
}, (_request, reply) => {
reply.send('')
})
} catch (err) {
t.assert.equal(err.message, 'Unknown value for route compress configuration')
}
})
})
test('It should avoid to trigger `onSend` hook twice', async (t) => {

@@ -424,0 +335,0 @@ t.plan(1)

@@ -5,5 +5,5 @@ 'use strict'

const { createReadStream } = require('node:fs')
const { pipeline } = require('node:stream')
const path = require('node:path')
const zlib = require('node:zlib')
const pump = require('pump')
const Fastify = require('fastify')

@@ -16,3 +16,5 @@ const compressPlugin = require('../index')

if (compressor) {
payload = pump(payload, compressor())
const compressed = compressor()
pipeline(payload, compressed, () => {})
payload = compressed
}

@@ -236,86 +238,1 @@

})
describe('When using the old routes `{ config: decompress }` option :', async () => {
test('it should decompress data using the route custom provided `createGunzip` method', async (t) => {
t.plan(8)
const equal = t.assert.equal
let usedCustomGlobal = false
let usedCustom = false
const customZlibGlobal = { createGunzip: () => (usedCustomGlobal = true) && zlib.createGunzip() }
const customZlib = { createGunzip: () => (usedCustom = true) && zlib.createGunzip() }
const fastify = Fastify()
await fastify.register(compressPlugin, { zlib: customZlibGlobal })
fastify.post('/', (request, reply) => {
reply.send(request.body.name)
})
fastify.post('/custom', {
config: {
decompress: {
zlib: customZlib
}
}
}, (request, reply) => {
reply.send(request.body.name)
})
await fastify.inject({
url: '/',
method: 'POST',
headers: {
'content-type': 'application/json',
'content-encoding': 'gzip'
},
payload: createPayload(zlib.createGzip)
}).then((response) => {
equal(usedCustom, false)
equal(usedCustomGlobal, true)
equal(response.statusCode, 200)
equal(response.body, '@fastify/compress')
usedCustom = false
usedCustomGlobal = false
})
const response = await fastify.inject({
url: '/custom',
method: 'POST',
headers: {
'content-type': 'application/json',
'content-encoding': 'gzip'
},
payload: createPayload(zlib.createGzip)
})
equal(usedCustom, true)
equal(usedCustomGlobal, false)
equal(response.statusCode, 200)
equal(response.body, '@fastify/compress')
})
test('it should use the old routes `{ config: decompress }` options over routes `decompress` options', async (t) => {
t.plan(1)
const fastify = Fastify()
await fastify.register(compressPlugin, { global: false })
try {
fastify.post('/', {
decompress: {
zlib: { createGunzip: () => zlib.createGunzip() }
},
config: {
decompress: 'bad config'
}
}, (request, reply) => {
reply.send(request.body.name)
})
} catch (err) {
t.assert.equal(err.message, 'Unknown value for route decompress configuration')
}
})
})

@@ -13,9 +13,2 @@ import {

declare module 'fastify' {
export interface FastifyContextConfig {
/** @deprecated `config.compress` is deprecated, use `compress` shorthand option instead */
compress?: RouteCompressOptions | false;
/** @deprecated `config.decompress` is deprecated, use `decompress` shorthand option instead */
decompress?: RouteDecompressOptions | false;
}
export interface RouteShorthandOptions<

@@ -101,9 +94,2 @@ // eslint-disable-next-line @typescript-eslint/no-unused-vars

export interface RoutesConfigCompressOptions {
/** @deprecated `config.compress` is deprecated, use `compress` shorthand option instead */
compress?: RouteCompressOptions | false;
/** @deprecated `config.decompress` is deprecated, use `decompress` shorthand option instead */
decompress?: RouteDecompressOptions | false;
}
export const fastifyCompress: FastifyCompress

@@ -110,0 +96,0 @@ export { fastifyCompress as default }

# Number of days of inactivity before an issue becomes stale
daysUntilStale: 15
# Number of days of inactivity before a stale issue is closed
daysUntilClose: 7
# Issues with these labels will never be considered stale
exemptLabels:
- "discussion"
- "feature request"
- "bug"
- "help wanted"
- "plugin suggestion"
- "good first issue"
# Label to use when marking an issue as stale
staleLabel: stale
# Comment to post when marking an issue as stale. Set to `false` to disable
markComment: >
This issue has been automatically marked as stale because it has not had
recent activity. It will be closed if no further activity occurs. Thank you
for your contributions.
# Comment to post when closing a stale issue. Set to `false` to disable
closeComment: false
import fastify, { FastifyInstance } from 'fastify'
import { createReadStream } from 'node:fs'
import { expectError, expectType } from 'tsd'
import * as zlib from 'node:zlib'
import fastifyCompress, { FastifyCompressOptions } from '..'
const stream = createReadStream('./package.json')
const withGlobalOptions: FastifyCompressOptions = {
global: true,
threshold: 10,
zlib,
brotliOptions: {
params: {
[zlib.constants.BROTLI_PARAM_MODE]: zlib.constants.BROTLI_MODE_TEXT,
[zlib.constants.BROTLI_PARAM_QUALITY]: 4
}
},
zlibOptions: { level: 1 },
inflateIfDeflated: true,
customTypes: /x-protobuf$/,
encodings: ['gzip', 'br', 'identity', 'deflate'],
requestEncodings: ['gzip', 'br', 'identity', 'deflate'],
forceRequestEncoding: 'gzip',
removeContentLengthHeader: true
}
const withZstdOptions: FastifyCompressOptions = {
encodings: ['zstd', 'br', 'gzip', 'deflate', 'identity'],
requestEncodings: ['zstd', 'br', 'gzip', 'deflate', 'identity']
}
const app: FastifyInstance = fastify()
app.register(fastifyCompress, withGlobalOptions)
app.register(fastifyCompress, withZstdOptions)
app.register(fastifyCompress, {
customTypes: value => value === 'application/json'
})
app.get('/test-one', async (_request, reply) => {
expectType<void>(reply.compress(stream))
})
app.get('/test-two', async (_request, reply) => {
expectError(reply.compress())
})
// Instantiation of an app without global
const appWithoutGlobal: FastifyInstance = fastify()
appWithoutGlobal.register(fastifyCompress, { global: false })
appWithoutGlobal.get('/one', {
compress: {
zlib: {
createGzip: () => zlib.createGzip()
},
removeContentLengthHeader: false
},
decompress: {
forceRequestEncoding: 'gzip',
zlib: {
createGunzip: () => zlib.createGunzip()
}
}
}, (_request, reply) => {
expectType<void>(reply.type('text/plain').compress(stream))
})
appWithoutGlobal.get('/two', {
config: {
compress: {
zlib: {
createGzip: () => zlib.createGzip()
}
},
decompress: {
forceRequestEncoding: 'gzip',
zlib: {
createGunzip: () => zlib.createGunzip()
}
}
}
}, (_request, reply) => {
expectType<void>(reply.type('text/plain').compress(stream))
})
expectError(
appWithoutGlobal.get('/throw-a-ts-arg-error-on-shorthand-route', {
compress: 'bad compress route option value',
decompress: 'bad decompress route option value'
}, (_request, reply) => {
expectType<void>(reply.type('text/plain').compress(stream))
})
)
expectError(
appWithoutGlobal.route({
method: 'GET',
path: '/throw-a-ts-arg-error',
compress: 'bad compress route option value',
decompress: 'bad decompress route option value',
handler: (_request, reply) => { expectType<void>(reply.type('text/plain').compress(stream)) }
})
)
appWithoutGlobal.inject(
{
method: 'GET',
path: '/throw-a-ts-arg-error',
headers: {
'accept-encoding': 'gzip'
}
},
(err) => {
expectType<Error | undefined>(err)
}
)
// Test that invalid encoding values trigger TypeScript errors
expectError(fastify().register(fastifyCompress, {
encodings: ['invalid-encoding']
}))
expectError(fastify().register(fastifyCompress, {
requestEncodings: ['another-invalid-encoding']
}))
// Instantiation of an app that should trigger a typescript error
const appThatTriggerAnError = fastify()
expectError(appThatTriggerAnError.register(fastifyCompress, {
global: true,
thisOptionDoesNotExist: 'trigger a typescript error'
}))
app.get('/ts-fetch-response', async (_request, reply) => {
const resp = new Response('ok', { headers: { 'content-type': 'text/plain' } })
expectType<void>(reply.compress(resp))
})
app.get('/ts-web-readable-stream', async (_request, reply) => {
const stream = new ReadableStream({
start (controller) {
controller.enqueue(new Uint8Array([1, 2, 3]))
controller.close()
}
})
expectType<void>(reply.compress(stream))
})