@envelop/response-cache 3.0.0-alpha-868cc42.0 → 3.0.0-alpha-9dd2d31.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/cjs/cache.js ADDED
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,66 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.hashSHA256 = void 0;
4
+ const webCrypto = globalThis.crypto;
5
+ const sha256Browser = (bytes) => {
6
+ const hash = webCrypto.subtle.digest({ name: 'SHA-256' }, bytes);
7
+ return new Promise((resolve, reject) => {
8
+ Promise.resolve(hash)
9
+ .then(function (result) {
10
+ resolve(new Uint8Array(result));
11
+ })
12
+ .catch(function (error) {
13
+ reject(error);
14
+ });
15
+ });
16
+ };
17
+ let nodeCrypto;
18
+ if (typeof window === 'undefined' && !webCrypto) {
19
+ // Indirect eval'd require/import to guarantee no side-effects in module scope
20
+ // (optimization for minifier)
21
+ try {
22
+ // eslint-disable-next-line no-new-func
23
+ nodeCrypto = Promise.resolve(new Function('require', 'return require("crypto")')(require));
24
+ }
25
+ catch (_error) {
26
+ try {
27
+ // eslint-disable-next-line no-new-func
28
+ nodeCrypto = new Function('return import("crypto")')();
29
+ }
30
+ catch (_error) { }
31
+ }
32
+ }
33
+ const hashSHA256 = async (text) => {
34
+ // Node.js support
35
+ if (nodeCrypto) {
36
+ return nodeCrypto.then(crypto => crypto.createHash('sha256').update(text).digest('hex'));
37
+ }
38
+ if (webCrypto) {
39
+ let buf;
40
+ if (typeof TextEncoder !== 'undefined') {
41
+ buf = new TextEncoder().encode(text);
42
+ }
43
+ else {
44
+ buf = new Uint8Array(text.length);
45
+ for (let i = 0, l = text.length; i < l; i++) {
46
+ // NOTE: We assume that the input GraphQL Query only uses UTF-8 at most
47
+ // since GraphQL mostly consists of ASCII, this is completely fine
48
+ buf[i] = text.charCodeAt(i);
49
+ }
50
+ }
51
+ const out = await sha256Browser(buf);
52
+ let hash = '';
53
+ for (let i = 0, l = out.length; i < l; i++) {
54
+ const hex = out[i].toString(16);
55
+ hash += '00'.slice(0, Math.max(0, 2 - hex.length)) + hex;
56
+ }
57
+ return hash;
58
+ }
59
+ if (process.env.NODE_ENV !== 'production') {
60
+ // eslint-disable-next-line no-console
61
+ console.warn('[@envelop/response-cache]: The Node Crypto and Web Crypto APIs are not available.\n' +
62
+ 'This is an unexpected error. Please report it by filing a GitHub Issue.');
63
+ }
64
+ return Promise.resolve('');
65
+ };
66
+ exports.hashSHA256 = hashSHA256;
@@ -0,0 +1,86 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.defaultBuildEntityId = exports.createInMemoryCache = void 0;
4
+ const tslib_1 = require("tslib");
5
+ const lru_cache_1 = tslib_1.__importDefault(require("lru-cache"));
6
+ const createInMemoryCache = (params) => {
7
+ var _a;
8
+ const buildEntityId = (_a = params === null || params === void 0 ? void 0 : params.buildEntityId) !== null && _a !== void 0 ? _a : exports.defaultBuildEntityId;
9
+ const cachedResponses = new lru_cache_1.default({
10
+ max: params === null || params === void 0 ? void 0 : params.max,
11
+ stale: false,
12
+ noDisposeOnSet: true,
13
+ dispose(responseId) {
14
+ purgeResponse(responseId, false);
15
+ },
16
+ });
17
+ const entityToResponseIds = new Map();
18
+ const responseIdToEntityIds = new Map();
19
+ function purgeResponse(responseId, shouldRemove = true) {
20
+ var _a;
21
+ const entityIds = responseIdToEntityIds.get(responseId);
22
+ // get entities related to the response
23
+ if (entityIds !== undefined) {
24
+ for (const entityId of entityIds) {
25
+ // remove the response mapping from the entity
26
+ (_a = entityToResponseIds.get(entityId)) === null || _a === void 0 ? void 0 : _a.delete(responseId);
27
+ }
28
+ // remove all the entity mappings from the response
29
+ responseIdToEntityIds.delete(responseId);
30
+ }
31
+ if (shouldRemove) {
32
+ // remove the response from the cache
33
+ cachedResponses.del(responseId);
34
+ }
35
+ }
36
+ function purgeEntity(entity) {
37
+ const responseIds = entityToResponseIds.get(entity);
38
+ if (responseIds !== undefined) {
39
+ for (const responseId of responseIds) {
40
+ purgeResponse(responseId);
41
+ }
42
+ }
43
+ }
44
+ return {
45
+ set(responseId, result, collectedEntities, ttl) {
46
+ cachedResponses.set(responseId, result, ttl);
47
+ const entityIds = new Set();
48
+ responseIdToEntityIds.set(responseId, entityIds);
49
+ for (const { typename, id } of collectedEntities) {
50
+ let operationIds = entityToResponseIds.get(typename);
51
+ if (operationIds == null) {
52
+ operationIds = new Set();
53
+ entityToResponseIds.set(typename, operationIds);
54
+ }
55
+ // typename => operation
56
+ operationIds.add(responseId);
57
+ // operation => typename
58
+ entityIds.add(typename);
59
+ if (id !== undefined) {
60
+ const entityId = buildEntityId(typename, id);
61
+ let responseIds = entityToResponseIds.get(entityId);
62
+ if (responseIds == null) {
63
+ responseIds = new Set();
64
+ entityToResponseIds.set(entityId, responseIds);
65
+ }
66
+ // typename:id => operation
67
+ responseIds.add(responseId);
68
+ // operation => typename:id
69
+ entityIds.add(entityId);
70
+ }
71
+ }
72
+ },
73
+ get(responseId) {
74
+ var _a;
75
+ return (_a = cachedResponses.get(responseId)) !== null && _a !== void 0 ? _a : null;
76
+ },
77
+ invalidate(entitiesToRemove) {
78
+ for (const { typename, id } of entitiesToRemove) {
79
+ purgeEntity(id != null ? buildEntityId(typename, id) : typename);
80
+ }
81
+ },
82
+ };
83
+ };
84
+ exports.createInMemoryCache = createInMemoryCache;
85
+ const defaultBuildEntityId = (typename, id) => `${typename}:${id}`;
86
+ exports.defaultBuildEntityId = defaultBuildEntityId;
package/cjs/index.js ADDED
@@ -0,0 +1,6 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const tslib_1 = require("tslib");
4
+ tslib_1.__exportStar(require("./in-memory-cache.js"), exports);
5
+ tslib_1.__exportStar(require("./plugin.js"), exports);
6
+ tslib_1.__exportStar(require("./cache.js"), exports);
@@ -0,0 +1 @@
1
+ {"type":"commonjs"}
@@ -1,158 +1,13 @@
1
- 'use strict';
2
-
3
- Object.defineProperty(exports, '__esModule', { value: true });
4
-
5
- function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; }
6
-
7
- const LRU = _interopDefault(require('lru-cache'));
8
- const core = require('@envelop/core');
9
- const utils = require('@graphql-tools/utils');
10
- const graphql = require('graphql');
11
- const jsonStableStringify = _interopDefault(require('fast-json-stable-stringify'));
12
-
13
- const createInMemoryCache = (params) => {
14
- var _a;
15
- const buildEntityId = (_a = params === null || params === void 0 ? void 0 : params.buildEntityId) !== null && _a !== void 0 ? _a : defaultBuildEntityId;
16
- const cachedResponses = new LRU({
17
- max: params === null || params === void 0 ? void 0 : params.max,
18
- stale: false,
19
- noDisposeOnSet: true,
20
- dispose(responseId) {
21
- purgeResponse(responseId, false);
22
- },
23
- });
24
- const entityToResponseIds = new Map();
25
- const responseIdToEntityIds = new Map();
26
- function purgeResponse(responseId, shouldRemove = true) {
27
- var _a;
28
- const entityIds = responseIdToEntityIds.get(responseId);
29
- // get entities related to the response
30
- if (entityIds !== undefined) {
31
- for (const entityId of entityIds) {
32
- // remove the response mapping from the entity
33
- (_a = entityToResponseIds.get(entityId)) === null || _a === void 0 ? void 0 : _a.delete(responseId);
34
- }
35
- // remove all the entity mappings from the response
36
- responseIdToEntityIds.delete(responseId);
37
- }
38
- if (shouldRemove) {
39
- // remove the response from the cache
40
- cachedResponses.del(responseId);
41
- }
42
- }
43
- function purgeEntity(entity) {
44
- const responseIds = entityToResponseIds.get(entity);
45
- if (responseIds !== undefined) {
46
- for (const responseId of responseIds) {
47
- purgeResponse(responseId);
48
- }
49
- }
50
- }
51
- return {
52
- set(responseId, result, collectedEntities, ttl) {
53
- cachedResponses.set(responseId, result, ttl);
54
- const entityIds = new Set();
55
- responseIdToEntityIds.set(responseId, entityIds);
56
- for (const { typename, id } of collectedEntities) {
57
- let operationIds = entityToResponseIds.get(typename);
58
- if (operationIds == null) {
59
- operationIds = new Set();
60
- entityToResponseIds.set(typename, operationIds);
61
- }
62
- // typename => operation
63
- operationIds.add(responseId);
64
- // operation => typename
65
- entityIds.add(typename);
66
- if (id !== undefined) {
67
- const entityId = buildEntityId(typename, id);
68
- let responseIds = entityToResponseIds.get(entityId);
69
- if (responseIds == null) {
70
- responseIds = new Set();
71
- entityToResponseIds.set(entityId, responseIds);
72
- }
73
- // typename:id => operation
74
- responseIds.add(responseId);
75
- // operation => typename:id
76
- entityIds.add(entityId);
77
- }
78
- }
79
- },
80
- get(responseId) {
81
- var _a;
82
- return (_a = cachedResponses.get(responseId)) !== null && _a !== void 0 ? _a : null;
83
- },
84
- invalidate(entitiesToRemove) {
85
- for (const { typename, id } of entitiesToRemove) {
86
- purgeEntity(id != null ? buildEntityId(typename, id) : typename);
87
- }
88
- },
89
- };
90
- };
91
- const defaultBuildEntityId = (typename, id) => `${typename}:${id}`;
92
-
93
- const webCrypto = globalThis.crypto;
94
- const sha256Browser = (bytes) => {
95
- const hash = webCrypto.subtle.digest({ name: 'SHA-256' }, bytes);
96
- return new Promise((resolve, reject) => {
97
- Promise.resolve(hash)
98
- .then(function (result) {
99
- resolve(new Uint8Array(result));
100
- })
101
- .catch(function (error) {
102
- reject(error);
103
- });
104
- });
105
- };
106
- let nodeCrypto;
107
- if (typeof window === 'undefined' && !webCrypto) {
108
- // Indirect eval'd require/import to guarantee no side-effects in module scope
109
- // (optimization for minifier)
110
- try {
111
- // eslint-disable-next-line no-new-func
112
- nodeCrypto = Promise.resolve(new Function('require', 'return require("crypto")')(require));
113
- }
114
- catch (_error) {
115
- try {
116
- // eslint-disable-next-line no-new-func
117
- nodeCrypto = new Function('return import("crypto")')();
118
- }
119
- catch (_error) { }
120
- }
121
- }
122
- const hashSHA256 = async (text) => {
123
- // Node.js support
124
- if (nodeCrypto) {
125
- return nodeCrypto.then(crypto => crypto.createHash('sha256').update(text).digest('hex'));
126
- }
127
- if (webCrypto) {
128
- let buf;
129
- if (typeof TextEncoder !== 'undefined') {
130
- buf = new TextEncoder().encode(text);
131
- }
132
- else {
133
- buf = new Uint8Array(text.length);
134
- for (let i = 0, l = text.length; i < l; i++) {
135
- // NOTE: We assume that the input GraphQL Query only uses UTF-8 at most
136
- // since GraphQL mostly consists of ASCII, this is completely fine
137
- buf[i] = text.charCodeAt(i);
138
- }
139
- }
140
- const out = await sha256Browser(buf);
141
- let hash = '';
142
- for (let i = 0, l = out.length; i < l; i++) {
143
- const hex = out[i].toString(16);
144
- hash += '00'.slice(0, Math.max(0, 2 - hex.length)) + hex;
145
- }
146
- return hash;
147
- }
148
- if (process.env.NODE_ENV !== 'production') {
149
- // eslint-disable-next-line no-console
150
- console.warn('[@envelop/response-cache]: The Node Crypto and Web Crypto APIs are not available.\n' +
151
- 'This is an unexpected error. Please report it by filing a GitHub Issue.');
152
- }
153
- return Promise.resolve('');
154
- };
155
-
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.useResponseCache = exports.defaultGetDocumentString = exports.defaultShouldCacheResult = exports.defaultBuildResponseCacheKey = void 0;
4
+ const tslib_1 = require("tslib");
5
+ const core_1 = require("@envelop/core");
6
+ const utils_1 = require("@graphql-tools/utils");
7
+ const graphql_1 = require("graphql");
8
+ const fast_json_stable_stringify_1 = tslib_1.__importDefault(require("fast-json-stable-stringify"));
9
+ const in_memory_cache_js_1 = require("./in-memory-cache.js");
10
+ const hashSHA256_js_1 = require("./hashSHA256.js");
156
11
  const contextSymbol = Symbol('responseCache');
157
12
  /**
158
13
  * Default function used for building the response cache key.
@@ -160,13 +15,14 @@ const contextSymbol = Symbol('responseCache');
160
15
  */
161
16
  const defaultBuildResponseCacheKey = params => {
162
17
  var _a, _b, _c;
163
- return hashSHA256([
18
+ return (0, hashSHA256_js_1.hashSHA256)([
164
19
  params.documentString,
165
20
  (_a = params.operationName) !== null && _a !== void 0 ? _a : '',
166
- jsonStableStringify((_b = params.variableValues) !== null && _b !== void 0 ? _b : {}),
21
+ (0, fast_json_stable_stringify_1.default)((_b = params.variableValues) !== null && _b !== void 0 ? _b : {}),
167
22
  (_c = params.sessionId) !== null && _c !== void 0 ? _c : '',
168
23
  ].join('|'));
169
24
  };
25
+ exports.defaultBuildResponseCacheKey = defaultBuildResponseCacheKey;
170
26
  /**
171
27
  * Default function used to check if the result should be cached.
172
28
  *
@@ -183,16 +39,18 @@ const defaultShouldCacheResult = (params) => {
183
39
  }
184
40
  return true;
185
41
  };
42
+ exports.defaultShouldCacheResult = defaultShouldCacheResult;
186
43
  const documentStringByDocument = new WeakMap();
187
44
  function defaultGetDocumentString(executionArgs) {
188
45
  let documentString = documentStringByDocument.get(executionArgs.document);
189
46
  if (!documentString) {
190
- documentString = graphql.print(executionArgs.document);
47
+ documentString = (0, graphql_1.print)(executionArgs.document);
191
48
  documentStringByDocument.set(executionArgs.document, documentString);
192
49
  }
193
50
  return documentString;
194
51
  }
195
- function useResponseCache({ cache = createInMemoryCache(), ttl: globalTtl = Infinity, session = () => null, enabled, ignoredTypes = [], ttlPerType = {}, ttlPerSchemaCoordinate = {}, idFields = ['id'], invalidateViaMutation = true, buildResponseCacheKey = defaultBuildResponseCacheKey, getDocumentString = defaultGetDocumentString, shouldCacheResult = defaultShouldCacheResult,
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,
196
54
  // eslint-disable-next-line dot-notation
197
55
  includeExtensionMetadata = typeof process !== 'undefined' ? process.env['NODE_ENV'] === 'development' : false, } = {}) {
198
56
  const appliedTransform = Symbol('responseCache.appliedTransform');
@@ -241,7 +99,7 @@ includeExtensionMetadata = typeof process !== 'undefined' ? process.env['NODE_EN
241
99
  }
242
100
  return {
243
101
  onExecuteDone({ result, setResult }) {
244
- if (core.isAsyncIterable(result)) {
102
+ if ((0, core_1.isAsyncIterable)(result)) {
245
103
  // eslint-disable-next-line no-console
246
104
  console.warn('[useResponseCache] AsyncIterable returned from execute is currently unsupported.');
247
105
  return;
@@ -287,8 +145,8 @@ includeExtensionMetadata = typeof process !== 'undefined' ? process.env['NODE_EN
287
145
  }
288
146
  }
289
147
  if (ttlPerSchemaCoordinate) {
290
- const typeInfo = new graphql.TypeInfo(ctx.args.schema);
291
- graphql.visit(ctx.args.document, graphql.visitWithTypeInfo(typeInfo, {
148
+ const typeInfo = new graphql_1.TypeInfo(ctx.args.schema);
149
+ (0, graphql_1.visit)(ctx.args.document, (0, graphql_1.visitWithTypeInfo)(typeInfo, {
292
150
  Field(fieldNode) {
293
151
  const parentType = typeInfo.getParentType();
294
152
  if (parentType) {
@@ -304,7 +162,7 @@ includeExtensionMetadata = typeof process !== 'undefined' ? process.env['NODE_EN
304
162
  return {
305
163
  onExecuteDone({ result, setResult }) {
306
164
  var _a;
307
- if (core.isAsyncIterable(result)) {
165
+ if ((0, core_1.isAsyncIterable)(result)) {
308
166
  // eslint-disable-next-line no-console
309
167
  console.warn('[useResponseCache] AsyncIterable returned from execute is currently unsupported.');
310
168
  return;
@@ -349,6 +207,7 @@ includeExtensionMetadata = typeof process !== 'undefined' ? process.env['NODE_EN
349
207
  },
350
208
  };
351
209
  }
210
+ exports.useResponseCache = useResponseCache;
352
211
  function isOperationDefinition(node) {
353
212
  return (node === null || node === void 0 ? void 0 : node.kind) === 'OperationDefinition';
354
213
  }
@@ -370,14 +229,14 @@ function runWith(input, callback) {
370
229
  }
371
230
  }
372
231
  function applyResponseCacheLogic(schema, idFieldNames) {
373
- return utils.mapSchema(schema, {
374
- [utils.MapperKind.OBJECT_FIELD](fieldConfig, fieldName, typename) {
232
+ return (0, utils_1.mapSchema)(schema, {
233
+ [utils_1.MapperKind.OBJECT_FIELD](fieldConfig, fieldName, typename) {
375
234
  if (idFieldNames.includes(fieldName)) {
376
235
  return {
377
236
  ...fieldConfig,
378
237
  resolve(src, args, context, info) {
379
238
  var _a;
380
- const result = ((_a = fieldConfig.resolve) !== null && _a !== void 0 ? _a : graphql.defaultFieldResolver)(src, args, context, info);
239
+ const result = ((_a = fieldConfig.resolve) !== null && _a !== void 0 ? _a : graphql_1.defaultFieldResolver)(src, args, context, info);
381
240
  runWith(result, (id) => {
382
241
  const ctx = context[contextSymbol];
383
242
  if (ctx !== undefined) {
@@ -405,10 +264,3 @@ function applyResponseCacheLogic(schema, idFieldNames) {
405
264
  },
406
265
  });
407
266
  }
408
-
409
- exports.createInMemoryCache = createInMemoryCache;
410
- exports.defaultBuildEntityId = defaultBuildEntityId;
411
- exports.defaultBuildResponseCacheKey = defaultBuildResponseCacheKey;
412
- exports.defaultGetDocumentString = defaultGetDocumentString;
413
- exports.defaultShouldCacheResult = defaultShouldCacheResult;
414
- exports.useResponseCache = useResponseCache;
package/esm/cache.js ADDED
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,62 @@
1
+ const webCrypto = globalThis.crypto;
2
+ const sha256Browser = (bytes) => {
3
+ const hash = webCrypto.subtle.digest({ name: 'SHA-256' }, bytes);
4
+ return new Promise((resolve, reject) => {
5
+ Promise.resolve(hash)
6
+ .then(function (result) {
7
+ resolve(new Uint8Array(result));
8
+ })
9
+ .catch(function (error) {
10
+ reject(error);
11
+ });
12
+ });
13
+ };
14
+ let nodeCrypto;
15
+ if (typeof window === 'undefined' && !webCrypto) {
16
+ // Indirect eval'd require/import to guarantee no side-effects in module scope
17
+ // (optimization for minifier)
18
+ try {
19
+ // eslint-disable-next-line no-new-func
20
+ nodeCrypto = Promise.resolve(new Function('require', 'return require("crypto")')(require));
21
+ }
22
+ catch (_error) {
23
+ try {
24
+ // eslint-disable-next-line no-new-func
25
+ nodeCrypto = new Function('return import("crypto")')();
26
+ }
27
+ catch (_error) { }
28
+ }
29
+ }
30
+ export const hashSHA256 = async (text) => {
31
+ // Node.js support
32
+ if (nodeCrypto) {
33
+ return nodeCrypto.then(crypto => crypto.createHash('sha256').update(text).digest('hex'));
34
+ }
35
+ if (webCrypto) {
36
+ let buf;
37
+ if (typeof TextEncoder !== 'undefined') {
38
+ buf = new TextEncoder().encode(text);
39
+ }
40
+ else {
41
+ buf = new Uint8Array(text.length);
42
+ for (let i = 0, l = text.length; i < l; i++) {
43
+ // NOTE: We assume that the input GraphQL Query only uses UTF-8 at most
44
+ // since GraphQL mostly consists of ASCII, this is completely fine
45
+ buf[i] = text.charCodeAt(i);
46
+ }
47
+ }
48
+ const out = await sha256Browser(buf);
49
+ let hash = '';
50
+ for (let i = 0, l = out.length; i < l; i++) {
51
+ const hex = out[i].toString(16);
52
+ hash += '00'.slice(0, Math.max(0, 2 - hex.length)) + hex;
53
+ }
54
+ return hash;
55
+ }
56
+ if (process.env.NODE_ENV !== 'production') {
57
+ // eslint-disable-next-line no-console
58
+ console.warn('[@envelop/response-cache]: The Node Crypto and Web Crypto APIs are not available.\n' +
59
+ 'This is an unexpected error. Please report it by filing a GitHub Issue.');
60
+ }
61
+ return Promise.resolve('');
62
+ };
@@ -0,0 +1,80 @@
1
+ import LRU from 'lru-cache';
2
+ export const createInMemoryCache = (params) => {
3
+ var _a;
4
+ const buildEntityId = (_a = params === null || params === void 0 ? void 0 : params.buildEntityId) !== null && _a !== void 0 ? _a : defaultBuildEntityId;
5
+ const cachedResponses = new LRU({
6
+ max: params === null || params === void 0 ? void 0 : params.max,
7
+ stale: false,
8
+ noDisposeOnSet: true,
9
+ dispose(responseId) {
10
+ purgeResponse(responseId, false);
11
+ },
12
+ });
13
+ const entityToResponseIds = new Map();
14
+ const responseIdToEntityIds = new Map();
15
+ function purgeResponse(responseId, shouldRemove = true) {
16
+ var _a;
17
+ const entityIds = responseIdToEntityIds.get(responseId);
18
+ // get entities related to the response
19
+ if (entityIds !== undefined) {
20
+ for (const entityId of entityIds) {
21
+ // remove the response mapping from the entity
22
+ (_a = entityToResponseIds.get(entityId)) === null || _a === void 0 ? void 0 : _a.delete(responseId);
23
+ }
24
+ // remove all the entity mappings from the response
25
+ responseIdToEntityIds.delete(responseId);
26
+ }
27
+ if (shouldRemove) {
28
+ // remove the response from the cache
29
+ cachedResponses.del(responseId);
30
+ }
31
+ }
32
+ function purgeEntity(entity) {
33
+ const responseIds = entityToResponseIds.get(entity);
34
+ if (responseIds !== undefined) {
35
+ for (const responseId of responseIds) {
36
+ purgeResponse(responseId);
37
+ }
38
+ }
39
+ }
40
+ return {
41
+ set(responseId, result, collectedEntities, ttl) {
42
+ cachedResponses.set(responseId, result, ttl);
43
+ const entityIds = new Set();
44
+ responseIdToEntityIds.set(responseId, entityIds);
45
+ for (const { typename, id } of collectedEntities) {
46
+ let operationIds = entityToResponseIds.get(typename);
47
+ if (operationIds == null) {
48
+ operationIds = new Set();
49
+ entityToResponseIds.set(typename, operationIds);
50
+ }
51
+ // typename => operation
52
+ operationIds.add(responseId);
53
+ // operation => typename
54
+ entityIds.add(typename);
55
+ if (id !== undefined) {
56
+ const entityId = buildEntityId(typename, id);
57
+ let responseIds = entityToResponseIds.get(entityId);
58
+ if (responseIds == null) {
59
+ responseIds = new Set();
60
+ entityToResponseIds.set(entityId, responseIds);
61
+ }
62
+ // typename:id => operation
63
+ responseIds.add(responseId);
64
+ // operation => typename:id
65
+ entityIds.add(entityId);
66
+ }
67
+ }
68
+ },
69
+ get(responseId) {
70
+ var _a;
71
+ return (_a = cachedResponses.get(responseId)) !== null && _a !== void 0 ? _a : null;
72
+ },
73
+ invalidate(entitiesToRemove) {
74
+ for (const { typename, id } of entitiesToRemove) {
75
+ purgeEntity(id != null ? buildEntityId(typename, id) : typename);
76
+ }
77
+ },
78
+ };
79
+ };
80
+ export const defaultBuildEntityId = (typename, id) => `${typename}:${id}`;
package/esm/index.js ADDED
@@ -0,0 +1,3 @@
1
+ export * from './in-memory-cache.js';
2
+ export * from './plugin.js';
3
+ export * from './cache.js';
@@ -1,158 +1,15 @@
1
- import LRU from 'lru-cache';
2
1
  import { isAsyncIterable } from '@envelop/core';
3
- import { mapSchema, MapperKind } from '@graphql-tools/utils';
4
- import { print, defaultFieldResolver, TypeInfo, visit, visitWithTypeInfo } from 'graphql';
2
+ import { MapperKind, mapSchema } from '@graphql-tools/utils';
3
+ import { visit, TypeInfo, visitWithTypeInfo, defaultFieldResolver, print, } from 'graphql';
5
4
  import jsonStableStringify from 'fast-json-stable-stringify';
6
-
7
- const createInMemoryCache = (params) => {
8
- var _a;
9
- const buildEntityId = (_a = params === null || params === void 0 ? void 0 : params.buildEntityId) !== null && _a !== void 0 ? _a : defaultBuildEntityId;
10
- const cachedResponses = new LRU({
11
- max: params === null || params === void 0 ? void 0 : params.max,
12
- stale: false,
13
- noDisposeOnSet: true,
14
- dispose(responseId) {
15
- purgeResponse(responseId, false);
16
- },
17
- });
18
- const entityToResponseIds = new Map();
19
- const responseIdToEntityIds = new Map();
20
- function purgeResponse(responseId, shouldRemove = true) {
21
- var _a;
22
- const entityIds = responseIdToEntityIds.get(responseId);
23
- // get entities related to the response
24
- if (entityIds !== undefined) {
25
- for (const entityId of entityIds) {
26
- // remove the response mapping from the entity
27
- (_a = entityToResponseIds.get(entityId)) === null || _a === void 0 ? void 0 : _a.delete(responseId);
28
- }
29
- // remove all the entity mappings from the response
30
- responseIdToEntityIds.delete(responseId);
31
- }
32
- if (shouldRemove) {
33
- // remove the response from the cache
34
- cachedResponses.del(responseId);
35
- }
36
- }
37
- function purgeEntity(entity) {
38
- const responseIds = entityToResponseIds.get(entity);
39
- if (responseIds !== undefined) {
40
- for (const responseId of responseIds) {
41
- purgeResponse(responseId);
42
- }
43
- }
44
- }
45
- return {
46
- set(responseId, result, collectedEntities, ttl) {
47
- cachedResponses.set(responseId, result, ttl);
48
- const entityIds = new Set();
49
- responseIdToEntityIds.set(responseId, entityIds);
50
- for (const { typename, id } of collectedEntities) {
51
- let operationIds = entityToResponseIds.get(typename);
52
- if (operationIds == null) {
53
- operationIds = new Set();
54
- entityToResponseIds.set(typename, operationIds);
55
- }
56
- // typename => operation
57
- operationIds.add(responseId);
58
- // operation => typename
59
- entityIds.add(typename);
60
- if (id !== undefined) {
61
- const entityId = buildEntityId(typename, id);
62
- let responseIds = entityToResponseIds.get(entityId);
63
- if (responseIds == null) {
64
- responseIds = new Set();
65
- entityToResponseIds.set(entityId, responseIds);
66
- }
67
- // typename:id => operation
68
- responseIds.add(responseId);
69
- // operation => typename:id
70
- entityIds.add(entityId);
71
- }
72
- }
73
- },
74
- get(responseId) {
75
- var _a;
76
- return (_a = cachedResponses.get(responseId)) !== null && _a !== void 0 ? _a : null;
77
- },
78
- invalidate(entitiesToRemove) {
79
- for (const { typename, id } of entitiesToRemove) {
80
- purgeEntity(id != null ? buildEntityId(typename, id) : typename);
81
- }
82
- },
83
- };
84
- };
85
- const defaultBuildEntityId = (typename, id) => `${typename}:${id}`;
86
-
87
- const webCrypto = globalThis.crypto;
88
- const sha256Browser = (bytes) => {
89
- const hash = webCrypto.subtle.digest({ name: 'SHA-256' }, bytes);
90
- return new Promise((resolve, reject) => {
91
- Promise.resolve(hash)
92
- .then(function (result) {
93
- resolve(new Uint8Array(result));
94
- })
95
- .catch(function (error) {
96
- reject(error);
97
- });
98
- });
99
- };
100
- let nodeCrypto;
101
- if (typeof window === 'undefined' && !webCrypto) {
102
- // Indirect eval'd require/import to guarantee no side-effects in module scope
103
- // (optimization for minifier)
104
- try {
105
- // eslint-disable-next-line no-new-func
106
- nodeCrypto = Promise.resolve(new Function('require', 'return require("crypto")')(require));
107
- }
108
- catch (_error) {
109
- try {
110
- // eslint-disable-next-line no-new-func
111
- nodeCrypto = new Function('return import("crypto")')();
112
- }
113
- catch (_error) { }
114
- }
115
- }
116
- const hashSHA256 = async (text) => {
117
- // Node.js support
118
- if (nodeCrypto) {
119
- return nodeCrypto.then(crypto => crypto.createHash('sha256').update(text).digest('hex'));
120
- }
121
- if (webCrypto) {
122
- let buf;
123
- if (typeof TextEncoder !== 'undefined') {
124
- buf = new TextEncoder().encode(text);
125
- }
126
- else {
127
- buf = new Uint8Array(text.length);
128
- for (let i = 0, l = text.length; i < l; i++) {
129
- // NOTE: We assume that the input GraphQL Query only uses UTF-8 at most
130
- // since GraphQL mostly consists of ASCII, this is completely fine
131
- buf[i] = text.charCodeAt(i);
132
- }
133
- }
134
- const out = await sha256Browser(buf);
135
- let hash = '';
136
- for (let i = 0, l = out.length; i < l; i++) {
137
- const hex = out[i].toString(16);
138
- hash += '00'.slice(0, Math.max(0, 2 - hex.length)) + hex;
139
- }
140
- return hash;
141
- }
142
- if (process.env.NODE_ENV !== 'production') {
143
- // eslint-disable-next-line no-console
144
- console.warn('[@envelop/response-cache]: The Node Crypto and Web Crypto APIs are not available.\n' +
145
- 'This is an unexpected error. Please report it by filing a GitHub Issue.');
146
- }
147
- return Promise.resolve('');
148
- };
149
-
5
+ import { createInMemoryCache } from './in-memory-cache.js';
6
+ import { hashSHA256 } from './hashSHA256.js';
150
7
  const contextSymbol = Symbol('responseCache');
151
8
  /**
152
9
  * Default function used for building the response cache key.
153
10
  * It is exported here for advanced use-cases. E.g. if you want to short circuit and serve responses from the cache on a global level in order to completely by-pass the GraphQL flow.
154
11
  */
155
- const defaultBuildResponseCacheKey = params => {
12
+ export const defaultBuildResponseCacheKey = params => {
156
13
  var _a, _b, _c;
157
14
  return hashSHA256([
158
15
  params.documentString,
@@ -169,7 +26,7 @@ const defaultBuildResponseCacheKey = params => {
169
26
  *
170
27
  * By default, results with errors (unexpected, EnvelopError, or GraphQLError) are not cached.
171
28
  */
172
- const defaultShouldCacheResult = (params) => {
29
+ export const defaultShouldCacheResult = (params) => {
173
30
  if (params.result.errors) {
174
31
  // eslint-disable-next-line no-console
175
32
  console.warn('[useResponseCache] Failed to cache due to errors');
@@ -178,7 +35,7 @@ const defaultShouldCacheResult = (params) => {
178
35
  return true;
179
36
  };
180
37
  const documentStringByDocument = new WeakMap();
181
- function defaultGetDocumentString(executionArgs) {
38
+ export function defaultGetDocumentString(executionArgs) {
182
39
  let documentString = documentStringByDocument.get(executionArgs.document);
183
40
  if (!documentString) {
184
41
  documentString = print(executionArgs.document);
@@ -186,7 +43,7 @@ function defaultGetDocumentString(executionArgs) {
186
43
  }
187
44
  return documentString;
188
45
  }
189
- function useResponseCache({ cache = createInMemoryCache(), ttl: globalTtl = Infinity, session = () => null, enabled, ignoredTypes = [], ttlPerType = {}, ttlPerSchemaCoordinate = {}, idFields = ['id'], invalidateViaMutation = true, buildResponseCacheKey = defaultBuildResponseCacheKey, getDocumentString = defaultGetDocumentString, shouldCacheResult = defaultShouldCacheResult,
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,
190
47
  // eslint-disable-next-line dot-notation
191
48
  includeExtensionMetadata = typeof process !== 'undefined' ? process.env['NODE_ENV'] === 'development' : false, } = {}) {
192
49
  const appliedTransform = Symbol('responseCache.appliedTransform');
@@ -399,5 +256,3 @@ function applyResponseCacheLogic(schema, idFieldNames) {
399
256
  },
400
257
  });
401
258
  }
402
-
403
- export { createInMemoryCache, defaultBuildEntityId, defaultBuildResponseCacheKey, defaultGetDocumentString, defaultShouldCacheResult, useResponseCache };
package/package.json CHANGED
@@ -1,15 +1,15 @@
1
1
  {
2
2
  "name": "@envelop/response-cache",
3
- "version": "3.0.0-alpha-868cc42.0",
3
+ "version": "3.0.0-alpha-9dd2d31.0",
4
4
  "sideEffects": false,
5
5
  "peerDependencies": {
6
- "@envelop/core": "^2.3.3",
6
+ "@envelop/core": "^2.4.0",
7
7
  "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0"
8
8
  },
9
9
  "dependencies": {
10
- "@graphql-tools/utils": "^8.6.1",
11
- "fast-json-stable-stringify": "^2.1.0",
12
- "lru-cache": "^6.0.0"
10
+ "@graphql-tools/utils": "^8.8.0",
11
+ "lru-cache": "^6.0.0",
12
+ "fast-json-stable-stringify": "^2.1.0"
13
13
  },
14
14
  "repository": {
15
15
  "type": "git",
@@ -18,21 +18,42 @@
18
18
  },
19
19
  "author": "Kamil Kisiela <kamilkisiela@gmail.com>",
20
20
  "license": "MIT",
21
- "main": "index.js",
22
- "module": "index.mjs",
23
- "typings": "index.d.ts",
21
+ "main": "cjs/index.js",
22
+ "module": "esm/index.js",
23
+ "typings": "typings/index.d.ts",
24
24
  "typescript": {
25
- "definition": "index.d.ts"
25
+ "definition": "typings/index.d.ts"
26
26
  },
27
+ "type": "module",
27
28
  "exports": {
28
29
  ".": {
29
- "require": "./index.js",
30
- "import": "./index.mjs"
30
+ "require": {
31
+ "types": "./typings/index.d.ts",
32
+ "default": "./cjs/index.js"
33
+ },
34
+ "import": {
35
+ "types": "./typings/index.d.ts",
36
+ "default": "./esm/index.js"
37
+ },
38
+ "default": {
39
+ "types": "./typings/index.d.ts",
40
+ "default": "./esm/index.js"
41
+ }
31
42
  },
32
43
  "./*": {
33
- "require": "./*.js",
34
- "import": "./*.mjs"
44
+ "require": {
45
+ "types": "./typings/*.d.ts",
46
+ "default": "./cjs/*.js"
47
+ },
48
+ "import": {
49
+ "types": "./typings/*.d.ts",
50
+ "default": "./esm/*.js"
51
+ },
52
+ "default": {
53
+ "types": "./typings/*.d.ts",
54
+ "default": "./esm/*.js"
55
+ }
35
56
  },
36
57
  "./package.json": "./package.json"
37
58
  }
38
- }
59
+ }
File without changes
File without changes
@@ -1,4 +1,4 @@
1
- import type { Cache } from './cache';
1
+ import type { Cache } from './cache.js';
2
2
  export declare type BuildEntityId = (typename: string, id: number | string) => string;
3
3
  export declare type InMemoryCacheParameter = {
4
4
  /**
@@ -11,5 +11,5 @@ export declare type InMemoryCacheParameter = {
11
11
  */
12
12
  buildEntityId?: BuildEntityId;
13
13
  };
14
- export declare const createInMemoryCache: (params?: InMemoryCacheParameter | undefined) => Cache;
14
+ export declare const createInMemoryCache: (params?: InMemoryCacheParameter) => Cache;
15
15
  export declare const defaultBuildEntityId: BuildEntityId;
@@ -0,0 +1,3 @@
1
+ export * from './in-memory-cache.js';
2
+ export * from './plugin.js';
3
+ export * from './cache.js';
@@ -1,6 +1,6 @@
1
1
  import { Plugin, Maybe } from '@envelop/core';
2
2
  import { ExecutionArgs, ExecutionResult } from 'graphql';
3
- import type { Cache } from './cache';
3
+ import type { Cache } from './cache.js';
4
4
  /**
5
5
  * Function for building the response cache key based on the input parameters
6
6
  */
package/index.d.ts DELETED
@@ -1,3 +0,0 @@
1
- export * from './in-memory-cache';
2
- export * from './plugin';
3
- export * from './cache';