@fastify/caching 8.2.0 → 8.4.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.
package/.gitattributes ADDED
@@ -0,0 +1,2 @@
1
+ # Set default behavior to automatically convert line endings
2
+ * text=auto eol=lf
@@ -2,6 +2,11 @@ name: CI
2
2
 
3
3
  on:
4
4
  push:
5
+ branches:
6
+ - main
7
+ - master
8
+ - next
9
+ - 'v*'
5
10
  paths-ignore:
6
11
  - 'docs/**'
7
12
  - '*.md'
package/Readme.md CHANGED
@@ -4,7 +4,7 @@
4
4
  [![NPM version](https://img.shields.io/npm/v/@fastify/caching.svg?style=flat)](https://www.npmjs.com/package/@fastify/caching)
5
5
  [![js-standard-style](https://img.shields.io/badge/code%20style-standard-brightgreen.svg?style=flat)](https://standardjs.com/)
6
6
 
7
- *@fastify/caching* is a plugin for the [Fastify](http://fastify.io/) framework
7
+ *@fastify/caching* is a plugin for the [Fastify](http://fastify.dev/) framework
8
8
  that provides server-side caching and mechanisms for manipulating HTTP cache headers according to
9
9
  [RFC 2616 §14.9](https://tools.ietf.org/html/rfc2616#section-14.9).
10
10
 
@@ -30,7 +30,7 @@ This example shows using the plugin to disable client side caching of all
30
30
  routes.
31
31
 
32
32
  ```js
33
- const http = require('http')
33
+ const http = require('node:http')
34
34
  const fastify = require('fastify')()
35
35
  const fastifyCaching = require('@fastify/caching')
36
36
 
package/index.js CHANGED
@@ -3,7 +3,7 @@
3
3
  /* eslint no-prototype-builtins: 0 */
4
4
 
5
5
  const fp = require('fastify-plugin')
6
- const uidSafe = require('uid-safe')
6
+ const { sync } = require('uid-safe')
7
7
  const abstractCache = require('abstract-cache')
8
8
 
9
9
  const defaultOptions = {
@@ -21,11 +21,7 @@ function cachingExpires (date) {
21
21
  }
22
22
 
23
23
  function etag (value, lifetime) {
24
- if (value) {
25
- this.header('ETag', value)
26
- } else {
27
- this.header('ETag', uidSafe.sync(18))
28
- }
24
+ this.header('ETag', value || sync(18))
29
25
  this._etagLife = Number.isInteger(lifetime) ? lifetime : 3600000
30
26
  return this
31
27
  }
@@ -35,7 +31,7 @@ function etagHandleRequest (req, res, next) {
35
31
  const etag = req.headers['if-none-match']
36
32
  this.cache.get({ id: etag, segment: this.cacheSegment }, (err, cached) => {
37
33
  if (err) return next(err)
38
- if (cached && cached.item) {
34
+ if (cached?.item) {
39
35
  return res.status(304).send()
40
36
  }
41
37
  next()
@@ -75,7 +71,9 @@ function fastifyCaching (instance, options, next) {
75
71
  }
76
72
 
77
73
  instance.addHook('onRequest', (req, res, next) => {
78
- res.header('Cache-control', value)
74
+ if (!res.hasHeader('Cache-control')) {
75
+ res.header('Cache-control', value)
76
+ }
79
77
  next()
80
78
  })
81
79
  }
package/package.json CHANGED
@@ -1,11 +1,13 @@
1
1
  {
2
2
  "name": "@fastify/caching",
3
- "version": "8.2.0",
3
+ "version": "8.4.0",
4
4
  "description": "A plugin for Fastify to enable management of cache control headers",
5
5
  "main": "index.js",
6
+ "type": "commonjs",
6
7
  "types": "types/index.d.ts",
7
8
  "scripts": {
8
9
  "lint": "standard --verbose | snazzy",
10
+ "lint:fix": "standard --verbose --fix | snazzy",
9
11
  "test": "npm run test:unit && npm run test:typescript",
10
12
  "test:typescript": "tsd",
11
13
  "test:unit": "tap",
@@ -33,16 +35,16 @@
33
35
  "homepage": "https://github.com/fastify/fastify-caching#readme",
34
36
  "devDependencies": {
35
37
  "@fastify/pre-commit": "^2.0.2",
36
- "@types/node": "^18.0.0",
37
- "fastify": "^4.0.0-rc.3",
38
+ "@types/node": "^20.6.1",
39
+ "fastify": "^4.23.2",
38
40
  "snazzy": "^9.0.0",
39
- "standard": "^17.0.0",
40
- "tap": "^16.0.0",
41
- "tsd": "^0.25.0"
41
+ "standard": "^17.1.0",
42
+ "tap": "^16.3.8",
43
+ "tsd": "^0.31.0"
42
44
  },
43
45
  "dependencies": {
44
46
  "abstract-cache": "^1.0.1",
45
- "fastify-plugin": "^4.0.0",
47
+ "fastify-plugin": "^4.5.1",
46
48
  "uid-safe": "^2.1.5"
47
49
  },
48
50
  "publishConfig": {
@@ -139,6 +139,35 @@ test('sets public with max-age and s-maxage header', async (t) => {
139
139
  t.equal(response.headers['cache-control'], 'public, max-age=300, s-maxage=12345')
140
140
  })
141
141
 
142
+ test('do not set headers if another upstream plugin already sets it', async (t) => {
143
+ t.plan(2)
144
+
145
+ const opts = {
146
+ privacy: plugin.privacy.PUBLIC,
147
+ expiresIn: 300,
148
+ serverExpiresIn: 12345
149
+ }
150
+
151
+ const fastify = Fastify()
152
+ fastify.addHook('onRequest', async (req, reply) => {
153
+ reply.header('cache-control', 'do not override')
154
+ })
155
+ await fastify.register(plugin, opts)
156
+
157
+ fastify.get('/', (req, reply) => {
158
+ reply.send({ hello: 'world' })
159
+ })
160
+
161
+ await fastify.ready()
162
+
163
+ const response = await fastify.inject({
164
+ method: 'GET',
165
+ path: '/'
166
+ })
167
+ t.ok(response.headers['cache-control'])
168
+ t.equal(response.headers['cache-control'], 'do not override')
169
+ })
170
+
142
171
  test('only sets max-age and ignores s-maxage with private header', async (t) => {
143
172
  t.plan(2)
144
173
 
package/types/index.d.ts CHANGED
@@ -35,15 +35,28 @@ type FastifyCaching = FastifyPluginCallback<fastifyCaching.FastifyCachingPluginO
35
35
  privacy: fastifyCaching.Privacy;
36
36
  };
37
37
 
38
+ type CacheResult<T> = {
39
+ item: T,
40
+ stored: number,
41
+ ttl: number,
42
+ } | null;
43
+
38
44
  declare namespace fastifyCaching {
39
45
  /**
40
46
  * @link [`abstract-cache` protocol documentation](https://github.com/jsumners/abstract-cache#protocol)
41
47
  */
42
48
  export interface AbstractCacheCompliantObject {
43
- get(
49
+ get<T = unknown>(
44
50
  key: string | { id: string; segment: string },
45
- callback?: (error: unknown, result: unknown) => void
51
+ callback: (error: unknown, result: CacheResult<T>) => void
46
52
  ): void;
53
+ /**
54
+ * If AbstractCache is using useAwait = true, then this method-header must be used.
55
+ * @param key
56
+ */
57
+ get<T = unknown>(
58
+ key: string | { id: string; segment: string },
59
+ ): Promise<CacheResult<T>>;
47
60
  set(
48
61
  key: string | { id: string; segment: string },
49
62
  value: unknown,
@@ -117,9 +130,8 @@ declare namespace fastifyCaching {
117
130
  serverExpiresIn?: number;
118
131
  }
119
132
 
120
- export const privacy: {
121
- privacy: Privacy;
122
- };
133
+ export const privacy: Privacy;
134
+
123
135
  export const fastifyCaching: FastifyCaching;
124
136
  export { fastifyCaching as default };
125
137
  }
@@ -50,3 +50,20 @@ const badCachingOptions = {
50
50
  };
51
51
 
52
52
  expectError(shouldErrorApp.register(fastifyCaching, badCachingOptions));
53
+
54
+ fastify.get('/three', async (request, reply) => {
55
+ expectAssignable<Promise<unknown>>(
56
+ fastify.cache.get('well-known')
57
+ );
58
+ expectAssignable<Promise<{ item: string; stored: number; ttl: number; } | null>>(
59
+ fastify.cache.get<string>('well-known')
60
+ );
61
+ expectType<void>(
62
+ fastify.cache.get<string>('well-known', (err, value) => {
63
+ expectType<unknown>(err);
64
+ expectAssignable<{ item: string; stored: number; ttl: number; } | null>(value);
65
+ })
66
+ );
67
+
68
+ return { message: 'two' };
69
+ });