bv-ui-core 2.9.4 → 2.9.7
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/lib/bvFetch/README.md +5 -5
- package/lib/bvFetch/index.js +67 -25
- package/package.json +1 -1
- package/test/unit/bvFetch/index.spec.js +18 -6
package/lib/bvFetch/README.md
CHANGED
@@ -21,13 +21,13 @@ The BvFetch module provides methods to cache duplicate API calls and interact wi
|
|
21
21
|
`url (String):` The URL of the API endpoint.
|
22
22
|
`options (Object):` Optional request options.
|
23
23
|
## generateCacheKey Return Value:
|
24
|
-
`
|
24
|
+
`Request:` The generated cache key.
|
25
25
|
|
26
|
-
##
|
27
|
-
Retrieves cached
|
28
|
-
##
|
26
|
+
## retrievecachedRequests Method
|
27
|
+
Retrieves cached Requests from the cache storage associated with the provided cache name.
|
28
|
+
## retrievecachedRequests Parameters
|
29
29
|
This method takes no parameters.
|
30
|
-
##
|
30
|
+
## retrievecachedRequests Return Value
|
31
31
|
`void:` This method does not return anything.
|
32
32
|
|
33
33
|
## fetchDataAndCache Method
|
package/lib/bvFetch/index.js
CHANGED
@@ -1,4 +1,3 @@
|
|
1
|
-
|
2
1
|
/**
|
3
2
|
* @fileOverview
|
4
3
|
* Provides api response caching utilties
|
@@ -11,41 +10,85 @@ module.exports = function BvFetch ({ shouldCache, cacheName, cacheLimit }) {
|
|
11
10
|
this.cacheName = cacheName || 'bvCache';
|
12
11
|
this.cacheLimit = cacheLimit * 1024 * 1024 || 10 * 1024 * 1024;
|
13
12
|
this.fetchPromises = new Map();
|
14
|
-
this.
|
13
|
+
this.cachedRequests = new Set();
|
15
14
|
|
16
15
|
/**
|
17
|
-
*
|
18
|
-
*
|
19
|
-
* @param {
|
20
|
-
* @
|
16
|
+
* Checks if a request is present in a set of cached URLs.
|
17
|
+
*
|
18
|
+
* @param {Set} cachedRequests - A set of cached request objects.
|
19
|
+
* @param {Object} cacheKey - The request object to check for in the cachedRequests set.
|
20
|
+
* @param {string} cacheKey.url - The URL of the request.
|
21
|
+
* @param {Headers} cacheKey.headers - The headers of the request.
|
22
|
+
* @returns {boolean} - Returns true if the request is found in the cachedRequests set, otherwise false.
|
21
23
|
*/
|
24
|
+
function isRequestInSet (cachedRequests, cacheKey) {
|
25
|
+
try {
|
26
|
+
// Convert the Set to an array and check if any request matches
|
27
|
+
return [...cachedRequests].some((cachedRequest) => {
|
28
|
+
// Compare URLs
|
29
|
+
if (cachedRequest.url !== cacheKey.url) {
|
30
|
+
return false;
|
31
|
+
}
|
32
|
+
|
33
|
+
// Compare headers
|
34
|
+
const cachedHeaders = [...cachedRequest.headers.entries()];
|
35
|
+
const keyHeaders = [...cacheKey.headers.entries()];
|
36
|
+
|
37
|
+
if (cachedHeaders.length !== keyHeaders.length) {
|
38
|
+
return false; // Different number of headers
|
39
|
+
}
|
40
|
+
|
41
|
+
return cachedHeaders.every(([key, value]) => {
|
42
|
+
return cacheKey.headers.get(key) === value;
|
43
|
+
});
|
44
|
+
});
|
45
|
+
}
|
46
|
+
catch (error) {
|
47
|
+
console.warn('Error checking in if request is in cache: ', error);
|
48
|
+
return false;
|
49
|
+
}
|
50
|
+
}
|
51
|
+
|
52
|
+
|
53
|
+
/**
|
54
|
+
* Creates a new Request object with the given URL and options.
|
55
|
+
*
|
56
|
+
* @param {string} url - The URL to which the request is sent.
|
57
|
+
* @param {Object} options - The options to apply to the request.
|
58
|
+
* @returns {Request} The created Request object.
|
59
|
+
*/
|
22
60
|
|
23
61
|
this.generateCacheKey = (url, options) => {
|
24
|
-
const
|
25
|
-
const key = url + optionsString;
|
62
|
+
const key = new Request(url, options);
|
26
63
|
return key;
|
27
64
|
};
|
28
65
|
|
29
66
|
/**
|
30
|
-
* Retrieves cached
|
67
|
+
* Retrieves cached Requests from the cache storage associated with the provided cache name.
|
31
68
|
* @returns {void}
|
32
69
|
*/
|
33
70
|
|
34
|
-
this.
|
71
|
+
this.retrievecachedRequests = () => {
|
35
72
|
// Open the Cache Storage
|
36
73
|
caches.open(this.cacheName).then(cache => {
|
37
74
|
// Get all cache keys
|
38
75
|
cache.keys().then(keys => {
|
39
76
|
keys.forEach(request => {
|
40
|
-
|
77
|
+
const headers = {};
|
78
|
+
request.headers.forEach((value, key) => {
|
79
|
+
headers[key] = value;
|
80
|
+
});
|
81
|
+
|
82
|
+
// Generate the cache key with headers and URL
|
83
|
+
const cacheKey = this.generateCacheKey(request.url, { headers });
|
84
|
+
this.cachedRequests.add(cacheKey); // Add to the set
|
41
85
|
});
|
42
86
|
});
|
43
87
|
});
|
44
|
-
|
45
88
|
}
|
46
89
|
|
47
|
-
//
|
48
|
-
this.
|
90
|
+
//callretrievecachedRequests function to set the cache URL set with the cached URLS
|
91
|
+
this.retrievecachedRequests();
|
49
92
|
|
50
93
|
/**
|
51
94
|
* Fetches data from the specified URL, caches the response, and returns the response.
|
@@ -107,8 +150,8 @@ module.exports = function BvFetch ({ shouldCache, cacheName, cacheLimit }) {
|
|
107
150
|
// Cache the response
|
108
151
|
caches.open(this.cacheName).then(cache => {
|
109
152
|
cache.put(cacheKey, newResponse);
|
110
|
-
//add key to
|
111
|
-
this.
|
153
|
+
//add key to cachedRequests set
|
154
|
+
this.cachedRequests.add(cacheKey);
|
112
155
|
});
|
113
156
|
});
|
114
157
|
}
|
@@ -123,8 +166,8 @@ module.exports = function BvFetch ({ shouldCache, cacheName, cacheLimit }) {
|
|
123
166
|
* @throws {Error} Throws an error if there's any problem fetching from cache.
|
124
167
|
*/
|
125
168
|
this.fetchFromCache = (cacheKey) => {
|
126
|
-
// Check if the URL is in the set of cached
|
127
|
-
if (!this.
|
169
|
+
// Check if the URL is in the set of cached requests set
|
170
|
+
if (!isRequestInSet(this.cachedRequests, cacheKey)) {
|
128
171
|
return Promise.resolve(null);
|
129
172
|
}
|
130
173
|
|
@@ -133,7 +176,10 @@ module.exports = function BvFetch ({ shouldCache, cacheName, cacheLimit }) {
|
|
133
176
|
.then((cache) => {
|
134
177
|
return cache.match(cacheKey)
|
135
178
|
.then((cachedResponse) => {
|
136
|
-
|
179
|
+
if (!cachedResponse) {
|
180
|
+
this.cachedRequests.delete(cacheKey)
|
181
|
+
return Promise.resolve(null);
|
182
|
+
}
|
137
183
|
const cachedTime = cachedResponse.headers.get('X-Bazaarvoice-Cached-Time');
|
138
184
|
const ttl = cachedResponse.headers.get('Cache-Control').match(/max-age=(\d+)/)[1];
|
139
185
|
const currentTimestamp = Date.now();
|
@@ -167,10 +213,6 @@ module.exports = function BvFetch ({ shouldCache, cacheName, cacheLimit }) {
|
|
167
213
|
// Check if response is available in cache
|
168
214
|
const newPromise = this.fetchFromCache(cacheKey)
|
169
215
|
.then((cachedResponse) => {
|
170
|
-
if (!cachedResponse) {
|
171
|
-
this.cachedUrls.delete(cacheKey)
|
172
|
-
return Promise.resolve(null);
|
173
|
-
}
|
174
216
|
// If response found in cache, return it
|
175
217
|
if (cachedResponse) {
|
176
218
|
return cachedResponse;
|
@@ -220,7 +262,7 @@ module.exports = function BvFetch ({ shouldCache, cacheName, cacheLimit }) {
|
|
220
262
|
const cacheAge = (currentTimestamp - cachedTime) / 1000;
|
221
263
|
if (cacheAge >= ttl) {
|
222
264
|
cache.delete(key);
|
223
|
-
this.
|
265
|
+
this.cachedRequests.delete(key);
|
224
266
|
}
|
225
267
|
});
|
226
268
|
});
|
@@ -268,7 +310,7 @@ module.exports = function BvFetch ({ shouldCache, cacheName, cacheLimit }) {
|
|
268
310
|
cacheEntries.forEach(entry => {
|
269
311
|
if (currentSize > this.cacheLimit) {
|
270
312
|
cache.delete(entry.key);
|
271
|
-
this.
|
313
|
+
this.cachedRequests.delete(entry.key);
|
272
314
|
currentSize -= entry.size;
|
273
315
|
}
|
274
316
|
});
|
package/package.json
CHANGED
@@ -38,16 +38,27 @@ describe('BvFetch', function () {
|
|
38
38
|
|
39
39
|
it('should generate correct cache key', function () {
|
40
40
|
const url = 'https://jsonplaceholder.typicode.com/todos';
|
41
|
-
const options = {
|
42
|
-
|
41
|
+
const options = {
|
42
|
+
method: 'GET',
|
43
|
+
headers: {
|
44
|
+
'X-Header-1': 'Value 1',
|
45
|
+
}
|
46
|
+
};
|
47
|
+
const expectedKey = new Request(url, options)
|
43
48
|
const generatedKey = bvFetchInstance.generateCacheKey(url, options);
|
44
|
-
expect(generatedKey).to.equal(expectedKey);
|
49
|
+
expect(generatedKey.url).to.equal(expectedKey.url);
|
50
|
+
expect(generatedKey.headers).to.deep.equal(expectedKey.headers);
|
45
51
|
});
|
46
52
|
|
47
53
|
|
48
54
|
it('should fetch from cache when the response is cached', function (done) {
|
49
55
|
const url = 'https://jsonplaceholder.typicode.com/todos';
|
50
|
-
const options = {
|
56
|
+
const options = {
|
57
|
+
method: 'GET',
|
58
|
+
headers: {
|
59
|
+
'X-Header-1': 'Value 1',
|
60
|
+
}
|
61
|
+
};
|
51
62
|
|
52
63
|
// Mocking cache response
|
53
64
|
const mockResponse = new Response('Mock Data', {
|
@@ -64,7 +75,8 @@ describe('BvFetch', function () {
|
|
64
75
|
// Overriding the stub for this specific test case
|
65
76
|
caches.open.resolves({
|
66
77
|
match: (key) => {
|
67
|
-
expect(key).to.equal(cacheKey);
|
78
|
+
expect(key.url).to.equal(cacheKey.url);
|
79
|
+
expect(key.headers).to.deep.equal(cacheKey.headers);
|
68
80
|
return Promise.resolve(mockResponse)
|
69
81
|
},
|
70
82
|
put: (key, response) => {
|
@@ -74,7 +86,7 @@ describe('BvFetch', function () {
|
|
74
86
|
});
|
75
87
|
|
76
88
|
// Simulate that the response is cached
|
77
|
-
bvFetchInstance.
|
89
|
+
bvFetchInstance.cachedRequests.add(cacheKey);
|
78
90
|
|
79
91
|
// Call the function under test
|
80
92
|
bvFetchInstance.bvFetchFunc(url, options)
|