koa-compress 5.2.0 → 5.2.1

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.
package/HISTORY.md CHANGED
@@ -1,5 +1,15 @@
1
1
  SEE https://github.com/koajs/compress/releases
2
2
 
3
+ 5.2.1 / 2026-03-12
4
+ ==================
5
+
6
+ * fixed TS typings and refactored them
7
+ * minor bug fix
8
+ * simplified code and removed unused code
9
+ * improved docs and typo fixes
10
+ * more tests
11
+ * updated dependencies
12
+
3
13
  5.2.0 / 2026-02-10
4
14
  ==================
5
15
 
package/README.md CHANGED
@@ -42,51 +42,49 @@ app.use(
42
42
  ### filter\<Function\>
43
43
 
44
44
  ```ts
45
- function (mimeType: string): Boolean {
46
-
47
- }
45
+ function (mimeType: string): boolean {}
48
46
  ```
49
47
 
50
- An optional function that checks the response content type to decide whether to compress.
51
- By default, it uses [compressible](https://github.com/jshttp/compressible).
48
+ A predicate that checks the response MIME type to decide whether to compress.
49
+ Default: [compressible](https://github.com/jshttp/compressible).
52
50
 
53
51
  ### options.threshold\<String|Number|Function\>
54
52
 
55
- Minimum response size in bytes to compress or a function that returns such response (see below).
56
- Default `1024` bytes or `1kb`.
53
+ Minimum response size in bytes to compress.
54
+ Can also be a string parsed by `bytes()` (e.g. `"1kb"`) or a function (see [Functional properties](#functional-properties)).
55
+ Default: `1024`.
57
56
 
58
57
  ### options[encoding]\<Object|Function\>
59
58
 
60
- The current encodings are, in order of preference: `br`, `zstd`, `gzip`, `deflate`.
61
- Setting `options[encoding] = {}` will pass those options to the encoding function.
62
- Setting `options[encoding] = false` will disable that encoding.
59
+ Supported encodings in default preference order: `zstd`, `br`, `gzip`, `deflate`.
60
+ Setting `options[encoding] = {}` passes those options to the corresponding `zlib` compressor.
61
+ Setting `options[encoding] = false` disables that encoding.
63
62
 
64
- It can be a function that returns options (see below).
63
+ Can also be a function (see [Functional properties](#functional-properties)).
65
64
 
66
65
  #### options.br
67
66
 
68
- [Brotli compression](https://en.wikipedia.org/wiki/Brotli) is supported in node v11.7.0+, which includes it natively.
69
- As of v5.1.0, the default quality level is 4 for performance reasons.
67
+ [Brotli compression](https://en.wikipedia.org/wiki/Brotli) is available natively in all supported Node.js versions.
68
+ The default quality level is 4 for performance reasons.
70
69
 
71
70
  #### options.zstd
72
71
 
73
- [Zstandard compression](https://en.wikipedia.org/wiki/Zstandard) is natively supported in the Node.js API. Minimum supported version: `v22.15.0` (LTS); also available on the Current line starting from `v23.8.0+`. This middleware performs runtime feature detection for `zlib.createZstdCompress`; if present, Zstd is enabled, otherwise it is skipped—no version configuration required.
72
+ [Zstandard compression](https://en.wikipedia.org/wiki/Zstandard) is natively supported starting from Node.js v22.15.0 (LTS) and v23.8.0 (Current). The middleware detects `zlib.createZstdCompress` at runtime; if available, zstd is enabled automatically, otherwise it is skipped.
74
73
 
75
74
  ### options.defaultEncoding\<String\>
76
75
 
77
- An optional string, which specifies what encoders to use for requests without
78
- [Accept-Encoding](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Accept-Encoding).
79
- Default `identity`.
76
+ Encoding assumed when the client sends no
77
+ [Accept-Encoding](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Accept-Encoding) header.
78
+ Default: `"identity"` (no compression).
80
79
 
81
- The standard dictates to treat such requests as `*` meaning that all compressions are permissible,
82
- yet it causes very practical problems when debugging servers with manual tools like `curl`, `wget`, and so on.
83
- If you want to enable the standard behavior, just set `defaultEncoding` to `*`.
80
+ The HTTP spec treats a missing header as `*` (any encoding is acceptable),
81
+ but that causes problems when debugging with tools like `curl` or `wget`.
82
+ Set `defaultEncoding` to `"*"` to restore spec-compliant behavior.
84
83
 
85
84
  ## Manually turning compression on and off
86
85
 
87
- You can always enable compression by setting `ctx.compress = true`.
88
- You can always disable compression by setting `ctx.compress = false`.
89
- This bypasses the filter check.
86
+ You can force compression by setting `ctx.compress = true` (bypasses the filter check).
87
+ You can disable compression by setting `ctx.compress = false`.
90
88
 
91
89
  ```js
92
90
  app.use((ctx, next) => {
@@ -95,32 +93,31 @@ app.use((ctx, next) => {
95
93
  });
96
94
  ```
97
95
 
98
- `ctx.compress` can be an object similar to `options` above, whose properties (`threshold` and encoding options)
99
- override the global `options` for this response and bypass the filter check.
96
+ `ctx.compress` can also be an options object (same shape as the middleware options).
97
+ Its `threshold` and encoding properties override the global defaults for this response.
98
+ Note: an options object does **not** bypass the filter check — only `true` does.
100
99
 
101
100
  ## Functional properties
102
101
 
103
- Certain properties (`threshold` and encoding options) can be specified as functions. Such functions will be called
102
+ The `threshold` and per-encoding options can be functions. They are called
104
103
  for every response with three arguments:
105
104
 
106
- - `type` &mdash; the same as `ctx.response.type` (provided for convenience)
107
- - `size` &mdash; the same as `ctx.response.length` (provided for convenience)
108
- - `ctx` &mdash; the whole context object, if you want to do something unique
105
+ - `type` &mdash; same as `ctx.response.type`
106
+ - `size` &mdash; same as `ctx.response.length`
107
+ - `ctx` &mdash; the full Koa context object
109
108
 
110
- It should return a valid value for that property. It is possible to return a function of the same shape,
111
- which will be used to calculate the actual property.
109
+ The function should return a valid value for that property.
110
+ Returning another function of the same shape is allowed — it will be called in turn.
112
111
 
113
112
  Example:
114
113
 
115
114
  ```js
116
- app.use((ctx, next) => {
117
- // ...
118
- ctx.compress = (type, size, ctx) => ({
119
- br: size && size >= 65536,
120
- gzip: size && size < 65536,
121
- });
122
- ctx.body = payload;
123
- });
115
+ app.use(
116
+ compress({
117
+ gzip: (type, size) => (size && size < 65536 ? { level: 9 } : false),
118
+ br: (type, size) => size && size >= 65536,
119
+ }),
120
+ );
124
121
  ```
125
122
 
126
- Read all about `ctx` in https://koajs.com/#context and `ctx.response` in https://koajs.com/#response
123
+ See the Koa documentation for [`ctx`](https://koajs.com/#context) and [`ctx.response`](https://koajs.com/#response).
package/lib/index.d.ts CHANGED
@@ -1,136 +1,161 @@
1
1
  import type { BrotliOptions, ZlibOptions, ZstdOptions } from "node:zlib";
2
2
  import type Koa = require("koa");
3
3
 
4
- /**
5
- * Function to calculate a threshold value dynamically from a MIME type,
6
- * an existing size and the current context.
7
- */
8
- export type ThresholdFunction = (
9
- /** MIME type of the response */
10
- type: string,
11
- /** Size of the response in bytes */
12
- size: number,
13
- /** Context of the request */
14
- ctx: Koa.Context,
15
- ) => number | string | ThresholdFunction;
16
-
17
- /**
18
- * Function to calculate compression parameters for `deflate` and `gzip` from a MIME type,
19
- * an exisiting size and the current context.
20
- */
21
- export type ZlibOptionsFunction = (
22
- /** MIME type of the response */
23
- type: string,
24
- /** Size of the response in bytes */
25
- size: number,
26
- /** Context of the request */
27
- ctx: Koa.Context,
28
- ) => boolean | null | ZlibOptions | ZlibOptionsFunction;
29
-
30
- /**
31
- * Function to calculate compression parameters for `brotli` from a MIME type,
32
- * an exisiting size and the current context.
33
- */
34
- export type BrotliOptionsFunction = (
35
- /** MIME type of the response */
36
- type: string,
37
- /** Size of the response in bytes */
38
- size: number,
39
- /** Context of the request */
40
- ctx: Koa.Context,
41
- ) => boolean | null | BrotliOptions | BrotliOptionsFunction;
42
-
43
- /**
44
- * Function to calculate compression parameters for `zstd` from a MIME type,
45
- * an exisiting size and the current context.
46
- */
47
- export type ZstdOptionsFunction = (
48
- /** MIME type of the response */
49
- type: string,
50
- /** Size of the response in bytes */
51
- size: number,
52
- /** Context of the request */
53
- ctx: Koa.Context,
54
- ) => boolean | null | ZstdOptions | ZstdOptionsFunction;
55
-
56
- /**
57
- * Compression options that govern how `koa/compress` handles responses.
58
- */
59
- export type CompressOptions = {
60
- /**
61
- * Function to determine if compression should be applied.
62
- * Default: `compressible()`.
63
- * @param type MIME type of the response
64
- * @returns `true` if compression should be applied, `false` otherwise
65
- */
66
- filter?: (type: string) => boolean;
67
- /**
68
- * Lower limit to apply compression to content. If it is a number, it is size in bytes,
69
- * if it is a string, it is a human-readable size accepted by `bytes()`, e.g., `"1mb"`,
70
- * or a `ThresholdFunction` that can calculate that value. Default: `1024`.
71
- */
72
- threshold?: number | string | ThresholdFunction;
4
+ declare namespace compress {
73
5
  /**
74
- * Default value for `Accept-Encoding` header, if it is not supplied by the client.
75
- * Default: `"identity"`.
6
+ * Calculates a threshold value dynamically from the MIME type,
7
+ * the response size, and the current context.
76
8
  */
77
- defaultEncoding?: string;
9
+ type ThresholdFunction = (
10
+ /** MIME type of the response */
11
+ type: string,
12
+ /** Size of the response in bytes */
13
+ size: number,
14
+ /** Context of the request */
15
+ ctx: Koa.Context,
16
+ ) => number | string | ThresholdFunction;
17
+
78
18
  /**
79
- * What `Accept-Encoding` value should be assumed if it is set to `"*"`. Default: `"gzip"`.
19
+ * Computes `deflate`/`gzip` compression options from the MIME type,
20
+ * the response size, and the current context.
80
21
  */
81
- wildcardAcceptEncoding?: string;
22
+ type ZlibOptionsFunction = (
23
+ /** MIME type of the response */
24
+ type: string,
25
+ /** Size of the response in bytes */
26
+ size: number,
27
+ /** Context of the request */
28
+ ctx: Koa.Context,
29
+ ) => boolean | null | ZlibOptions | ZlibOptionsFunction;
30
+
82
31
  /**
83
- * An array of compression types, which should be used when we have multiple choices
84
- * with the same weight. An item with a lower index has higher priority.
85
- * Default: `['zstd', 'br', 'gzip', 'deflate']`.
32
+ * Computes `brotli` compression options from the MIME type,
33
+ * the response size, and the current context.
86
34
  */
87
- encodingPreference?: string[];
35
+ type BrotliOptionsFunction = (
36
+ /** MIME type of the response */
37
+ type: string,
38
+ /** Size of the response in bytes */
39
+ size: number,
40
+ /** Context of the request */
41
+ ctx: Koa.Context,
42
+ ) => boolean | null | BrotliOptions | BrotliOptionsFunction;
43
+
88
44
  /**
89
- * Options to use when compressing with `deflate()`.
90
- * If it is `false` or `null` this compression should be disabled.
91
- * It can be a function used to calculate such values.
92
- * Default: `{}`.
45
+ * Computes `zstd` compression options from the MIME type,
46
+ * the response size, and the current context.
93
47
  */
94
- deflate?: boolean | null | ZlibOptions | ZlibOptionsFunction;
48
+ type ZstdOptionsFunction = (
49
+ /** MIME type of the response */
50
+ type: string,
51
+ /** Size of the response in bytes */
52
+ size: number,
53
+ /** Context of the request */
54
+ ctx: Koa.Context,
55
+ ) => boolean | null | ZstdOptions | ZstdOptionsFunction;
56
+
95
57
  /**
96
- * Options to use when compressing with `gzip()`.
97
- * If it is `false` or `null` this compression should be disabled.
98
- * It can be a function used to calculate such values.
99
- * Default: `{}`.
58
+ * Options for the `koa-compress` middleware.
100
59
  */
101
- gzip?: boolean | null | ZlibOptions | ZlibOptionsFunction;
60
+ type CompressOptions = {
61
+ /**
62
+ * Predicate that decides whether a given MIME type should be compressed.
63
+ * Default: `compressible()`.
64
+ * @param type - MIME type of the response
65
+ * @returns `true` to compress, `false` to skip
66
+ */
67
+ filter?: (type: string) => boolean;
68
+ /**
69
+ * Minimum response size to compress. A number (bytes), a string
70
+ * parsed by `bytes()` (e.g. `"1mb"`), or a {@link ThresholdFunction}.
71
+ * Default: `1024`.
72
+ */
73
+ threshold?: number | string | ThresholdFunction;
74
+ /**
75
+ * Encoding assumed when the client sends no `Accept-Encoding` header.
76
+ * Set to `"*"` for spec-compliant behavior. Default: `"identity"`.
77
+ */
78
+ defaultEncoding?: string;
79
+ /**
80
+ * Encoding to use when `Accept-Encoding` is `"*"`. Default: `"gzip"`.
81
+ */
82
+ wildcardAcceptEncoding?: string;
83
+ /**
84
+ * Preferred encoding order used to break ties among equally weighted
85
+ * encodings. Lower index = higher priority.
86
+ * Default: `['zstd', 'br', 'gzip', 'deflate', 'identity']`.
87
+ */
88
+ encodingPreference?: string[];
89
+ /**
90
+ * Options passed to `zlib.createDeflate()`, or `false`/`null` to disable.
91
+ * Can be a {@link ZlibOptionsFunction} for per-response values.
92
+ * Default: `{}`.
93
+ */
94
+ deflate?: boolean | null | ZlibOptions | ZlibOptionsFunction;
95
+ /**
96
+ * Options passed to `zlib.createGzip()`, or `false`/`null` to disable.
97
+ * Can be a {@link ZlibOptionsFunction} for per-response values.
98
+ * Default: `{}`.
99
+ */
100
+ gzip?: boolean | null | ZlibOptions | ZlibOptionsFunction;
101
+ /**
102
+ * Options passed to `zlib.createBrotliCompress()`, or `false`/`null` to disable.
103
+ * Can be a {@link BrotliOptionsFunction} for per-response values.
104
+ * Default: `{params: {[zlib.constants.BROTLI_PARAM_QUALITY]: 4}}`.
105
+ */
106
+ br?: boolean | null | BrotliOptions | BrotliOptionsFunction;
107
+ /**
108
+ * Options passed to `zlib.createZstdCompress()`, or `false`/`null` to disable.
109
+ * Can be a {@link ZstdOptionsFunction} for per-response values.
110
+ * Default: `{}`.
111
+ */
112
+ zstd?: boolean | null | ZstdOptions | ZstdOptionsFunction;
113
+ };
114
+
102
115
  /**
103
- * Options to use when compressing with `br()`.
104
- * If it is `false` or `null` this compression should be disabled.
105
- * It can be a function used to calculate such values.
106
- * Default: `{[zlib.constants.BROTLI_PARAM_QUALITY]: 4}`.
116
+ * Per-encoding options: built-in defaults merged with user-supplied values.
107
117
  */
108
- br?: boolean | null | BrotliOptions | BrotliOptionsFunction;
118
+ type EncodingOptions = {
119
+ [encoding: string]: BrotliOptions | ZlibOptions | ZstdOptions | undefined;
120
+ };
121
+
109
122
  /**
110
- * Options to use when compressing with `zstd()`.
111
- * If it is `false` or `null` this compression should be disabled.
112
- * It can be a function used to calculate such values.
113
- * Default: `{}`.
123
+ * Koa middleware with additional properties for introspection.
114
124
  */
115
- zstd?: boolean | null | ZstdOptions | ZstdOptionsFunction;
116
- };
125
+ interface CompressMiddleware extends Koa.Middleware {
126
+ /**
127
+ * Supported content encodings available in the current Node.js runtime,
128
+ * ordered by preference.
129
+ */
130
+ preferredEncodings: string[];
131
+ /**
132
+ * Resolved options for each supported encoding (built-in defaults
133
+ * merged with user-provided values).
134
+ */
135
+ encodingOptions: EncodingOptions;
136
+ }
137
+ }
117
138
 
118
139
  /**
119
- * The main function that constructs a middleware for compressing responses.
120
- * @param options sets the default way to handle compression.
121
- * @returns a middleware function that compresses responses.
140
+ * Creates a Koa middleware that compresses response bodies via content
141
+ * negotiation. The returned function also exposes
142
+ * {@link compress.CompressMiddleware.preferredEncodings | preferredEncodings} and
143
+ * {@link compress.CompressMiddleware.encodingOptions | encodingOptions}.
144
+ *
145
+ * @param options - Compression options. See {@link compress.CompressOptions}.
146
+ * @returns Koa middleware with introspection properties.
122
147
  */
123
- declare function compress(options: CompressOptions = {}): Koa.Middleware;
148
+ declare function compress(options?: compress.CompressOptions): compress.CompressMiddleware;
124
149
 
125
150
  declare module "koa" {
126
151
  interface DefaultContext {
127
152
  /**
128
- * Context property used to handle individual responses.
129
- * If it is set to `false`, the compression is disabled.
130
- * If it is an object, it is mixed with the default options overriding
131
- * its properties for this request.
153
+ * Per-response compression override.
154
+ * Set to `false` to disable compression, `true` to force it
155
+ * (bypassing the filter), or a `CompressOptions` object whose
156
+ * properties override the defaults for this response.
132
157
  */
133
- compress?: boolean | CompressOptions;
158
+ compress?: boolean | compress.CompressOptions;
134
159
  }
135
160
  }
136
161
 
package/lib/index.js CHANGED
@@ -43,9 +43,9 @@ const encodingMethodDefaultOptions = {
43
43
  const NO_TRANSFORM_REGEX = /(?:^|,)\s*?no-transform\s*?(?:,|$)/
44
44
 
45
45
  /**
46
- * empty body statues.
46
+ * empty body statuses.
47
47
  */
48
- const emptyBodyStatues = new Set([204, 205, 304])
48
+ const emptyBodyStatuses = new Set([204, 205, 304])
49
49
 
50
50
  /**
51
51
  * Compress middleware.
@@ -58,12 +58,10 @@ const emptyBodyStatues = new Set([204, 205, 304])
58
58
  module.exports = (options = {}) => {
59
59
  let {
60
60
  filter = compressible,
61
- threshold = 1024,
62
61
  defaultEncoding,
63
62
  wildcardAcceptEncoding,
64
63
  encodingPreference = encodingDefaultPreference
65
64
  } = options
66
- if (typeof threshold === 'string') threshold = bytes(threshold)
67
65
  if (!wildcardAcceptEncoding || wildcardAcceptEncoding === '*') {
68
66
  wildcardAcceptEncoding = 'gzip'
69
67
  }
@@ -103,7 +101,7 @@ module.exports = (options = {}) => {
103
101
  !ctx.writable ||
104
102
  ctx.compress === false ||
105
103
  ctx.request.method === 'HEAD' ||
106
- emptyBodyStatues.has(+ctx.response.status) ||
104
+ emptyBodyStatuses.has(+ctx.response.status) ||
107
105
  ctx.response.get('Content-Encoding') ||
108
106
  // forced compression or implied
109
107
  !(ctx.compress === true || filter(type)) ||
@@ -168,7 +166,8 @@ module.exports = (options = {}) => {
168
166
  ctx.res.removeHeader('Content-Length')
169
167
 
170
168
  const compress = encodingMethods[encoding]
171
- const stream = (ctx.body = compress(responseOptions[encoding]))
169
+ const compressOptions = { ...encodingMethodDefaultOptions[encoding], ...responseOptions[encoding] }
170
+ const stream = (ctx.body = compress(compressOptions))
172
171
 
173
172
  if (body instanceof Stream) return body.pipe(stream)
174
173
  stream.end(body)
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "koa-compress",
3
3
  "description": "Compress middleware for koa",
4
- "version": "5.2.0",
4
+ "version": "5.2.1",
5
5
  "type": "commonjs",
6
6
  "author": {
7
7
  "name": "Jonathan Ong",
@@ -32,10 +32,10 @@
32
32
  },
33
33
  "devDependencies": {
34
34
  "@types/koa": "^3.0.1",
35
- "@types/node": "^25.2.2",
36
- "c8": "^10.1.3",
37
- "jest": "^30.2.0",
38
- "koa": "^3.1.1",
35
+ "@types/node": "^25.5.0",
36
+ "c8": "^11.0.0",
37
+ "jest": "^30.3.0",
38
+ "koa": "^3.1.2",
39
39
  "snazzy": "^9.0.0",
40
40
  "standard": "^17.1.2",
41
41
  "supertest": "^7.2.2",