Skip to content

Commit c5919b0

Browse files
authored
feat: move to compress and decompress route options and typescript improvements (#199)
* test (types): move `index.test-d.ts` file to `test/types` folder * feat!: add `compress` and `decompress` route shorthand configuration properties * test: update routes related tests * types: update typescript types * test (types): actually test typescript types * docs: update documentation * chore: add new npm scripts * test: make sure the old `(de)compress` route option won't break * fix: make sure the old `(de)compress` route option won't break * fix: typo * types: add `package.json` types entry * refactor: use `request` instead of `req` * fix (types): mark `config.(de)compress` use as deprecated
1 parent 2fb87c7 commit c5919b0

File tree

8 files changed

+437
-161
lines changed

8 files changed

+437
-161
lines changed

README.md

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -51,18 +51,20 @@ fastify.register(
5151

5252
// only compress if the payload is above a certain size and use brotli
5353
fastify.get('/custom-route', {
54-
config: {
55-
compress: {
56-
threshold: 128
57-
brotli: brotli
58-
}
54+
compress: {
55+
inflateIfDeflated: true,
56+
threshold: 128,
57+
zlib: {
58+
createBrotliCompress: () => createYourCustomBrotliCompress(),
59+
createGzip: () => createYourCustomGzip(),
60+
createDeflate: () => createYourCustomDeflate()
5961
}
6062
}, (req, reply) => {
6163
// ...
6264
})
6365
```
6466
65-
Note: Setting `config.compress = false` on any route will disable compression on the route even if global compression is enabled.
67+
Note: Setting `compress = false` on any route will disable compression on the route even if global compression is enabled.
6668
6769
### `reply.compress`
6870
This plugin adds a `compress` method to `reply` that accepts a stream or a string, and compresses it based on the `accept-encoding` header. If a JS object is passed in, it will be stringified to JSON.
@@ -204,12 +206,15 @@ fastify.register(
204206

205207
// Always decompress using gzip
206208
fastify.get('/custom-route', {
207-
config: {
208-
decompress: {
209-
forceRequestEncoding: 'gzip'
210-
}
209+
decompress: {
210+
forceRequestEncoding: 'gzip',
211+
zlib: {
212+
createBrotliDecompress: () => createYourCustomBrotliDecompress(),
213+
createGunzip: () => createYourCustomGunzip(),
214+
createInflate: () => createYourCustomInflate()
211215
}
212-
}, (req, reply) => {
216+
}
217+
}, (req, reply) => {
213218
// ...
214219
})
215220
```

index.d.ts

Lines changed: 72 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,79 @@
1-
import { FastifyPlugin, FastifyReply, FastifyRequest } from 'fastify';
2-
import { Input, InputObject } from 'into-stream';
3-
import { Stream } from 'stream';
4-
import { BrotliOptions, ZlibOptions } from 'zlib';
1+
import {
2+
FastifyPluginCallback,
3+
FastifyReply,
4+
FastifyRequest,
5+
RawServerBase,
6+
RawServerDefault
7+
} from 'fastify'
8+
import * as fastify from 'fastify'
9+
import { Input, InputObject } from 'into-stream'
10+
import { Stream } from 'stream'
11+
import { BrotliOptions, ZlibOptions } from 'zlib'
12+
13+
type EncodingToken = 'br' | 'deflate' | 'gzip' | 'identity';
14+
15+
export interface FastifyCompressOptions {
16+
brotliOptions?: BrotliOptions;
17+
customTypes?: RegExp;
18+
encodings?: EncodingToken[];
19+
forceRequestEncoding?: EncodingToken;
20+
global?: boolean;
21+
inflateIfDeflated?: boolean;
22+
onInvalidRequestPayload?: (encoding: string, request: FastifyRequest, error: Error) => Error | undefined | null;
23+
onUnsupportedEncoding?: (encoding: string, request: FastifyRequest, reply: FastifyReply) => string | Buffer | Stream;
24+
onUnsupportedRequestEncoding?: (encoding: string, request: FastifyRequest, reply: FastifyReply) => Error | undefined | null;
25+
requestEncodings?: EncodingToken[];
26+
threshold?: number;
27+
zlib?: unknown;
28+
zlibOptions?: ZlibOptions;
29+
}
30+
31+
interface RouteCompressOptions extends Pick<FastifyCompressOptions,
32+
| 'brotliOptions'
33+
| 'customTypes'
34+
| 'encodings'
35+
| 'inflateIfDeflated'
36+
| 'onUnsupportedEncoding'
37+
| 'threshold'
38+
| 'zlib'
39+
| 'zlibOptions'
40+
> {}
41+
42+
interface RouteDecompressOptions extends Pick<FastifyCompressOptions,
43+
| 'forceRequestEncoding'
44+
| 'onInvalidRequestPayload'
45+
| 'onUnsupportedRequestEncoding'
46+
| 'requestEncodings'
47+
| 'zlib'
48+
> {}
49+
50+
interface FastifyCompressRouteOptions {
51+
compress?: RouteCompressOptions | false;
52+
decompress?: RouteDecompressOptions | false;
53+
}
54+
55+
export interface RouteOptions extends fastify.RouteOptions, FastifyCompressRouteOptions {}
56+
57+
export interface RoutesConfigCompressOptions {
58+
/** @deprecated `config.compress` is deprecated, use `compress` shorthand option instead */
59+
compress?: RouteCompressOptions | false;
60+
/** @deprecated `config.decompress` is deprecated, use `decompress` shorthand option instead */
61+
decompress?: RouteDecompressOptions | false;
62+
}
63+
64+
declare module 'fastify' {
65+
export interface FastifyContextConfig extends RoutesConfigCompressOptions {}
66+
67+
export interface RouteShorthandOptions<
68+
RawServer extends RawServerBase = RawServerDefault
69+
> extends FastifyCompressRouteOptions {}
570

6-
declare module "fastify" {
771
interface FastifyReply {
872
compress(input: Stream | Input | InputObject): void;
973
}
10-
}
1174

12-
type EncodingToken = 'br' | 'deflate' | 'gzip' | 'identity'
13-
14-
export interface FastifyCompressOptions {
15-
global?: boolean
16-
threshold?: number
17-
customTypes?: RegExp
18-
zlib?: NodeModule
19-
brotliOptions?: BrotliOptions
20-
zlibOptions?: ZlibOptions
21-
inflateIfDeflated?: boolean
22-
onUnsupportedEncoding?: (encoding: string, request: FastifyRequest, reply: FastifyReply) => string | Buffer | Stream
23-
encodings?: Array<EncodingToken>
24-
requestEncodings?: Array<EncodingToken>
25-
forceRequestEncoding?: EncodingToken
26-
  onUnsupportedRequestEncoding?: (encoding: string, request: FastifyRequest, reply: FastifyReply) => Error | undefined | null
27-
onInvalidRequestPayload?: (encoding: string, request: FastifyRequest, error: Error) => Error | undefined | null
75+
export interface RouteOptions extends FastifyCompressRouteOptions {}
2876
}
2977

30-
declare const fastifyCompress: FastifyPlugin<FastifyCompressOptions>
31-
export default fastifyCompress;
78+
declare const fastifyCompress: FastifyPluginCallback<FastifyCompressOptions>
79+
export default fastifyCompress

index.js

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -52,16 +52,21 @@ function compressPlugin (fastify, opts, next) {
5252

5353
// add onSend hook onto each route as needed
5454
fastify.addHook('onRoute', (routeOptions) => {
55-
// Manage compression options
55+
// If route config.compress has been set it takes precedence over compress
5656
if (routeOptions.config && typeof routeOptions.config.compress !== 'undefined') {
57-
if (typeof routeOptions.config.compress === 'object') {
57+
routeOptions.compress = routeOptions.config.compress
58+
}
59+
60+
// Manage compression options
61+
if (typeof routeOptions.compress !== 'undefined') {
62+
if (typeof routeOptions.compress === 'object') {
5863
const mergedCompressParams = Object.assign(
59-
{}, globalCompressParams, processCompressParams(routeOptions.config.compress)
64+
{}, globalCompressParams, processCompressParams(routeOptions.compress)
6065
)
6166

6267
// if the current endpoint has a custom compress configuration ...
6368
buildRouteCompress(fastify, mergedCompressParams, routeOptions)
64-
} else if (routeOptions.config.compress === false) {
69+
} else if (routeOptions.compress === false) {
6570
// don't apply any compress settings
6671
} else {
6772
throw new Error('Unknown value for route compress configuration')
@@ -76,16 +81,21 @@ function compressPlugin (fastify, opts, next) {
7681
buildRouteCompress(fastify, globalCompressParams, routeOptions, true)
7782
}
7883

79-
// Manage decompression options
84+
// If route config.decompress has been set it takes precedence over compress
8085
if (routeOptions.config && typeof routeOptions.config.decompress !== 'undefined') {
81-
if (typeof routeOptions.config.decompress === 'object') {
86+
routeOptions.decompress = routeOptions.config.decompress
87+
}
88+
89+
// Manage decompression options
90+
if (typeof routeOptions.decompress !== 'undefined') {
91+
if (typeof routeOptions.decompress === 'object') {
8292
// if the current endpoint has a custom compress configuration ...
8393
const mergedDecompressParams = Object.assign(
84-
{}, globalDecompressParams, processDecompressParams(routeOptions.config.decompress)
94+
{}, globalDecompressParams, processDecompressParams(routeOptions.decompress)
8595
)
8696

8797
buildRouteDecompress(fastify, mergedDecompressParams, routeOptions)
88-
} else if (routeOptions.config.decompress === false) {
98+
} else if (routeOptions.decompress === false) {
8999
// don't apply any decompress settings
90100
} else {
91101
throw new Error('Unknown value for route decompress configuration')

package.json

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
"version": "3.6.1",
44
"description": "Fastify compression utils",
55
"main": "index.js",
6+
"types": "index.d.ts",
67
"dependencies": {
78
"encoding-negotiator": "^2.0.1",
89
"fastify-plugin": "^3.0.0",
@@ -34,11 +35,16 @@
3435
},
3536
"scripts": {
3637
"coverage": "npm run unit -- --cov",
37-
"coverage-report": "npm run coverage && tap --coverage-report=lcov",
38-
"lint:typescript": "standard --fix --parser @typescript-eslint/parser --plugin typescript test/types/*.ts",
39-
"test": "standard && npm run unit && npm run typescript",
40-
"typescript": "tsd",
41-
"unit": "tap -J test/*.js"
38+
"coverage-report": "npm run coverage -- --coverage-report=lcov",
39+
"lint": "standard",
40+
"lint:fix": "npm run lint -- --fix",
41+
"lint:typescript": "npm run lint:fix -- --parser @typescript-eslint/parser --plugin typescript test/types/*.ts",
42+
"lint:types": "npm run lint:fix -- --parser @typescript-eslint/parser --plugin typescript *.d.ts",
43+
"test": "npm run lint && npm run unit && npm run test:typescript",
44+
"test:typescript": "tsd",
45+
"unit": "tap -J test/*.js",
46+
"unit:report": "npm run unit -- --cov --coverage-report=html",
47+
"unit:verbose": "npm run unit -- -Rspec"
4248
},
4349
"keywords": [
4450
"fastify",
@@ -61,6 +67,6 @@
6167
"node": ">=10.16"
6268
},
6369
"tsd": {
64-
"directory": "test"
70+
"directory": "test/types"
6571
}
6672
}

test/index.test-d.ts

Lines changed: 0 additions & 35 deletions
This file was deleted.

0 commit comments

Comments
 (0)