@envelop/response-cache 3.0.0-alpha-9dd2d31.0 → 3.0.0-alpha-9e9dfbb.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/README.md +39 -21
- package/cjs/cache-document-str.js +26 -0
- package/cjs/plugin.js +9 -20
- package/esm/cache-document-str.js +21 -0
- package/esm/plugin.js +9 -19
- package/package.json +1 -1
- package/typings/cache-document-str.d.ts +4 -0
- package/typings/plugin.d.ts +3 -4
package/README.md
CHANGED
|
@@ -44,7 +44,10 @@ import { useResponseCache } from '@envelop/response-cache';
|
|
|
44
44
|
const getEnveloped = envelop({
|
|
45
45
|
plugins: [
|
|
46
46
|
// ... other plugins ...
|
|
47
|
-
useResponseCache(
|
|
47
|
+
useResponseCache({
|
|
48
|
+
// use global cache for all operations
|
|
49
|
+
session: () => null,
|
|
50
|
+
}),
|
|
48
51
|
],
|
|
49
52
|
});
|
|
50
53
|
```
|
|
@@ -61,12 +64,31 @@ const getEnveloped = envelop({
|
|
|
61
64
|
plugins: [
|
|
62
65
|
// ... other plugins ...
|
|
63
66
|
useResponseCache({ cache }),
|
|
67
|
+
session: () => null, // use global cache for all operations
|
|
64
68
|
],
|
|
65
69
|
});
|
|
66
70
|
```
|
|
67
71
|
|
|
68
72
|
> Note: The in-memory LRU cache is not suitable for serverless deployments. Instead, consider the Redis cache provided by `@envelop/response-cache-redis`.
|
|
69
73
|
|
|
74
|
+
### Cache based on session/user
|
|
75
|
+
|
|
76
|
+
```ts
|
|
77
|
+
import { envelop } from '@envelop/core';
|
|
78
|
+
import { useResponseCache } from '@envelop/response-cache';
|
|
79
|
+
|
|
80
|
+
const getEnveloped = envelop({
|
|
81
|
+
plugins: [
|
|
82
|
+
// ... other plugins ...
|
|
83
|
+
useResponseCache({
|
|
84
|
+
ttl: 2000,
|
|
85
|
+
// context is the GraphQL context used for execution
|
|
86
|
+
session: context => String(context.user?.id),
|
|
87
|
+
}),
|
|
88
|
+
],
|
|
89
|
+
});
|
|
90
|
+
```
|
|
91
|
+
|
|
70
92
|
### Redis Cache
|
|
71
93
|
|
|
72
94
|
```bash
|
|
@@ -93,14 +115,17 @@ const redis = new Redis({
|
|
|
93
115
|
password: '1234567890',
|
|
94
116
|
});
|
|
95
117
|
|
|
96
|
-
const redis = new Redis(
|
|
118
|
+
const redis = new Redis('rediss://:1234567890@my-redis-db.example.com:30652');
|
|
97
119
|
|
|
98
120
|
const cache = createRedisCache({ redis });
|
|
99
121
|
|
|
100
122
|
const getEnveloped = envelop({
|
|
101
123
|
plugins: [
|
|
102
124
|
// ... other plugins ...
|
|
103
|
-
useResponseCache({
|
|
125
|
+
useResponseCache({
|
|
126
|
+
cache,
|
|
127
|
+
session: () => null, // use global cache for all operations
|
|
128
|
+
}),
|
|
104
129
|
],
|
|
105
130
|
});
|
|
106
131
|
```
|
|
@@ -120,6 +145,7 @@ const getEnveloped = envelop({
|
|
|
120
145
|
// ... other plugins ...
|
|
121
146
|
useResponseCache({
|
|
122
147
|
ttl: 2000, // cached execution results become stale after 2 seconds
|
|
148
|
+
session: () => null, // use global cache for all operations
|
|
123
149
|
}),
|
|
124
150
|
],
|
|
125
151
|
});
|
|
@@ -167,24 +193,6 @@ const getEnveloped = envelop({
|
|
|
167
193
|
});
|
|
168
194
|
```
|
|
169
195
|
|
|
170
|
-
### Cache based on session/user
|
|
171
|
-
|
|
172
|
-
```ts
|
|
173
|
-
import { envelop } from '@envelop/core';
|
|
174
|
-
import { useResponseCache } from '@envelop/response-cache';
|
|
175
|
-
|
|
176
|
-
const getEnveloped = envelop({
|
|
177
|
-
plugins: [
|
|
178
|
-
// ... other plugins ...
|
|
179
|
-
useResponseCache({
|
|
180
|
-
ttl: 2000,
|
|
181
|
-
// context is the GraphQL context used for execution
|
|
182
|
-
session: context => String(context.user?.id),
|
|
183
|
-
}),
|
|
184
|
-
],
|
|
185
|
-
});
|
|
186
|
-
```
|
|
187
|
-
|
|
188
196
|
### Disable cache based on session/user
|
|
189
197
|
|
|
190
198
|
```ts
|
|
@@ -198,6 +206,7 @@ const getEnveloped = envelop({
|
|
|
198
206
|
ttl: 2000,
|
|
199
207
|
// context is the GraphQL context used for execution
|
|
200
208
|
enabled: context => context.user?.role !== 'admin',
|
|
209
|
+
session: () => null,
|
|
201
210
|
}),
|
|
202
211
|
],
|
|
203
212
|
});
|
|
@@ -231,6 +240,7 @@ const getEnveloped = envelop({
|
|
|
231
240
|
// ... other plugins ...
|
|
232
241
|
useResponseCache({
|
|
233
242
|
shouldCacheResult = myCustomShouldCacheResult,
|
|
243
|
+
session: () => null,
|
|
234
244
|
}),
|
|
235
245
|
],
|
|
236
246
|
});
|
|
@@ -253,6 +263,7 @@ const getEnveloped = envelop({
|
|
|
253
263
|
ttlPerSchemaCoordinate: {
|
|
254
264
|
'Query.__schema': undefined, // cache infinitely
|
|
255
265
|
},
|
|
266
|
+
session: () => null,
|
|
256
267
|
}),
|
|
257
268
|
],
|
|
258
269
|
});
|
|
@@ -271,6 +282,7 @@ const getEnveloped = envelop({
|
|
|
271
282
|
ttlPerSchemaCoordinate: {
|
|
272
283
|
'Query.__schema': 10_000, // cache for 10 seconds
|
|
273
284
|
},
|
|
285
|
+
session: () => null,
|
|
274
286
|
}),
|
|
275
287
|
],
|
|
276
288
|
});
|
|
@@ -287,6 +299,7 @@ const getEnveloped = envelop({
|
|
|
287
299
|
// ... other plugins ...
|
|
288
300
|
useResponseCache({
|
|
289
301
|
ttl: 2000, // cached execution results become stale after 2 seconds
|
|
302
|
+
session: () => null,
|
|
290
303
|
}),
|
|
291
304
|
],
|
|
292
305
|
});
|
|
@@ -305,6 +318,7 @@ const getEnveloped = envelop({
|
|
|
305
318
|
ttl: 2000,
|
|
306
319
|
// use the `_id` instead of `id` field.
|
|
307
320
|
idFields: ['_id'],
|
|
321
|
+
session: () => null,
|
|
308
322
|
}),
|
|
309
323
|
],
|
|
310
324
|
});
|
|
@@ -323,6 +337,7 @@ const getEnveloped = envelop({
|
|
|
323
337
|
ttl: 2000,
|
|
324
338
|
// some might prefer invalidating based on a database write log
|
|
325
339
|
invalidateViaMutation: false,
|
|
340
|
+
session: () => null,
|
|
326
341
|
}),
|
|
327
342
|
],
|
|
328
343
|
});
|
|
@@ -345,6 +360,7 @@ const getEnveloped = envelop({
|
|
|
345
360
|
ttl: 2000,
|
|
346
361
|
// we pass the cache instance to the request.
|
|
347
362
|
cache,
|
|
363
|
+
session: () => null,
|
|
348
364
|
}),
|
|
349
365
|
],
|
|
350
366
|
});
|
|
@@ -379,6 +395,7 @@ const getEnveloped = envelop({
|
|
|
379
395
|
ttl: 2000,
|
|
380
396
|
// we pass the cache instance to the request.
|
|
381
397
|
cache,
|
|
398
|
+
session: () => null,
|
|
382
399
|
}),
|
|
383
400
|
],
|
|
384
401
|
});
|
|
@@ -395,6 +412,7 @@ const getEnveloped = envelop({
|
|
|
395
412
|
useResponseCache({
|
|
396
413
|
ttl: 2000,
|
|
397
414
|
includeExtensionMetadata: true,
|
|
415
|
+
session: () => null,
|
|
398
416
|
}),
|
|
399
417
|
],
|
|
400
418
|
});
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.defaultGetDocumentString = exports.useCacheDocumentString = void 0;
|
|
4
|
+
const graphql_1 = require("graphql");
|
|
5
|
+
const documentStringByDocument = new WeakMap();
|
|
6
|
+
function useCacheDocumentString() {
|
|
7
|
+
return {
|
|
8
|
+
onParse({ params: { source } }) {
|
|
9
|
+
return function onParseEnd({ result }) {
|
|
10
|
+
if (result != null && !(result instanceof Error)) {
|
|
11
|
+
documentStringByDocument.set(result, source.toString());
|
|
12
|
+
}
|
|
13
|
+
};
|
|
14
|
+
},
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
exports.useCacheDocumentString = useCacheDocumentString;
|
|
18
|
+
function defaultGetDocumentString(executionArgs) {
|
|
19
|
+
let documentString = documentStringByDocument.get(executionArgs.document);
|
|
20
|
+
if (documentString == null) {
|
|
21
|
+
documentString = (0, graphql_1.print)(executionArgs.document);
|
|
22
|
+
documentStringByDocument.set(executionArgs.document, documentString);
|
|
23
|
+
}
|
|
24
|
+
return documentString;
|
|
25
|
+
}
|
|
26
|
+
exports.defaultGetDocumentString = defaultGetDocumentString;
|
package/cjs/plugin.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.useResponseCache = exports.
|
|
3
|
+
exports.useResponseCache = exports.defaultShouldCacheResult = exports.defaultBuildResponseCacheKey = void 0;
|
|
4
4
|
const tslib_1 = require("tslib");
|
|
5
5
|
const core_1 = require("@envelop/core");
|
|
6
6
|
const utils_1 = require("@graphql-tools/utils");
|
|
@@ -8,6 +8,7 @@ const graphql_1 = require("graphql");
|
|
|
8
8
|
const fast_json_stable_stringify_1 = tslib_1.__importDefault(require("fast-json-stable-stringify"));
|
|
9
9
|
const in_memory_cache_js_1 = require("./in-memory-cache.js");
|
|
10
10
|
const hashSHA256_js_1 = require("./hashSHA256.js");
|
|
11
|
+
const cache_document_str_js_1 = require("./cache-document-str.js");
|
|
11
12
|
const contextSymbol = Symbol('responseCache');
|
|
12
13
|
/**
|
|
13
14
|
* Default function used for building the response cache key.
|
|
@@ -40,24 +41,19 @@ const defaultShouldCacheResult = (params) => {
|
|
|
40
41
|
return true;
|
|
41
42
|
};
|
|
42
43
|
exports.defaultShouldCacheResult = defaultShouldCacheResult;
|
|
43
|
-
|
|
44
|
-
function defaultGetDocumentString(executionArgs) {
|
|
45
|
-
let documentString = documentStringByDocument.get(executionArgs.document);
|
|
46
|
-
if (!documentString) {
|
|
47
|
-
documentString = (0, graphql_1.print)(executionArgs.document);
|
|
48
|
-
documentStringByDocument.set(executionArgs.document, documentString);
|
|
49
|
-
}
|
|
50
|
-
return documentString;
|
|
51
|
-
}
|
|
52
|
-
exports.defaultGetDocumentString = defaultGetDocumentString;
|
|
53
|
-
function useResponseCache({ cache = (0, in_memory_cache_js_1.createInMemoryCache)(), ttl: globalTtl = Infinity, session = () => null, enabled, ignoredTypes = [], ttlPerType = {}, ttlPerSchemaCoordinate = {}, idFields = ['id'], invalidateViaMutation = true, buildResponseCacheKey = exports.defaultBuildResponseCacheKey, getDocumentString = defaultGetDocumentString, shouldCacheResult = exports.defaultShouldCacheResult,
|
|
44
|
+
function useResponseCache({ cache = (0, in_memory_cache_js_1.createInMemoryCache)(), ttl: globalTtl = Infinity, session, enabled, ignoredTypes = [], ttlPerType = {}, ttlPerSchemaCoordinate = {}, idFields = ['id'], invalidateViaMutation = true, buildResponseCacheKey = exports.defaultBuildResponseCacheKey, getDocumentString = cache_document_str_js_1.defaultGetDocumentString, shouldCacheResult = exports.defaultShouldCacheResult,
|
|
54
45
|
// eslint-disable-next-line dot-notation
|
|
55
|
-
includeExtensionMetadata = typeof process !== 'undefined' ? process.env['NODE_ENV'] === 'development' : false, }
|
|
46
|
+
includeExtensionMetadata = typeof process !== 'undefined' ? process.env['NODE_ENV'] === 'development' : false, }) {
|
|
56
47
|
const appliedTransform = Symbol('responseCache.appliedTransform');
|
|
57
48
|
const ignoredTypesMap = new Set(ignoredTypes);
|
|
58
49
|
// never cache Introspections
|
|
59
50
|
ttlPerSchemaCoordinate = { 'Query.__schema': 0, ...ttlPerSchemaCoordinate };
|
|
60
51
|
return {
|
|
52
|
+
onPluginInit({ addPlugin }) {
|
|
53
|
+
if (getDocumentString === cache_document_str_js_1.defaultGetDocumentString) {
|
|
54
|
+
addPlugin((0, cache_document_str_js_1.useCacheDocumentString)());
|
|
55
|
+
}
|
|
56
|
+
},
|
|
61
57
|
onSchemaChange({ schema, replaceSchema }) {
|
|
62
58
|
var _a;
|
|
63
59
|
// @ts-expect-error See https://github.com/graphql/graphql-js/pull/3511 - remove this comments once merged
|
|
@@ -71,13 +67,6 @@ includeExtensionMetadata = typeof process !== 'undefined' ? process.env['NODE_EN
|
|
|
71
67
|
};
|
|
72
68
|
replaceSchema(patchedSchema);
|
|
73
69
|
},
|
|
74
|
-
onParse({ params: { source } }) {
|
|
75
|
-
return function onParseEnd({ result }) {
|
|
76
|
-
if (result != null && !(result instanceof Error)) {
|
|
77
|
-
documentStringByDocument.set(result, source.toString());
|
|
78
|
-
}
|
|
79
|
-
};
|
|
80
|
-
},
|
|
81
70
|
async onExecute(ctx) {
|
|
82
71
|
var _a;
|
|
83
72
|
const identifier = new Map();
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { print } from 'graphql';
|
|
2
|
+
const documentStringByDocument = new WeakMap();
|
|
3
|
+
export function useCacheDocumentString() {
|
|
4
|
+
return {
|
|
5
|
+
onParse({ params: { source } }) {
|
|
6
|
+
return function onParseEnd({ result }) {
|
|
7
|
+
if (result != null && !(result instanceof Error)) {
|
|
8
|
+
documentStringByDocument.set(result, source.toString());
|
|
9
|
+
}
|
|
10
|
+
};
|
|
11
|
+
},
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
export function defaultGetDocumentString(executionArgs) {
|
|
15
|
+
let documentString = documentStringByDocument.get(executionArgs.document);
|
|
16
|
+
if (documentString == null) {
|
|
17
|
+
documentString = print(executionArgs.document);
|
|
18
|
+
documentStringByDocument.set(executionArgs.document, documentString);
|
|
19
|
+
}
|
|
20
|
+
return documentString;
|
|
21
|
+
}
|
package/esm/plugin.js
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { isAsyncIterable } from '@envelop/core';
|
|
2
2
|
import { MapperKind, mapSchema } from '@graphql-tools/utils';
|
|
3
|
-
import { visit, TypeInfo, visitWithTypeInfo, defaultFieldResolver,
|
|
3
|
+
import { visit, TypeInfo, visitWithTypeInfo, defaultFieldResolver, } from 'graphql';
|
|
4
4
|
import jsonStableStringify from 'fast-json-stable-stringify';
|
|
5
5
|
import { createInMemoryCache } from './in-memory-cache.js';
|
|
6
6
|
import { hashSHA256 } from './hashSHA256.js';
|
|
7
|
+
import { defaultGetDocumentString, useCacheDocumentString } from './cache-document-str.js';
|
|
7
8
|
const contextSymbol = Symbol('responseCache');
|
|
8
9
|
/**
|
|
9
10
|
* Default function used for building the response cache key.
|
|
@@ -34,23 +35,19 @@ export const defaultShouldCacheResult = (params) => {
|
|
|
34
35
|
}
|
|
35
36
|
return true;
|
|
36
37
|
};
|
|
37
|
-
|
|
38
|
-
export function defaultGetDocumentString(executionArgs) {
|
|
39
|
-
let documentString = documentStringByDocument.get(executionArgs.document);
|
|
40
|
-
if (!documentString) {
|
|
41
|
-
documentString = print(executionArgs.document);
|
|
42
|
-
documentStringByDocument.set(executionArgs.document, documentString);
|
|
43
|
-
}
|
|
44
|
-
return documentString;
|
|
45
|
-
}
|
|
46
|
-
export function useResponseCache({ cache = createInMemoryCache(), ttl: globalTtl = Infinity, session = () => null, enabled, ignoredTypes = [], ttlPerType = {}, ttlPerSchemaCoordinate = {}, idFields = ['id'], invalidateViaMutation = true, buildResponseCacheKey = defaultBuildResponseCacheKey, getDocumentString = defaultGetDocumentString, shouldCacheResult = defaultShouldCacheResult,
|
|
38
|
+
export function useResponseCache({ cache = createInMemoryCache(), ttl: globalTtl = Infinity, session, enabled, ignoredTypes = [], ttlPerType = {}, ttlPerSchemaCoordinate = {}, idFields = ['id'], invalidateViaMutation = true, buildResponseCacheKey = defaultBuildResponseCacheKey, getDocumentString = defaultGetDocumentString, shouldCacheResult = defaultShouldCacheResult,
|
|
47
39
|
// eslint-disable-next-line dot-notation
|
|
48
|
-
includeExtensionMetadata = typeof process !== 'undefined' ? process.env['NODE_ENV'] === 'development' : false, }
|
|
40
|
+
includeExtensionMetadata = typeof process !== 'undefined' ? process.env['NODE_ENV'] === 'development' : false, }) {
|
|
49
41
|
const appliedTransform = Symbol('responseCache.appliedTransform');
|
|
50
42
|
const ignoredTypesMap = new Set(ignoredTypes);
|
|
51
43
|
// never cache Introspections
|
|
52
44
|
ttlPerSchemaCoordinate = { 'Query.__schema': 0, ...ttlPerSchemaCoordinate };
|
|
53
45
|
return {
|
|
46
|
+
onPluginInit({ addPlugin }) {
|
|
47
|
+
if (getDocumentString === defaultGetDocumentString) {
|
|
48
|
+
addPlugin(useCacheDocumentString());
|
|
49
|
+
}
|
|
50
|
+
},
|
|
54
51
|
onSchemaChange({ schema, replaceSchema }) {
|
|
55
52
|
var _a;
|
|
56
53
|
// @ts-expect-error See https://github.com/graphql/graphql-js/pull/3511 - remove this comments once merged
|
|
@@ -64,13 +61,6 @@ includeExtensionMetadata = typeof process !== 'undefined' ? process.env['NODE_EN
|
|
|
64
61
|
};
|
|
65
62
|
replaceSchema(patchedSchema);
|
|
66
63
|
},
|
|
67
|
-
onParse({ params: { source } }) {
|
|
68
|
-
return function onParseEnd({ result }) {
|
|
69
|
-
if (result != null && !(result instanceof Error)) {
|
|
70
|
-
documentStringByDocument.set(result, source.toString());
|
|
71
|
-
}
|
|
72
|
-
};
|
|
73
|
-
},
|
|
74
64
|
async onExecute(ctx) {
|
|
75
65
|
var _a;
|
|
76
66
|
const identifier = new Map();
|
package/package.json
CHANGED
package/typings/plugin.d.ts
CHANGED
|
@@ -12,7 +12,7 @@ export declare type BuildResponseCacheKeyFunction = (params: {
|
|
|
12
12
|
/** The name of the GraphQL operation that should be executed from within the document. */
|
|
13
13
|
operationName?: Maybe<string>;
|
|
14
14
|
/** optional sessionId for make unique cache keys based on the session. */
|
|
15
|
-
sessionId
|
|
15
|
+
sessionId: Maybe<string>;
|
|
16
16
|
}) => Promise<string>;
|
|
17
17
|
export declare type GetDocumentStringFunction = (executionArgs: ExecutionArgs) => string;
|
|
18
18
|
export declare type ShouldCacheResultFunction = (params: {
|
|
@@ -46,7 +46,7 @@ export declare type UseResponseCacheParameter<C = any> = {
|
|
|
46
46
|
* Creates a global session by default.
|
|
47
47
|
* @param context GraphQL Context
|
|
48
48
|
*/
|
|
49
|
-
session
|
|
49
|
+
session(context: C): string | undefined | null;
|
|
50
50
|
/**
|
|
51
51
|
* Specify whether the cache should be used based on the context.
|
|
52
52
|
* By default any request uses the cache.
|
|
@@ -105,5 +105,4 @@ export declare const defaultBuildResponseCacheKey: BuildResponseCacheKeyFunction
|
|
|
105
105
|
* By default, results with errors (unexpected, EnvelopError, or GraphQLError) are not cached.
|
|
106
106
|
*/
|
|
107
107
|
export declare const defaultShouldCacheResult: ShouldCacheResultFunction;
|
|
108
|
-
export declare function
|
|
109
|
-
export declare function useResponseCache({ cache, ttl: globalTtl, session, enabled, ignoredTypes, ttlPerType, ttlPerSchemaCoordinate, idFields, invalidateViaMutation, buildResponseCacheKey, getDocumentString, shouldCacheResult, includeExtensionMetadata, }?: UseResponseCacheParameter): Plugin;
|
|
108
|
+
export declare function useResponseCache({ cache, ttl: globalTtl, session, enabled, ignoredTypes, ttlPerType, ttlPerSchemaCoordinate, idFields, invalidateViaMutation, buildResponseCacheKey, getDocumentString, shouldCacheResult, includeExtensionMetadata, }: UseResponseCacheParameter): Plugin;
|