@fastify/caching 9.0.1 → 9.0.2
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/.github/workflows/ci.yml +1 -1
- package/Readme.md +4 -4
- package/eslint.config.js +6 -0
- package/index.js +5 -5
- package/package.json +4 -5
- package/test/cache.test.js +4 -4
- package/test/headers.test.js +1 -1
- package/types/index.d.ts +7 -7
- package/types/index.test-d.ts +30 -30
package/.github/workflows/ci.yml
CHANGED
package/Readme.md
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
# @fastify/caching
|
|
2
2
|
|
|
3
|
-
](https://github.com/fastify/fastify-caching/actions/workflows/ci.yml)
|
|
4
4
|
[](https://www.npmjs.com/package/@fastify/caching)
|
|
5
|
-
[](https://github.com/neostandard/neostandard)
|
|
6
6
|
|
|
7
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
|
|
@@ -105,14 +105,14 @@ fastify.listen({ port: 3000 }, (err) => {
|
|
|
105
105
|
for a *cache-response-directive* as defined by RFC 2616.
|
|
106
106
|
+ `expiresIn` (Default: `undefined`): a value, in seconds, for the *max-age* the
|
|
107
107
|
resource may be cached. When this is set, and `privacy` is not set to `no-cache`,
|
|
108
|
-
then `', max-age=<value>'` will be appended to the `cache-control` header.
|
|
108
|
+
then `', max-age=<value>'` will be appended to the `cache-control` header.
|
|
109
109
|
+ `cache` (Default: `abstract-cache.memclient`): an [abstract-cache][acache]
|
|
110
110
|
protocol compliant cache object. Note: the plugin requires a cache instance to
|
|
111
111
|
properly support the ETag mechanism. Therefore, if a falsy value is supplied
|
|
112
112
|
the default will be used.
|
|
113
113
|
+ `cacheSegment` (Default: `'@fastify/caching'`): segment identifier to use when
|
|
114
114
|
communicating with the cache.
|
|
115
|
-
+ `serverExpiresIn` (Default: `undefined`): a value, in seconds, for the length of time the resource is fresh and may be held in a shared cache (e.g. a CDN). Shared caches will ignore max-age when this is specified, though browsers will continue to use max-age. Should be used with expiresIn, not in place of it. When this is set, and `privacy` is set to `public`, then `', s-maxage=<value>'` will be appended to the `cache-control` header.
|
|
115
|
+
+ `serverExpiresIn` (Default: `undefined`): a value, in seconds, for the length of time the resource is fresh and may be held in a shared cache (e.g. a CDN). Shared caches will ignore max-age when this is specified, though browsers will continue to use max-age. Should be used with expiresIn, not in place of it. When this is set, and `privacy` is set to `public`, then `', s-maxage=<value>'` will be appended to the `cache-control` header.
|
|
116
116
|
|
|
117
117
|
[acache]: https://www.npmjs.com/package/abstract-cache
|
|
118
118
|
|
package/eslint.config.js
ADDED
package/index.js
CHANGED
|
@@ -26,7 +26,7 @@ function etag (value, lifetime) {
|
|
|
26
26
|
return this
|
|
27
27
|
}
|
|
28
28
|
|
|
29
|
-
function
|
|
29
|
+
function cachingLoadByEtag (req, res, next) {
|
|
30
30
|
if (!req.headers['if-none-match']) return next()
|
|
31
31
|
const etag = req.headers['if-none-match']
|
|
32
32
|
this.cache.get({ id: etag, segment: this.cacheSegment }, (err, cached) => {
|
|
@@ -38,7 +38,7 @@ function etagHandleRequest (req, res, next) {
|
|
|
38
38
|
})
|
|
39
39
|
}
|
|
40
40
|
|
|
41
|
-
function
|
|
41
|
+
function cachingStoreByEtag (req, res, payload, next) {
|
|
42
42
|
const etag = res.getHeader('etag')
|
|
43
43
|
if (!etag || !res._etagLife) return next()
|
|
44
44
|
this.cache.set(
|
|
@@ -70,7 +70,7 @@ function fastifyCaching (instance, options, next) {
|
|
|
70
70
|
value += `, s-maxage=${_options.serverExpiresIn}`
|
|
71
71
|
}
|
|
72
72
|
|
|
73
|
-
instance.addHook('onRequest', (req, res, next)
|
|
73
|
+
instance.addHook('onRequest', function cachingSetCacheControlHeader (req, res, next) {
|
|
74
74
|
if (!res.hasHeader('Cache-control')) {
|
|
75
75
|
res.header('Cache-control', value)
|
|
76
76
|
}
|
|
@@ -83,8 +83,8 @@ function fastifyCaching (instance, options, next) {
|
|
|
83
83
|
instance.decorate('etagMaxLife', _options.etagMaxLife)
|
|
84
84
|
instance.decorateReply('etag', etag)
|
|
85
85
|
instance.decorateReply('expires', cachingExpires)
|
|
86
|
-
instance.addHook('onRequest',
|
|
87
|
-
instance.addHook('onSend',
|
|
86
|
+
instance.addHook('onRequest', cachingLoadByEtag)
|
|
87
|
+
instance.addHook('onSend', cachingStoreByEtag)
|
|
88
88
|
|
|
89
89
|
instance[Symbol.for('fastify-caching.registered')] = true
|
|
90
90
|
next()
|
package/package.json
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fastify/caching",
|
|
3
|
-
"version": "9.0.
|
|
3
|
+
"version": "9.0.2",
|
|
4
4
|
"description": "A plugin for Fastify to enable management of cache control headers",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"type": "commonjs",
|
|
7
7
|
"types": "types/index.d.ts",
|
|
8
8
|
"scripts": {
|
|
9
|
-
"lint": "
|
|
10
|
-
"lint:fix": "
|
|
9
|
+
"lint": "eslint",
|
|
10
|
+
"lint:fix": "eslint --fix",
|
|
11
11
|
"test": "npm run test:unit && npm run test:typescript",
|
|
12
12
|
"test:typescript": "tsd",
|
|
13
13
|
"test:unit": "c8 --100 node --test",
|
|
@@ -38,8 +38,7 @@
|
|
|
38
38
|
"@types/node": "^22.0.0",
|
|
39
39
|
"c8": "^10.1.2",
|
|
40
40
|
"fastify": "^5.0.0",
|
|
41
|
-
"
|
|
42
|
-
"standard": "^17.1.0",
|
|
41
|
+
"neostandard": "^0.11.9",
|
|
43
42
|
"tsd": "^0.31.0"
|
|
44
43
|
},
|
|
45
44
|
"dependencies": {
|
package/test/cache.test.js
CHANGED
|
@@ -22,13 +22,13 @@ test('cache is usable', async (t) => {
|
|
|
22
22
|
|
|
23
23
|
const fastify = Fastify()
|
|
24
24
|
await fastify.register(async (instance, options) => {
|
|
25
|
-
instance.addHook('onRequest', async function (req, reply) {
|
|
25
|
+
instance.addHook('onRequest', async function checkCachingRegistered (req, reply) {
|
|
26
26
|
t.assert.ifError(instance[Symbol.for('fastify-caching.registered')])
|
|
27
27
|
})
|
|
28
28
|
})
|
|
29
29
|
await fastify.register(plugin)
|
|
30
30
|
|
|
31
|
-
fastify.addHook('onRequest', async function (req, reply) {
|
|
31
|
+
fastify.addHook('onRequest', async function checkCachingRegistered (req, reply) {
|
|
32
32
|
t.assert.strictEqual(this[Symbol.for('fastify-caching.registered')], true)
|
|
33
33
|
})
|
|
34
34
|
|
|
@@ -71,13 +71,13 @@ test('cache is usable with function as plugin default options input', async (t)
|
|
|
71
71
|
|
|
72
72
|
const fastify = Fastify()
|
|
73
73
|
await fastify.register(async (instance, options) => {
|
|
74
|
-
instance.addHook('onRequest', async function (req, reply) {
|
|
74
|
+
instance.addHook('onRequest', async function checkCachingNotRegistered (req, reply) {
|
|
75
75
|
t.assert.failure(instance[Symbol.for('fastify-caching.registered')])
|
|
76
76
|
})
|
|
77
77
|
})
|
|
78
78
|
await fastify.register(plugin, () => () => {})
|
|
79
79
|
|
|
80
|
-
fastify.addHook('onRequest', async function (req, reply) {
|
|
80
|
+
fastify.addHook('onRequest', async function checkCachingRegistered (req, reply) {
|
|
81
81
|
t.assert.strictEqual(this[Symbol.for('fastify-caching.registered')], true)
|
|
82
82
|
})
|
|
83
83
|
|
package/test/headers.test.js
CHANGED
|
@@ -151,7 +151,7 @@ test('do not set headers if another upstream plugin already sets it', async (t)
|
|
|
151
151
|
}
|
|
152
152
|
|
|
153
153
|
const fastify = Fastify()
|
|
154
|
-
fastify.addHook('onRequest', async (req, reply)
|
|
154
|
+
fastify.addHook('onRequest', async function checkCachingDoesNotOverrideCacheControlHeader (req, reply) {
|
|
155
155
|
reply.header('cache-control', 'do not override')
|
|
156
156
|
})
|
|
157
157
|
await fastify.register(plugin, opts)
|
package/types/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/// <reference types='node' />
|
|
2
2
|
|
|
3
|
-
import { FastifyPluginCallback } from 'fastify'
|
|
3
|
+
import { FastifyPluginCallback } from 'fastify'
|
|
4
4
|
|
|
5
5
|
declare module 'fastify' {
|
|
6
6
|
interface FastifyInstance {
|
|
@@ -33,13 +33,13 @@ declare module 'fastify' {
|
|
|
33
33
|
|
|
34
34
|
type FastifyCaching = FastifyPluginCallback<fastifyCaching.FastifyCachingPluginOptions> & {
|
|
35
35
|
privacy: fastifyCaching.Privacy;
|
|
36
|
-
}
|
|
36
|
+
}
|
|
37
37
|
|
|
38
38
|
type CacheResult<T> = {
|
|
39
39
|
item: T,
|
|
40
40
|
stored: number,
|
|
41
41
|
ttl: number,
|
|
42
|
-
} | null
|
|
42
|
+
} | null
|
|
43
43
|
|
|
44
44
|
declare namespace fastifyCaching {
|
|
45
45
|
/**
|
|
@@ -130,11 +130,11 @@ declare namespace fastifyCaching {
|
|
|
130
130
|
serverExpiresIn?: number;
|
|
131
131
|
}
|
|
132
132
|
|
|
133
|
-
export const privacy: Privacy
|
|
133
|
+
export const privacy: Privacy
|
|
134
134
|
|
|
135
|
-
export const fastifyCaching: FastifyCaching
|
|
136
|
-
export { fastifyCaching as default }
|
|
135
|
+
export const fastifyCaching: FastifyCaching
|
|
136
|
+
export { fastifyCaching as default }
|
|
137
137
|
}
|
|
138
138
|
|
|
139
|
-
declare function fastifyCaching(...params: Parameters<FastifyCaching>): ReturnType<FastifyCaching>
|
|
139
|
+
declare function fastifyCaching (...params: Parameters<FastifyCaching>): ReturnType<FastifyCaching>
|
|
140
140
|
export = fastifyCaching
|
package/types/index.test-d.ts
CHANGED
|
@@ -1,69 +1,69 @@
|
|
|
1
|
-
import Fastify, { FastifyReply } from 'fastify'
|
|
2
|
-
import { expectAssignable, expectError, expectType } from 'tsd'
|
|
1
|
+
import Fastify, { FastifyReply } from 'fastify'
|
|
2
|
+
import { expectAssignable, expectError, expectType } from 'tsd'
|
|
3
3
|
import fastifyCaching, {
|
|
4
4
|
AbstractCacheCompliantObject,
|
|
5
5
|
FastifyCachingPluginOptions,
|
|
6
|
-
} from '..'
|
|
6
|
+
} from '..'
|
|
7
7
|
|
|
8
|
-
const fastify = Fastify({ logger: true })
|
|
8
|
+
const fastify = Fastify({ logger: true })
|
|
9
9
|
|
|
10
10
|
const cachingOptions: FastifyCachingPluginOptions = {
|
|
11
11
|
privacy: fastifyCaching.privacy.PUBLIC,
|
|
12
12
|
expiresIn: 300,
|
|
13
13
|
cacheSegment: 'fastify-caching',
|
|
14
|
-
}
|
|
15
|
-
expectAssignable<FastifyCachingPluginOptions>(cachingOptions)
|
|
14
|
+
}
|
|
15
|
+
expectAssignable<FastifyCachingPluginOptions>(cachingOptions)
|
|
16
16
|
|
|
17
|
-
fastify.register(fastifyCaching, cachingOptions)
|
|
17
|
+
fastify.register(fastifyCaching, cachingOptions)
|
|
18
18
|
|
|
19
|
-
expectType<AbstractCacheCompliantObject>(fastify.cache)
|
|
20
|
-
expectType<AbstractCacheCompliantObject['get']>(fastify.cache.get)
|
|
21
|
-
expectType<AbstractCacheCompliantObject['set']>(fastify.cache.set)
|
|
22
|
-
expectType<string>(fastify.cacheSegment)
|
|
19
|
+
expectType<AbstractCacheCompliantObject>(fastify.cache)
|
|
20
|
+
expectType<AbstractCacheCompliantObject['get']>(fastify.cache.get)
|
|
21
|
+
expectType<AbstractCacheCompliantObject['set']>(fastify.cache.set)
|
|
22
|
+
expectType<string>(fastify.cacheSegment)
|
|
23
23
|
// expectType<number>(fastify.etagMaxLife);
|
|
24
24
|
|
|
25
25
|
fastify.get('/one', async (request, reply) => {
|
|
26
|
-
expectType<(tag?: string, timeToLive?: number) => FastifyReply>(reply.etag)
|
|
27
|
-
expectType<(date?: Date) => FastifyReply>(reply.expires)
|
|
26
|
+
expectType<(tag?: string, timeToLive?: number) => FastifyReply>(reply.etag)
|
|
27
|
+
expectType<(date?: Date) => FastifyReply>(reply.expires)
|
|
28
28
|
|
|
29
|
-
expectType<FastifyReply>(reply.etag('hello', 6000))
|
|
30
|
-
expectType<FastifyReply>(reply.expires(new Date(Date.now() + 6000)))
|
|
29
|
+
expectType<FastifyReply>(reply.etag('hello', 6000))
|
|
30
|
+
expectType<FastifyReply>(reply.expires(new Date(Date.now() + 6000)))
|
|
31
31
|
|
|
32
|
-
return { message: 'one' }
|
|
33
|
-
})
|
|
32
|
+
return { message: 'one' }
|
|
33
|
+
})
|
|
34
34
|
|
|
35
35
|
fastify.get('/two', async (request, reply) => {
|
|
36
36
|
expectType<FastifyReply>(
|
|
37
37
|
reply.etag('hello', 6000).expires(new Date(Date.now() + 6000))
|
|
38
|
-
)
|
|
38
|
+
)
|
|
39
39
|
|
|
40
|
-
return { message: 'two' }
|
|
41
|
-
})
|
|
40
|
+
return { message: 'two' }
|
|
41
|
+
})
|
|
42
42
|
|
|
43
43
|
// We register a new instance that should trigger a typescript error.
|
|
44
|
-
const shouldErrorApp = Fastify({ logger: true })
|
|
44
|
+
const shouldErrorApp = Fastify({ logger: true })
|
|
45
45
|
|
|
46
46
|
const badCachingOptions = {
|
|
47
47
|
privacy: fastifyCaching.privacy.PRIVATE,
|
|
48
48
|
expiresIn: 'a string instead of a number of second',
|
|
49
49
|
cacheSegment: 'fastify-caching',
|
|
50
|
-
}
|
|
50
|
+
}
|
|
51
51
|
|
|
52
|
-
expectError(shouldErrorApp.register(fastifyCaching, badCachingOptions))
|
|
52
|
+
expectError(shouldErrorApp.register(fastifyCaching, badCachingOptions))
|
|
53
53
|
|
|
54
54
|
fastify.get('/three', async (request, reply) => {
|
|
55
55
|
expectAssignable<Promise<unknown>>(
|
|
56
56
|
fastify.cache.get('well-known')
|
|
57
|
-
)
|
|
57
|
+
)
|
|
58
58
|
expectAssignable<Promise<{ item: string; stored: number; ttl: number; } | null>>(
|
|
59
59
|
fastify.cache.get<string>('well-known')
|
|
60
|
-
)
|
|
60
|
+
)
|
|
61
61
|
expectType<void>(
|
|
62
62
|
fastify.cache.get<string>('well-known', (err, value) => {
|
|
63
|
-
expectType<unknown>(err)
|
|
64
|
-
expectAssignable<{ item: string; stored: number; ttl: number; } | null>(value)
|
|
63
|
+
expectType<unknown>(err)
|
|
64
|
+
expectAssignable<{ item: string; stored: number; ttl: number; } | null>(value)
|
|
65
65
|
})
|
|
66
|
-
)
|
|
66
|
+
)
|
|
67
67
|
|
|
68
|
-
return { message: 'two' }
|
|
69
|
-
})
|
|
68
|
+
return { message: 'two' }
|
|
69
|
+
})
|