feat(ajax): add an option to initialize the cache interceptors even when useCache is turned off in the global options
This commit is contained in:
parent
a28686ee72
commit
56af96f1da
6 changed files with 64 additions and 18 deletions
5
.changeset/silent-ravens-smell.md
Normal file
5
.changeset/silent-ravens-smell.md
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
---
|
||||||
|
'@lion/ajax': minor
|
||||||
|
---
|
||||||
|
|
||||||
|
Add an option "addCaching" to the Ajax config, in order to add cache interceptors when useCache is turned off. In this situation, all requests are cached proactively.
|
||||||
|
|
@ -23,11 +23,12 @@ export class Ajax {
|
||||||
*/
|
*/
|
||||||
constructor(config = {}) {
|
constructor(config = {}) {
|
||||||
/**
|
/**
|
||||||
* @type {Partial<AjaxConfig>}
|
* @type {AjaxConfig}
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
this.__config = {
|
this.__config = {
|
||||||
addAcceptLanguage: true,
|
addAcceptLanguage: true,
|
||||||
|
addCaching: false,
|
||||||
xsrfCookieName: 'XSRF-TOKEN',
|
xsrfCookieName: 'XSRF-TOKEN',
|
||||||
xsrfHeaderName: 'X-XSRF-TOKEN',
|
xsrfHeaderName: 'X-XSRF-TOKEN',
|
||||||
jsonPrefix: '',
|
jsonPrefix: '',
|
||||||
|
|
@ -53,7 +54,7 @@ export class Ajax {
|
||||||
}
|
}
|
||||||
|
|
||||||
const { cacheOptions } = this.__config;
|
const { cacheOptions } = this.__config;
|
||||||
if (cacheOptions?.useCache) {
|
if (cacheOptions.useCache || this.__config.addCaching) {
|
||||||
const { cacheRequestInterceptor, cacheResponseInterceptor } = createCacheInterceptors(
|
const { cacheRequestInterceptor, cacheResponseInterceptor } = createCacheInterceptors(
|
||||||
cacheOptions.getCacheIdentifier,
|
cacheOptions.getCacheIdentifier,
|
||||||
cacheOptions,
|
cacheOptions,
|
||||||
|
|
@ -65,7 +66,7 @@ export class Ajax {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Configures the Ajax instance
|
* Configures the Ajax instance
|
||||||
* @param {Partial<AjaxConfig>} config configuration for the Ajax instance
|
* @param {AjaxConfig} config configuration for the Ajax instance
|
||||||
*/
|
*/
|
||||||
set options(config) {
|
set options(config) {
|
||||||
this.__config = config;
|
this.__config = config;
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,15 @@ import {
|
||||||
isCurrentSessionId,
|
isCurrentSessionId,
|
||||||
} from '../cacheManager.js';
|
} from '../cacheManager.js';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests whether the request method is supported according to the `cacheOptions`
|
||||||
|
* @param {ValidatedCacheOptions} cacheOptions
|
||||||
|
* @param {string} method
|
||||||
|
* @returns {boolean}
|
||||||
|
*/
|
||||||
|
const isMethodSupported = (cacheOptions, method) =>
|
||||||
|
cacheOptions.methods.includes(method.toLowerCase());
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Request interceptor to return relevant cached requests
|
* Request interceptor to return relevant cached requests
|
||||||
* @param {function(): string} getCacheId used to invalidate cache if identifier is changed
|
* @param {function(): string} getCacheId used to invalidate cache if identifier is changed
|
||||||
|
|
@ -36,9 +45,8 @@ const createCacheRequestInterceptor =
|
||||||
}
|
}
|
||||||
|
|
||||||
const requestId = cacheOptions.requestIdFunction(request);
|
const requestId = cacheOptions.requestIdFunction(request);
|
||||||
const isMethodSupported = cacheOptions.methods.includes(request.method.toLowerCase());
|
|
||||||
|
|
||||||
if (!isMethodSupported) {
|
if (!isMethodSupported(cacheOptions, request.method)) {
|
||||||
invalidateMatchingCache(requestId, cacheOptions);
|
invalidateMatchingCache(requestId, cacheOptions);
|
||||||
return request;
|
return request;
|
||||||
}
|
}
|
||||||
|
|
@ -81,12 +89,9 @@ const createCacheResponseInterceptor =
|
||||||
...response.request.cacheOptions,
|
...response.request.cacheOptions,
|
||||||
});
|
});
|
||||||
|
|
||||||
const requestId = cacheOptions.requestIdFunction(response.request);
|
if (!response.fromCache && isMethodSupported(cacheOptions, response.request.method)) {
|
||||||
const isAlreadyFromCache = !!response.fromCache;
|
const requestId = cacheOptions.requestIdFunction(response.request);
|
||||||
const isCacheActive = cacheOptions.useCache;
|
|
||||||
const isMethodSupported = cacheOptions.methods.includes(response.request?.method.toLowerCase());
|
|
||||||
|
|
||||||
if (!isAlreadyFromCache && isCacheActive && isMethodSupported) {
|
|
||||||
if (isCurrentSessionId(response.request.cacheSessionId)) {
|
if (isCurrentSessionId(response.request.cacheSessionId)) {
|
||||||
// Cache the response
|
// Cache the response
|
||||||
ajaxCache.set(requestId, response.clone());
|
ajaxCache.set(requestId, response.clone());
|
||||||
|
|
@ -95,6 +100,7 @@ const createCacheResponseInterceptor =
|
||||||
// Mark the pending request as resolved
|
// Mark the pending request as resolved
|
||||||
pendingRequestStore.resolve(requestId);
|
pendingRequestStore.resolve(requestId);
|
||||||
}
|
}
|
||||||
|
|
||||||
return response;
|
return response;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -43,6 +43,7 @@ describe('Ajax', () => {
|
||||||
};
|
};
|
||||||
const expected = {
|
const expected = {
|
||||||
addAcceptLanguage: true,
|
addAcceptLanguage: true,
|
||||||
|
addCaching: false,
|
||||||
xsrfCookieName: 'XSRF-TOKEN',
|
xsrfCookieName: 'XSRF-TOKEN',
|
||||||
xsrfHeaderName: 'X-XSRF-TOKEN',
|
xsrfHeaderName: 'X-XSRF-TOKEN',
|
||||||
jsonPrefix: ")]}',",
|
jsonPrefix: ")]}',",
|
||||||
|
|
@ -303,6 +304,44 @@ describe('Ajax', () => {
|
||||||
getCacheIdentifier = () => String(cacheId);
|
getCacheIdentifier = () => String(cacheId);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('does not add cache interceptors when useCache is turned off', () => {
|
||||||
|
const customAjax = new Ajax({
|
||||||
|
cacheOptions: {
|
||||||
|
maxAge: 100,
|
||||||
|
getCacheIdentifier,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(customAjax._requestInterceptors.length).to.equal(2);
|
||||||
|
expect(customAjax._responseInterceptors.length).to.equal(0);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('adds cache interceptors when useCache is turned on', () => {
|
||||||
|
const customAjax = new Ajax({
|
||||||
|
cacheOptions: {
|
||||||
|
useCache: true,
|
||||||
|
maxAge: 100,
|
||||||
|
getCacheIdentifier,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(customAjax._requestInterceptors.length).to.equal(3);
|
||||||
|
expect(customAjax._responseInterceptors.length).to.equal(1);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('adds cache interceptors when addCaching is turned on', () => {
|
||||||
|
const customAjax = new Ajax({
|
||||||
|
addCaching: true,
|
||||||
|
cacheOptions: {
|
||||||
|
maxAge: 100,
|
||||||
|
getCacheIdentifier,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(customAjax._requestInterceptors.length).to.equal(3);
|
||||||
|
expect(customAjax._responseInterceptors.length).to.equal(1);
|
||||||
|
});
|
||||||
|
|
||||||
describe('caching interceptors', async () => {
|
describe('caching interceptors', async () => {
|
||||||
/**
|
/**
|
||||||
* @type {Ajax}
|
* @type {Ajax}
|
||||||
|
|
|
||||||
|
|
@ -150,14 +150,12 @@ describe('cache interceptors', () => {
|
||||||
expect(fetchStub.callCount).to.equal(1);
|
expect(fetchStub.callCount).to.equal(1);
|
||||||
});
|
});
|
||||||
|
|
||||||
// TODO: Check if this is the behaviour we want
|
it('all calls are cached proactively', async () => {
|
||||||
it('all calls with non-default `maxAge` are cached proactively', async () => {
|
|
||||||
// Given
|
// Given
|
||||||
newCacheId();
|
newCacheId();
|
||||||
|
|
||||||
addCacheInterceptors(ajax, {
|
addCacheInterceptors(ajax, {
|
||||||
useCache: false,
|
useCache: false,
|
||||||
maxAge: 100,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// When
|
// When
|
||||||
|
|
@ -169,11 +167,7 @@ describe('cache interceptors', () => {
|
||||||
expect(fetchStub.callCount).to.equal(1);
|
expect(fetchStub.callCount).to.equal(1);
|
||||||
|
|
||||||
// When
|
// When
|
||||||
await ajax.fetch('/test', {
|
await ajax.fetch('/test');
|
||||||
cacheOptions: {
|
|
||||||
useCache: true,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
// Then
|
// Then
|
||||||
expect(fetchStub.callCount).to.equal(2);
|
expect(fetchStub.callCount).to.equal(2);
|
||||||
|
|
|
||||||
1
packages/ajax/types/types.d.ts
vendored
1
packages/ajax/types/types.d.ts
vendored
|
|
@ -12,6 +12,7 @@ export interface LionRequestInit extends Omit<RequestInit, 'body'> {
|
||||||
|
|
||||||
export interface AjaxConfig {
|
export interface AjaxConfig {
|
||||||
addAcceptLanguage: boolean;
|
addAcceptLanguage: boolean;
|
||||||
|
addCaching: boolean;
|
||||||
xsrfCookieName: string | null;
|
xsrfCookieName: string | null;
|
||||||
xsrfHeaderName: string | null;
|
xsrfHeaderName: string | null;
|
||||||
cacheOptions: CacheOptionsWithIdentifier;
|
cacheOptions: CacheOptionsWithIdentifier;
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue