Socket
Socket
Sign inDemoInstall

axios-cache-interceptor

Package Overview
Dependencies
Maintainers
1
Versions
78
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

axios-cache-interceptor - npm Package Compare versions

Comparing version 1.0.1 to 1.1.0

dist/tsconfig.types.tsbuildinfo

2

dev/index.bundle.js

@@ -1,2 +0,2 @@

!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports.AxiosCacheInterceptor=t():e.AxiosCacheInterceptor=t()}("undefined"!=typeof self?self:this,(()=>(()=>{"use strict";var e={d:(t,a)=>{for(var r in a)e.o(a,r)&&!e.o(t,r)&&Object.defineProperty(t,r,{enumerable:!0,get:a[r]})},o:(e,t)=>Object.prototype.hasOwnProperty.call(e,t),r:e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})}},t={};e.r(t),e.d(t,{Header:()=>i,buildKeyGenerator:()=>A,buildMemoryStorage:()=>x,buildStorage:()=>w,buildWebStorage:()=>O,canStale:()=>b,createCacheResponse:()=>f,createValidateStatus:()=>d,defaultHeaderInterpreter:()=>s,defaultKeyGenerator:()=>j,defaultRequestInterceptor:()=>g,defaultResponseInterceptor:()=>m,isExpired:()=>y,isMethodIn:()=>u,isStorage:()=>v,setupCache:()=>E,testCachePredicate:()=>h,updateCache:()=>p,updateStaleRequest:()=>l});var a=Symbol("cache-parser");function r(e){return("string"==typeof e||"number"==typeof e)&&(e=Number(e))>=0&&e<1/0}function n(e){return!0===e||"number"==typeof e||"string"==typeof e&&"false"!==e}var o=Number;const i=Object.freeze({IfModifiedSince:"if-modified-since",LastModified:"last-modified",IfNoneMatch:"if-none-match",CacheControl:"cache-control",Pragma:"pragma",ETag:"etag",Expires:"expires",Age:"age",XAxiosCacheEtag:"x-axios-cache-etag",XAxiosCacheLastModified:"x-axios-cache-last-modified",XAxiosCacheStaleIfError:"x-axios-cache-stale-if-error"}),s=e=>{if(!e)return"not enough headers";const t=e[i.CacheControl];if(t){const{noCache:s,noStore:c,mustRevalidate:d,maxAge:u,immutable:l}=function(e){var t=Object.defineProperty({},a,{enumerable:!1,value:1});if(!e||"string"!=typeof e)return t;var i=function(e){var t={},a=e.toLowerCase().replace(/\s+/g,"").split(",");for(var r in a){var n,o=a[r].split("=",2);t[o[0]]=null==(n=o[1])||n}return t}(e),s=i["max-age"],c=i["max-stale"],d=i["min-fresh"],u=i["s-maxage"],l=i["stale-if-error"],f=i["stale-while-revalidate"];return n(i.immutable)&&(t.immutable=!0),r(s)&&(t.maxAge=o(s)),r(c)&&(t.maxStale=o(c)),r(d)&&(t.minFresh=o(d)),n(i["must-revalidate"])&&(t.mustRevalidate=!0),n(i["must-understand"])&&(t.mustUnderstand=!0),n(i["no-cache"])&&(t.noCache=!0),n(i["no-store"])&&(t.noStore=!0),n(i["no-transform"])&&(t.noTransform=!0),n(i["only-if-cached"])&&(t.onlyIfCached=!0),n(i.private)&&(t.private=!0),n(i["proxy-revalidate"])&&(t.proxyRevalidate=!0),n(i.public)&&(t.public=!0),r(u)&&(t.sMaxAge=o(u)),r(l)&&(t.staleIfError=o(l)),r(f)&&(t.staleWhileRevalidate=o(f)),t}(String(t));if(s||c)return"dont cache";if(l)return 31536e6;if(d)return 0;if(void 0!==u){const t=e[i.Age];return t?1e3*(u-Number(t)):1e3*u}}const s=e[i.Expires];if(s){const e=Date.parse(String(s))-Date.now();return e>=0?e:"dont cache"}return"not enough headers"};var c=Symbol();function d(e){return e?t=>e(t)||304===t:e=>e>=200&&e<300||304===e}function u(e="get",t=[]){return e=e.toLowerCase(),t.some((t=>t===e))}function l(e,t){var a;t.headers||(t.headers={});const{etag:r,modifiedSince:n}=t.cache;if(r){const n=!0===r?null===(a=e.data)||void 0===a?void 0:a.headers[i.ETag]:r;n&&(t.headers[i.IfNoneMatch]=n)}n&&(t.headers[i.IfModifiedSince]=!0===n?e.data.headers[i.LastModified]||new Date(e.createdAt).toUTCString():n.toUTCString())}function f(e,t){return 304===e.status&&t?(e.cached=!0,e.data=t.data,e.status=t.status,e.statusText=t.statusText,e.headers=Object.assign(Object.assign({},t.headers),e.headers),t):{data:e.data,status:e.status,statusText:e.statusText,headers:e.headers}}function g(e){const t=async t=>{var a,r,n,o,s,f,g,h,p,m,v,b,y,w,x,S,C;const I=t.id=e.generateKey(t);if(!1===t.cache)return null===(a=e.debug)||void 0===a||a.call(e,{msg:"Ignoring cache because config.cache === false",data:t}),t;if(t.cache=Object.assign(Object.assign({},e.defaults.cache),t.cache),t.cache.cacheTakeover&&(null!==(r=(b=t.headers)[y=i.CacheControl])&&void 0!==r||(b[y]="no-cache"),null!==(n=(w=t.headers)[x=i.Pragma])&&void 0!==n||(w[x]="no-cache"),null!==(o=(S=t.headers)[C=i.Expires])&&void 0!==o||(S[C]="0")),!u(t.method,t.cache.methods))return null===(s=e.debug)||void 0===s||s.call(e,{msg:`Ignored because method (${t.method}) is not in cache.methods (${t.cache.methods})`}),t;let A=await e.storage.get(I,t);const j=t.cache.override;e:if("empty"===A.state||"stale"===A.state||j){if(e.waiting[I]&&!j&&(A=await e.storage.get(I,t),"empty"!==A.state)){null===(f=e.debug)||void 0===f||f.call(e,{id:I,msg:"Waiting list had an deferred for this key, waiting for it to finish"});break e}return e.waiting[I]=function(){var e,t,a=new Promise((function(a,r){e=a,t=r}));return a.resolve=e,a.reject=t,a[c]=1,a}(),e.waiting[I].catch((()=>{})),await e.storage.set(I,{state:"loading",previous:j?A.data?"stale":"empty":A.state,data:A.data,createdAt:j&&!A.createdAt?Date.now():A.createdAt},t),"stale"===A.state&&(l(A,t),null===(g=e.debug)||void 0===g||g.call(e,{id:I,msg:"Updated stale request"})),t.validateStatus=d(t.validateStatus),null===(h=e.debug)||void 0===h||h.call(e,{id:I,msg:"Sending request, waiting for response",data:{overrideCache:j,state:A.state}}),t}let E;if("loading"===A.state){const a=e.waiting[I];if(!a)return await e.storage.remove(I,t),t;null===(p=e.debug)||void 0===p||p.call(e,{id:I,msg:"Detected concurrent request, waiting for it to finish"});try{E=await a}catch(a){return null===(m=e.debug)||void 0===m||m.call(e,{id:I,msg:"Deferred rejected, requesting again",data:a}),t}}else E=A.data;return t.adapter=()=>Promise.resolve({config:t,data:E.data,headers:E.headers,status:E.status,statusText:E.statusText,cached:!0,id:I}),null===(v=e.debug)||void 0===v||v.call(e,{id:I,msg:"Returning cached response"}),t};return{onFulfilled:t,apply:()=>e.interceptors.request.use(t)}}async function h(e,t){var a;if("function"==typeof t)return t(e);const{statusCheck:r,responseMatch:n,containsHeaders:o}=t;if(r&&!await r(e.status)||n&&!await n(e))return!1;if(o)for(const[t,r]of Object.entries(o))if(!await r(null!==(a=e.headers[t.toLowerCase()])&&void 0!==a?a:e.headers[t]))return!1;return!0}async function p(e,t,a){if("function"==typeof a)return a(t);for(const[r,n]of Object.entries(a)){if("delete"===n){await e.remove(r,t.config);continue}const a=await e.get(r,t.config);if("loading"===a.state)continue;const o=await n(a,t);"delete"!==o?"ignore"!==o&&await e.set(r,o,t.config):await e.remove(r,t.config)}}function m(e){const t=async(t,a)=>{var r;await e.storage.remove(t,a),null===(r=e.waiting[t])||void 0===r||r.reject(),delete e.waiting[t]},a=async a=>{var r,n,o,s,c,d,l,g,m,v,b,y;const w=a.id=null!==(r=(y=a.config).id)&&void 0!==r?r:y.id=e.generateKey(a.config);if(null!==(n=a.cached)&&void 0!==n||(a.cached=!1),a.cached)return null===(o=e.debug)||void 0===o||o.call(e,{id:w,msg:"Returned cached response"}),a;const x=a.config,S=x.cache;if(!S)return null===(s=e.debug)||void 0===s||s.call(e,{id:w,msg:"Response with config.cache falsy",data:a}),Object.assign(Object.assign({},a),{cached:!1});if(S.update&&await p(e.storage,a,S.update),!u(x.method,S.methods))return null===(c=e.debug)||void 0===c||c.call(e,{id:w,msg:`Ignored because method (${x.method}) is not in cache.methods (${S.methods})`,data:{config:x,cacheConfig:S}}),a;const C=await e.storage.get(w,x);if("loading"!==C.state)return null===(d=e.debug)||void 0===d||d.call(e,{id:w,msg:"Response not cached and storage isn't loading",data:{cache:C,response:a}}),a;if(!C.data&&!await h(a,S.cachePredicate))return await t(w,x),null===(l=e.debug)||void 0===l||l.call(e,{id:w,msg:"Cache predicate rejected this response"}),a;for(const e of Object.keys(a.headers))e.startsWith("x-axios-cache")&&delete a.headers[e];S.etag&&!0!==S.etag&&(a.headers[i.XAxiosCacheEtag]=S.etag),S.modifiedSince&&(a.headers[i.XAxiosCacheLastModified]=!0===S.modifiedSince?"use-cache-timestamp":S.modifiedSince.toUTCString());let I=S.ttl||-1;if(S.interpretHeader){const r=e.headerInterpreter(a.headers);if("dont cache"===r)return await t(w,x),null===(g=e.debug)||void 0===g||g.call(e,{id:w,msg:"Cache header interpreted as 'dont cache'",data:{cache:C,response:a,expirationTime:r}}),a;I="not enough headers"===r?I:r}const A=f(a,C.data);"function"==typeof I&&(I=await I(a)),S.staleIfError&&(a.headers[i.XAxiosCacheStaleIfError]=String(I)),null===(m=e.debug)||void 0===m||m.call(e,{id:w,msg:"Useful response configuration found",data:{cacheConfig:S,cacheResponse:A}});const j={state:"cached",ttl:I,createdAt:Date.now(),data:A},E=e.waiting[w];return E&&(E.resolve(j.data),delete e.waiting[w],null===(v=e.debug)||void 0===v||v.call(e,{id:w,msg:"Found waiting deferred(s) and resolved them"})),await e.storage.set(w,j,x),null===(b=e.debug)||void 0===b||b.call(e,{id:w,msg:"Response cached",data:{cache:j,response:a}}),a},r=async a=>{var r,n,o,i,s,c,d;const l=a.config,f=l.id,g=l.cache;if(!g||!f)throw null===(r=e.debug)||void 0===r||r.call(e,{msg:"Web request returned an error but cache handling is not enabled",data:{error:a}}),a;if(!u(l.method,g.methods))throw null===(n=e.debug)||void 0===n||n.call(e,{id:f,msg:`Ignored because method (${l.method}) is not in cache.methods (${g.methods})`,data:{config:l,cacheConfig:g}}),a;const h=await e.storage.get(f,l);if("loading"!==h.state||"stale"!==h.previous)throw await t(f,l),null===(o=e.debug)||void 0===o||o.call(e,{id:f,msg:"Caught an error in the request interceptor",data:{error:a,config:l}}),a;if(g.staleIfError){const t="function"==typeof g.staleIfError?await g.staleIfError(a.response,h,a):g.staleIfError;if(null===(i=e.debug)||void 0===i||i.call(e,{id:f,msg:"Found cache if stale config for rejected response",data:{error:a,config:l,staleIfError:t}}),!0===t||"number"==typeof t&&h.createdAt+t>Date.now())return null===(s=e.waiting[f])||void 0===s||s.resolve(h.data),delete e.waiting[f],await e.storage.set(f,{state:"stale",createdAt:Date.now(),data:h.data},l),null===(c=e.debug)||void 0===c||c.call(e,{id:f,msg:"staleIfError resolved this response with cached data",data:{error:a,config:l,cache:h}}),{cached:!0,config:l,id:f,data:h.data.data,headers:h.data.headers,status:h.data.status,statusText:h.data.statusText}}throw null===(d=e.debug)||void 0===d||d.call(e,{id:f,msg:"Received an unknown error that could not be handled",data:{error:a,config:l}}),a};return{onFulfilled:a,onRejected:r,apply:()=>e.interceptors.response.use(a,r)}}const v=e=>!!e&&!!e["is-storage"];function b(e){const t=e.data.headers;return i.ETag in t||i.LastModified in t||i.XAxiosCacheEtag in t||i.XAxiosCacheStaleIfError in t||i.XAxiosCacheLastModified in t}function y(e){return e.createdAt+e.ttl<=Date.now()}function w({set:e,find:t,remove:a}){return{"is-storage":1,set:e,remove:a,get:async(r,n)=>{const o=await t(r,n);if(!o)return{state:"empty"};if("cached"!==o.state||!y(o))return o;if(b(o)){const t={state:"stale",createdAt:o.createdAt,data:o.data};return await e(r,t,n),t}return await a(r,n),{state:"empty"}}}}function x(e=!1){const t=w({set:(e,a)=>{t.data[e]=a},remove:e=>{delete t.data[e]},find:a=>{const r=t.data[a];return e&&void 0!==r?"function"==typeof structuredClone?structuredClone(r):JSON.parse(JSON.stringify(r)):r}});return t.data=Object.create(null),t}function S(e){var t=typeof e;if(e&&"object"===t&&!(e instanceof Date||e instanceof RegExp)){for(var a=Array.isArray(e)?[]:{},r=Object.keys(e).sort((function(e,t){return e>t?1:-1})),n=r.length;n--;){var o=r[n];a[o]=S(e[o])}return String(e.constructor)+JSON.stringify(a,r)}return t+String(e)}function C(e){e=S(e);for(var t=5381,a=0;a<e.length;)t=33*t^e.charCodeAt(a++);return t}const I=/^\/|\/$/g;function A(e){return t=>{if(t.id)return t.id;const a=e(t);return"string"==typeof a||"number"==typeof a?`${a}`:`${C(a)}`}}const j=A((({baseURL:e="",url:t="",method:a="get",params:r,data:n})=>(e&&(e=e.replace(I,"")),t&&(t=t.replace(I,"")),a&&(a=a.toLowerCase()),{url:e+(e&&t?"/":"")+t,params:r,method:a,data:n})));function E(e,t={}){var a,r,n,o,i,c;const d=e;if(d.defaults.cache)throw new Error("setupCache() should be called only once");if(d.storage=t.storage||x(),!v(d.storage))throw new Error("Use buildStorage() function");return d.waiting=t.waiting||{},d.generateKey=t.generateKey||j,d.headerInterpreter=t.headerInterpreter||s,d.requestInterceptor=t.requestInterceptor||g(d),d.responseInterceptor=t.responseInterceptor||m(d),d.debug=t.debug,d.defaults.cache={update:t.update||{},ttl:null!==(a=t.ttl)&&void 0!==a?a:3e5,methods:t.methods||["get"],cachePredicate:t.cachePredicate||{statusCheck:e=>e>=200&&e<400},etag:null===(r=t.etag)||void 0===r||r,modifiedSince:null!==(n=t.modifiedSince)&&void 0!==n?n:!1===t.etag,interpretHeader:null===(o=t.interpretHeader)||void 0===o||o,cacheTakeover:null===(i=t.cacheTakeover)||void 0===i||i,staleIfError:null===(c=t.staleIfError)||void 0===c||c,override:!1},d.requestInterceptor.apply(),d.responseInterceptor.apply(),d}function O(e,t="axios-cache-"){return w({find:a=>{const r=e.getItem(t+a);return r?JSON.parse(r):void 0},remove:a=>{e.removeItem(t+a)},set:(a,r)=>{const n=()=>e.setItem(t+a,JSON.stringify(r));try{return n()}catch(r){const o=Object.entries(e).filter((e=>e[0].startsWith(t))).map((e=>[e[0],JSON.parse(e[1])]));for(const t of o)"cached"===t[1].state&&y(t[1])&&!b(t[1])&&e.removeItem(t[0]);try{return n()}catch(t){const a=o.sort(((e,t)=>(e[1].createdAt||0)-(t[1].createdAt||0)));for(const t of a){e.removeItem(t[0]);try{return n()}catch(e){}}}e.removeItem(t+a)}}})}return console.error("You are using a development build. Make sure to use the correct build in production\nhttps://axios-cache-interceptor.js.org/#/pages/installing\n\n"),t})()));
!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports.AxiosCacheInterceptor=t():e.AxiosCacheInterceptor=t()}("undefined"!=typeof self?self:this,(()=>(()=>{"use strict";var e={d:(t,a)=>{for(var r in a)e.o(a,r)&&!e.o(t,r)&&Object.defineProperty(t,r,{enumerable:!0,get:a[r]})},o:(e,t)=>Object.prototype.hasOwnProperty.call(e,t),r:e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})}},t={};e.r(t),e.d(t,{Header:()=>s,buildKeyGenerator:()=>E,buildMemoryStorage:()=>S,buildStorage:()=>C,buildWebStorage:()=>R,canStale:()=>w,createCacheResponse:()=>h,createValidateStatus:()=>l,defaultHeaderInterpreter:()=>c,defaultKeyGenerator:()=>O,defaultRequestInterceptor:()=>g,defaultResponseInterceptor:()=>v,isExpired:()=>x,isMethodIn:()=>u,isStorage:()=>b,setupCache:()=>T,testCachePredicate:()=>p,updateCache:()=>m,updateStaleRequest:()=>f});var a=Symbol("cache-parser");function r(e){return("string"==typeof e||"number"==typeof e)&&(e=Number(e))>=0&&e<1/0}function o(e){return!0===e||"number"==typeof e||"string"==typeof e&&"false"!==e}var n=Number;function i(e){var t=Object.defineProperty({},a,{enumerable:!1,value:1});if(!e||"string"!=typeof e)return t;var i=function(e){var t={},a=e.toLowerCase().replace(/\s+/g,"").split(",");for(var r in a){var o,n=a[r].split("=",2);t[n[0]]=null==(o=n[1])||o}return t}(e),s=i["max-age"],c=i["max-stale"],d=i["min-fresh"],l=i["s-maxage"],u=i["stale-if-error"],f=i["stale-while-revalidate"];return o(i.immutable)&&(t.immutable=!0),r(s)&&(t.maxAge=n(s)),r(c)&&(t.maxStale=n(c)),r(d)&&(t.minFresh=n(d)),o(i["must-revalidate"])&&(t.mustRevalidate=!0),o(i["must-understand"])&&(t.mustUnderstand=!0),o(i["no-cache"])&&(t.noCache=!0),o(i["no-store"])&&(t.noStore=!0),o(i["no-transform"])&&(t.noTransform=!0),o(i["only-if-cached"])&&(t.onlyIfCached=!0),o(i.private)&&(t.private=!0),o(i["proxy-revalidate"])&&(t.proxyRevalidate=!0),o(i.public)&&(t.public=!0),r(l)&&(t.sMaxAge=n(l)),r(u)&&(t.staleIfError=n(u)),r(f)&&(t.staleWhileRevalidate=n(f)),t}const s=Object.freeze({IfModifiedSince:"if-modified-since",LastModified:"last-modified",IfNoneMatch:"if-none-match",CacheControl:"cache-control",Pragma:"pragma",ETag:"etag",Expires:"expires",Age:"age",XAxiosCacheEtag:"x-axios-cache-etag",XAxiosCacheLastModified:"x-axios-cache-last-modified",XAxiosCacheStaleIfError:"x-axios-cache-stale-if-error"}),c=e=>{if(!e)return"not enough headers";const t=e[s.CacheControl];if(t){const{noCache:a,noStore:r,maxAge:o,immutable:n,staleWhileRevalidate:c}=i(String(t));if(a||r)return"dont cache";if(n)return{cache:31536e6};if(void 0!==o){const t=e[s.Age];return{cache:t?1e3*(o-Number(t)):1e3*o,stale:void 0!==c?1e3*c:0}}}const a=e[s.Expires];if(a){const e=Date.parse(String(a))-Date.now();return e>=0?{cache:e}:"dont cache"}return"not enough headers"};var d=Symbol();function l(e){return e?t=>e(t)||304===t:e=>e>=200&&e<300||304===e}function u(e="get",t=[]){return e=e.toLowerCase(),t.some((t=>t===e))}function f(e,t){var a;t.headers||(t.headers={});const{etag:r,modifiedSince:o}=t.cache;if(r){const o=!0===r?null===(a=e.data)||void 0===a?void 0:a.headers[s.ETag]:r;o&&(t.headers[s.IfNoneMatch]=o)}o&&(t.headers[s.IfModifiedSince]=!0===o?e.data.headers[s.LastModified]||new Date(e.createdAt).toUTCString():o.toUTCString())}function h(e,t){return 304===e.status&&t?(e.cached=!0,e.data=t.data,e.status=t.status,e.statusText=t.statusText,e.headers=Object.assign(Object.assign({},t.headers),e.headers),t):{data:e.data,status:e.status,statusText:e.statusText,headers:e.headers}}function g(e){const t=async t=>{var a,r,o,n,i,c,h,g,p,m,v,b,y,w,x,C,S,I,A,j,E,O,T;const R=t.id=e.generateKey(t);if(!1===t.cache)return null===(a=e.debug)||void 0===a||a.call(e,{msg:"Ignoring cache because config.cache === false",data:t}),t;if(t.cache=Object.assign(Object.assign({},e.defaults.cache),t.cache),t.cache.cacheTakeover&&(null!==(r=(I=t.headers)[A=s.CacheControl])&&void 0!==r||(I[A]="no-cache"),null!==(o=(j=t.headers)[E=s.Pragma])&&void 0!==o||(j[E]="no-cache"),null!==(n=(O=t.headers)[T=s.Expires])&&void 0!==n||(O[T]="0")),!u(t.method,t.cache.methods))return null===(i=e.debug)||void 0===i||i.call(e,{msg:`Ignored because method (${t.method}) is not in cache.methods (${t.cache.methods})`}),t;let M=await e.storage.get(R,t);const k=t.cache.override;e:if("empty"===M.state||"stale"===M.state||k){if(e.waiting[R]&&!k&&(M=await e.storage.get(R,t),"empty"!==M.state)){null===(c=e.debug)||void 0===c||c.call(e,{id:R,msg:"Waiting list had an deferred for this key, waiting for it to finish"});break e}return e.waiting[R]=function(){var e,t,a=new Promise((function(a,r){e=a,t=r}));return a.resolve=e,a.reject=t,a[d]=1,a}(),e.waiting[R].catch((()=>{})),await e.storage.set(R,{state:"loading",previous:k?M.data?"stale":"empty":M.state,data:M.data,createdAt:k&&!M.createdAt?Date.now():M.createdAt},t),"stale"===M.state&&(f(M,t),null===(h=e.debug)||void 0===h||h.call(e,{id:R,msg:"Updated stale request"})),t.validateStatus=l(t.validateStatus),null===(g=e.debug)||void 0===g||g.call(e,{id:R,msg:"Sending request, waiting for response",data:{overrideCache:k,state:M.state}}),("stale"===M.state||M.data)&&await(null===(m=(p=t.cache).hydrate)||void 0===m?void 0:m.call(p,M)),t}let P;if("loading"===M.state){const a=e.waiting[R];if(!a)return await e.storage.remove(R,t),M.data&&await(null===(b=(v=t.cache).hydrate)||void 0===b?void 0:b.call(v,M)),t;null===(y=e.debug)||void 0===y||y.call(e,{id:R,msg:"Detected concurrent request, waiting for it to finish"});try{P=await a}catch(a){return null===(w=e.debug)||void 0===w||w.call(e,{id:R,msg:"Deferred rejected, requesting again",data:a}),M.data&&await(null===(C=(x=t.cache).hydrate)||void 0===C?void 0:C.call(x,M)),t}}else P=M.data;return t.adapter=()=>Promise.resolve({config:t,data:P.data,headers:P.headers,status:P.status,statusText:P.statusText,cached:!0,id:R}),null===(S=e.debug)||void 0===S||S.call(e,{id:R,msg:"Returning cached response"}),t};return{onFulfilled:t,apply:()=>e.interceptors.request.use(t)}}async function p(e,t){var a;if("function"==typeof t)return t(e);const{statusCheck:r,responseMatch:o,containsHeaders:n}=t;if(r&&!await r(e.status)||o&&!await o(e))return!1;if(n)for(const[t,r]of Object.entries(n))if(!await r(null!==(a=e.headers[t.toLowerCase()])&&void 0!==a?a:e.headers[t]))return!1;return!0}async function m(e,t,a){if("function"==typeof a)return a(t);for(const[r,o]of Object.entries(a)){if("delete"===o){await e.remove(r,t.config);continue}const a=await e.get(r,t.config);if("loading"===a.state)continue;const n=await o(a,t);"delete"!==n?"ignore"!==n&&await e.set(r,n,t.config):await e.remove(r,t.config)}}function v(e){const t=async(t,a)=>{var r;await e.storage.remove(t,a),null===(r=e.waiting[t])||void 0===r||r.reject(),delete e.waiting[t]},a=async a=>{var r,o,n,i,c,d,l,f,g,v,b,y,w;if(!a.config)throw null===(r=e.debug)||void 0===r||r.call(e,{msg:"Response interceptor received an unknown response.",data:a}),a;const x=a.id=null!==(o=(w=a.config).id)&&void 0!==o?o:w.id=e.generateKey(a.config);if(null!==(n=a.cached)&&void 0!==n||(a.cached=!1),a.cached)return null===(i=e.debug)||void 0===i||i.call(e,{id:x,msg:"Returned cached response"}),a;const C=a.config,S=C.cache;if(!S)return null===(c=e.debug)||void 0===c||c.call(e,{id:x,msg:"Response with config.cache falsy",data:a}),Object.assign(Object.assign({},a),{cached:!1});if(S.update&&await m(e.storage,a,S.update),!u(C.method,S.methods))return null===(d=e.debug)||void 0===d||d.call(e,{id:x,msg:`Ignored because method (${C.method}) is not in cache.methods (${S.methods})`,data:{config:C,cacheConfig:S}}),a;const I=await e.storage.get(x,C);if("loading"!==I.state)return null===(l=e.debug)||void 0===l||l.call(e,{id:x,msg:"Response not cached and storage isn't loading",data:{cache:I,response:a}}),a;if(!I.data&&!await p(a,S.cachePredicate))return await t(x,C),null===(f=e.debug)||void 0===f||f.call(e,{id:x,msg:"Cache predicate rejected this response"}),a;for(const e of Object.keys(a.headers))e.startsWith("x-axios-cache")&&delete a.headers[e];S.etag&&!0!==S.etag&&(a.headers[s.XAxiosCacheEtag]=S.etag),S.modifiedSince&&(a.headers[s.XAxiosCacheLastModified]=!0===S.modifiedSince?"use-cache-timestamp":S.modifiedSince.toUTCString());let A,j=S.ttl||-1;if(S.interpretHeader){const r=e.headerInterpreter(a.headers);if("dont cache"===r)return await t(x,C),null===(g=e.debug)||void 0===g||g.call(e,{id:x,msg:"Cache header interpreted as 'dont cache'",data:{cache:I,response:a,expirationTime:r}}),a;"not enough headers"!==r&&("number"==typeof r?j=r:(j=r.cache,A=r.stale))}const E=h(a,I.data);"function"==typeof j&&(j=await j(a)),S.staleIfError&&(a.headers[s.XAxiosCacheStaleIfError]=String(j)),null===(v=e.debug)||void 0===v||v.call(e,{id:x,msg:"Useful response configuration found",data:{cacheConfig:S,cacheResponse:E}});const O={state:"cached",ttl:j,staleTtl:A,createdAt:Date.now(),data:E},T=e.waiting[x];return T&&(T.resolve(O.data),delete e.waiting[x],null===(b=e.debug)||void 0===b||b.call(e,{id:x,msg:"Found waiting deferred(s) and resolved them"})),await e.storage.set(x,O,C),null===(y=e.debug)||void 0===y||y.call(e,{id:x,msg:"Response cached",data:{cache:O,response:a}}),a},r=async a=>{var r,o,n,c,d,l,f;const h=a.config,g=h.id,p=h.cache,m=a.response;if(!p||!g)throw null===(r=e.debug)||void 0===r||r.call(e,{msg:"Web request returned an error but cache handling is not enabled",data:{error:a}}),a;if(!u(h.method,p.methods))throw null===(o=e.debug)||void 0===o||o.call(e,{id:g,msg:`Ignored because method (${h.method}) is not in cache.methods (${p.methods})`,data:{config:h,cacheConfig:p}}),a;const v=await e.storage.get(g,h);if("loading"!==v.state||"stale"!==v.previous)throw await t(g,h),null===(n=e.debug)||void 0===n||n.call(e,{id:g,msg:"Caught an error in the request interceptor",data:{cache:v,error:a,config:h}}),a;if(p.staleIfError){const t=String(null==m?void 0:m.headers[s.CacheControl]),r=t&&i(t).staleIfError,o="function"==typeof p.staleIfError?await p.staleIfError(m,v,a):!0===p.staleIfError&&r?1e3*r:p.staleIfError;if(null===(c=e.debug)||void 0===c||c.call(e,{id:g,msg:"Found cache if stale config for rejected response",data:{error:a,config:h,staleIfError:o}}),!0===o||"number"==typeof o&&v.createdAt+o>Date.now())return null===(d=e.waiting[g])||void 0===d||d.resolve(v.data),delete e.waiting[g],await e.storage.set(g,{state:"stale",createdAt:Date.now(),data:v.data},h),null===(l=e.debug)||void 0===l||l.call(e,{id:g,msg:"staleIfError resolved this response with cached data",data:{error:a,config:h,cache:v}}),{cached:!0,config:h,id:g,data:v.data.data,headers:v.data.headers,status:v.data.status,statusText:v.data.statusText}}throw null===(f=e.debug)||void 0===f||f.call(e,{id:g,msg:"Received an unknown error that could not be handled",data:{error:a,config:h}}),a};return{onFulfilled:a,onRejected:r,apply:()=>e.interceptors.response.use(a,r)}}const b=e=>!!e&&!!e["is-storage"];function y(e){const t=e.data.headers;return s.ETag in t||s.LastModified in t||s.XAxiosCacheEtag in t||s.XAxiosCacheLastModified in t}function w(e){return!String(e.data.headers[s.CacheControl]).includes("must-revalidate")&&(!!y(e)||"cached"===e.state&&void 0!==e.staleTtl&&e.createdAt+e.ttl+e.staleTtl<=Date.now())}function x(e){return void 0!==e.ttl&&e.createdAt+e.ttl<=Date.now()}function C({set:e,find:t,remove:a}){return{"is-storage":1,set:e,remove:a,get:async(r,o)=>{let n=await t(r,o);if(!n)return{state:"empty"};if("empty"===n.state||"loading"===n.state)return n;if("cached"===n.state){if(!x(n))return n;if(!w(n))return await a(r,o),{state:"empty"};n={state:"stale",createdAt:n.createdAt,data:n.data,ttl:void 0!==n.staleTtl?n.staleTtl+n.ttl:void 0},await e(r,n,o)}return x(n)?y(n)?n:(await a(r,o),{state:"empty"}):n}}}function S(e=!1,t=!1){const a=C({set:(e,t)=>{a.data[e]=t},remove:e=>{delete a.data[e]},find:t=>{const r=a.data[t];return e&&void 0!==r?"function"==typeof structuredClone?structuredClone(r):JSON.parse(JSON.stringify(r)):r}});return a.data=Object.create(null),t&&(a.cleaner=setInterval((()=>{const e=Object.keys(a.data);let t,r,o=-1;for(;++o<e.length;)r=e[o],t=a.data[r],"empty"!==t.state?"cached"===t.state&&x(t)&&!w(t)&&a.remove(r):a.remove(r)}),t)),a}function I(e){var t=typeof e;if(e&&"object"===t&&!(e instanceof Date||e instanceof RegExp)){for(var a=Array.isArray(e)?[]:{},r=Object.keys(e).sort((function(e,t){return e>t?1:-1})),o=r.length;o--;){var n=r[o];a[n]=I(e[n])}return String(e.constructor)+JSON.stringify(a,r)}return t+String(e)}function A(e){e=I(e);for(var t=5381,a=0;a<e.length;)t=33*t^e.charCodeAt(a++);return t}const j=/^\/|\/$/g;function E(e){return t=>{if(t.id)return t.id;const a=e(t);return"string"==typeof a||"number"==typeof a?`${a}`:`${A(a)}`}}const O=E((({baseURL:e="",url:t="",method:a="get",params:r,data:o})=>(e&&(e=e.replace(j,"")),t&&(t=t.replace(j,"")),a&&(a=a.toLowerCase()),{url:e+(e&&t?"/":"")+t,params:r,method:a,data:o})));function T(e,t={}){var a,r,o,n,i,s;const d=e;if(d.defaults.cache)throw new Error("setupCache() should be called only once");if(d.storage=t.storage||S(),!b(d.storage))throw new Error("Use buildStorage() function");return d.waiting=t.waiting||{},d.generateKey=t.generateKey||O,d.headerInterpreter=t.headerInterpreter||c,d.requestInterceptor=t.requestInterceptor||g(d),d.responseInterceptor=t.responseInterceptor||v(d),d.debug=t.debug,d.defaults.cache={update:t.update||{},ttl:null!==(a=t.ttl)&&void 0!==a?a:3e5,methods:t.methods||["get","head"],cachePredicate:t.cachePredicate||{statusCheck:e=>[200,203,300,301,302,404,405,410,414,501].includes(e)},etag:null===(r=t.etag)||void 0===r||r,modifiedSince:null!==(o=t.modifiedSince)&&void 0!==o?o:!1===t.etag,interpretHeader:null===(n=t.interpretHeader)||void 0===n||n,cacheTakeover:null===(i=t.cacheTakeover)||void 0===i||i,staleIfError:null===(s=t.staleIfError)||void 0===s||s,override:!1,hydrate:void 0},d.requestInterceptor.apply(),d.responseInterceptor.apply(),d}function R(e,t="axios-cache-"){return C({find:a=>{const r=e.getItem(t+a);return r?JSON.parse(r):void 0},remove:a=>{e.removeItem(t+a)},set:(a,r)=>{const o=()=>e.setItem(t+a,JSON.stringify(r));try{return o()}catch(r){const n=Object.entries(e).filter((e=>e[0].startsWith(t))).map((e=>[e[0],JSON.parse(e[1])]));for(const t of n)"cached"===t[1].state&&x(t[1])&&!w(t[1])&&e.removeItem(t[0]);try{return o()}catch(t){const a=n.sort(((e,t)=>(e[1].createdAt||0)-(t[1].createdAt||0)));for(const t of a){e.removeItem(t[0]);try{return o()}catch(e){}}}e.removeItem(t+a)}}})}return console.error("You are using a development build. Make sure to use the correct build in production\nhttps://axios-cache-interceptor.js.org/guide/getting-started\n\n"),t})()));
//# sourceMappingURL=index.bundle.js.map
import type { AxiosInstance, AxiosInterceptorManager, AxiosRequestConfig, AxiosResponse, AxiosResponseHeaders } from 'axios';
import type { CacheInstance, CacheProperties } from './cache';
/**
* A slightly changed than the original axios response. Containing information about the
* cache and other needed properties.
*
* @template R The type returned by this response
* @template D The type that the request body was
* @see https://axios-cache-interceptor.js.org/config/response-object
*/
export type CacheAxiosResponse<R = any, D = any> = AxiosResponse<R, D> & {
config: CacheRequestConfig<R, D>;
/** The id used for this request. if config specified an id, the id will be returned */
/**
* The [Request ID](https://axios-cache-interceptor.js.org/guide/request-id) used in
* this request.
*
* It may have been generated by the [Key
* Generator](https://axios-cache-interceptor.js.org/guide/request-id#custom-generator)
* or a custom one provided by
* [`config.id`](https://axios-cache-interceptor.js.org/config/request-specifics#id)
*
* @see https://axios-cache-interceptor.js.org/config/response-object#id
*/
id: string;
/** A simple boolean to check whether this request was cached or not */
/**
* A simple boolean indicating if the request returned data from the cache or from the
* network call.
*
* This does not indicated if the request was capable of being cached or not, as options
* like
* [`cache.override`](https://axios-cache-interceptor.js.org/config/request-specifics#cache-override)
* may have been enabled.
*
* @see https://axios-cache-interceptor.js.org/config/response-object#cached
*/
cached: boolean;

@@ -22,12 +46,24 @@ };

/**
* An id for this request, if this request is used in cache, only the last request made
* with this id will be returned.
* The [Request ID](https://axios-cache-interceptor.js.org/guide/request-id) used in
* this request.
*
* @default undefined
* It may have been generated by the [Key
* Generator](https://axios-cache-interceptor.js.org/guide/request-id#custom-generator)
* or a custom one provided by
* [`config.id`](https://axios-cache-interceptor.js.org/config/request-specifics#id)
*
* @default 'auto generated by the current key generator'
* @see https://axios-cache-interceptor.js.org/config/response-object#id
*/
id?: string;
/**
* All cache options for the request.
* The cache option available through the request config is where all the cache
* customization happens.
*
* False means ignore everything about cache, for this request.
* Setting the `cache` property to `false` will disable the cache for this request.
*
* This does not mean that the current cache will be excluded from the storage.
*
* @default 'inherits from global configuration'
* @see https://axios-cache-interceptor.js.org/config/response-object#cache
*/

@@ -44,5 +80,3 @@ cache?: false | Partial<CacheProperties<R, D>>;

*
* @see AxiosInstance
* @see CacheRequestConfig
* @see CacheInstance
* @see https://axios-cache-interceptor.js.org/guide/getting-started
*/

@@ -49,0 +83,0 @@ export interface AxiosCacheInstance extends CacheInstance, AxiosInstance {

import type { Method } from 'axios';
import type { Deferred } from 'fast-defer';
import type { HeadersInterpreter } from '../header/types';
import type { HeaderInterpreter } from '../header/types';
import type { AxiosInterceptor } from '../interceptors/build';
import type { AxiosStorage, CachedResponse } from '../storage/types';
import type { AxiosStorage, CachedResponse, CachedStorageValue, LoadingStorageValue, StaleStorageValue } from '../storage/types';
import type { CachePredicate, CacheUpdater, KeyGenerator, StaleIfErrorPredicate } from '../util/types';

@@ -23,63 +23,111 @@ import type { CacheAxiosResponse, CacheRequestConfig } from './axios';

* @default 1000 * 60 * 5 // 5 Minutes
* @see https://axios-cache-interceptor.js.org/config/request-specifics#cache-ttl
*/
ttl: number | ((response: CacheAxiosResponse<R, D>) => number | Promise<number>);
/**
* If this interceptor should configure the cache from the request cache header When
* used, the ttl property is ignored
* If activated, when the response is received, the `ttl` property will be inferred from
* the requests headers. As described in the MDN docs and HTML specification.
*
* See the actual implementation of the
* [`interpretHeader`](https://github.com/arthurfiorette/axios-cache-interceptor/blob/main/src/header/interpreter.ts)
* method for more information.
*
* @default true
* @see https://axios-cache-interceptor.js.org/config/request-specifics#cache-interpretheader
*/
interpretHeader: boolean;
/**
* If this interceptor should include some headers in the request to tell any possible
* adapter / client that only we should use cache mechanisms to this request.
* As most of our cache strategies depends on well known defined HTTP headers, most
* browsers also use those headers to define their own cache strategies and storages.
*
* When your requested routes includes `Cache-Control` in their responses, you may end
* up with we and your browser caching the response, resulting in a **double layer of
* cache**.
*
* This option solves this by including some predefined headers in the request, that
* should tell any client / adapter to not cache the response, thus only we will cache
* it.
*
* _These are headers used in our specific request, it won't affect any other request or
* response that the server may handle._*
*
* Headers included:
*
* - `Cache-Control: no-cache`
* - `Pragma: no-cache`
* - `Expires: 0`
*
* Learn more at
* [#437](https://github.com/arthurfiorette/axios-cache-interceptor/issues/437#issuecomment-1361262194)
* and in this [StackOverflow](https://stackoverflow.com/a/62781874/14681561) answer.
*
* @default true
* @see https://axios-cache-interceptor.js.org/config/request-specifics#cache-cachetakeover
*/
cacheTakeover: boolean;
/**
* All methods that should be cached.
* Specifies which methods we should handle and cache. This is where you can enable
* caching to `POST`, `PUT`, `DELETE` and other methods, as the default is only `GET`.
*
* We use `methods` in a per-request configuration setup because sometimes you have
* exceptions to the method rule.
*
* @default ['get']
* @see https://axios-cache-interceptor.js.org/config/request-specifics#cache-methods
*/
methods: Lowercase<Method>[];
/**
* The function to check if the response code permit being cached.
* An object or function that will be tested against the response to indicate if it can
* be cached.
*
* @default {statusCheck: (status) => status >= 200 && status < 400}
* @default { statusCheck: (status) => [200, 203, 300, 301, 302, 404, 405, 410, 414, 501].includes(status) }
* @see https://axios-cache-interceptor.js.org/config/request-specifics#cache-cachepredicate
*/
cachePredicate: CachePredicate<R, D>;
/**
* Once the request is resolved, this specifies what requests should we change the
* cache. Can be used to update the request or delete other caches.
* Once the request is resolved, this specifies what other responses should change their
* cache. Can be used to update the request or delete other caches. It is a simple
* `Record` with the request id.
*
* This is independent if the request made was cached or not.
* Here's an example with some basic login:
*
* If an provided id represents and loading cache, he will be ignored.
*
* The id used is the same as the id on `CacheRequestConfig['id']`, auto-generated or
* not.
*
* **Using a function instead of an object is supported but not recommended, as it's
* Using a function instead of an object is supported but not recommended, as it's
* better to just consume the response normally and write your own code after it. But
* it`s here in case you need it.**
* it`s here in case you need it.
*
* @default {{}}
* @see https://axios-cache-interceptor.js.org/config/request-specifics#cache-update
*/
update: CacheUpdater<R, D>;
/**
* If the request should handle `ETag` and `If-None-Match` support. Use a string to
* force a custom value or true to use the response ETag
* If the request should handle
* [`ETag`](https://developer.mozilla.org/pt-BR/docs/Web/HTTP/Headers/ETag) and
* [`If-None-Match
* support`](https://developer.mozilla.org/pt-BR/docs/Web/HTTP/Headers/If-None-Match).
* Use a string to force a custom static value or true to use the previous response
* ETag.
*
* To use `true` (automatic ETag handling), `interpretHeader` option must be set to
* `true`.
*
* @default true
* @link https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/ETag
* @see https://axios-cache-interceptor.js.org/config/request-specifics#cache-etag
*/
etag: string | boolean;
/**
* Use `If-Modified-Since` header in this request. Use a date to force a custom value or
* true to use the last cached timestamp. If never cached before, the header is not
* set.
* Use
* [`If-Modified-Since`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/If-Modified-Since)
* header in this request. Use a date to force a custom static value or true to use the
* last cached timestamp.
*
* If never cached before, the header is not set.
*
* If `interpretHeader` is set and a
* [`Last-Modified`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Last-Modified)
* header is sent to us, then value from that header is used, otherwise cache creation
* timestamp will be sent in
* [`If-Modified-Since`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/If-Modified-Since).
*
* @default false // The opposite of the resulting `etag` option.
* @link https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/If-Modified-Since
* @see https://axios-cache-interceptor.js.org/config/request-specifics#cache-modifiedsince
*/

@@ -92,22 +140,16 @@ modifiedSince: Date | boolean;

*
* **Note**: If the response is treated as error because of invalid status code _(like
* from AxiosRequestConfig#invalidateStatus)_, and this ends up `true`, the cache will
* be preserved over the "invalid" request. So, if you want to preserve the response,
* you can use this predicate:
* **If the response is treated as error because of invalid status code _(like when
* using
* [statusCheck](https://axios-cache-interceptor.js.org/config/request-specifics#cache-cachepredicate))_,
* and this ends up `true`, the cache will be preserved over the "invalid" request.**
*
* ```js
* const customPredicate = (response, cache, error) => {
* // Return false if has a response
* return !response;
* };
* ```
* Types:
*
* Possible types:
*
* - `number` -> the max time (in seconds) that the cache can be reused.
* - `boolean` -> `false` disables and `true` enables with infinite time.
* - `boolean` -> `false` disables and `true` enables with infinite time if no value is
* present on `stale-if-error` in Cache-Control.
* - `function` -> a predicate that can return `number` or `boolean` as described above.
*
* @default true
* @link https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control#stale-if-error
* @see https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control#stale-if-error
*/

@@ -125,10 +167,48 @@ staleIfError: StaleIfErrorPredicate<R, D>;

* @default false
* @see https://axios-cache-interceptor.js.org/config/request-specifics#cache-override
*/
override: boolean;
/**
* Asynchronously called when a network request is needed to resolve the data, but an
* older one **and probably expired** cache exists. Its with the current data **BEFORE**
* the network travel starts, so you can use it to temporarily update your UI with
* expired data before the network returns.
*
* Hydrating your components with old data before the network resolves with the newer
* one is better than _flickering_ your entire UI. This is even better when dealing with
* slower networks and persisted cache, like for mobile apps.
*
* If the request can return cached data, as no extensive network travel is needed, the
* hydrate **IS NOT CALLED**, as the axios promise will be resolved instantly.
*
* @default undefined
* @see https://axios-cache-interceptor.js.org/config/request-specifics#cache-hydrate
*/
hydrate: undefined | ((cache: (LoadingStorageValue & {
previous: 'stale';
}) | CachedStorageValue | StaleStorageValue) => void | Promise<void>);
};
/**
* These are properties that are used and shared by the entire application.
*
* ```ts
* const axios = setupCache(axios, OPTIONS);
* ```
*
* The `setupCache` function receives global options and all [request
* specifics](https://axios-cache-interceptor.js.org/config/request-specifics) ones too.
* This way, you can customize the defaults for all requests.
*
* @see https://axios-cache-interceptor.js.org/config/request-specifics
*/
export interface CacheInstance {
/**
* The storage to save the cache data. Defaults to an in-memory storage.
* A storage interface is the entity responsible for saving, retrieving and serializing
* data received from network and requested when a axios call is made.
*
* See the [Storages](https://axios-cache-interceptor.js.org/guide/storages) page for
* more information.
*
* @default buildMemoryStorage
* @see https://axios-cache-interceptor.js.org/config#storage
*/

@@ -138,37 +218,87 @@ storage: AxiosStorage;

* The function used to create different keys for each request. Defaults to a function
* that priorizes the id, and if not specified, a string is generated using the method,
* baseURL, params, and url
* that priorizes the id, and if not specified, a string is generated using the
* `method`, `baseURL`, `params`, `data` and `url`.
*
* You can learn on how to use them on the [Request
* ID](https://axios-cache-interceptor.js.org/guide/request-id#custom-generator) page.
*
* @default defaultKeyGenerator
* @see https://axios-cache-interceptor.js.org/config#generatekey
*/
generateKey: KeyGenerator;
/**
* A simple object that holds all deferred objects until it is resolved or rejected.
* A simple object that will hold a promise for each pending request. Used to handle
* concurrent requests.
*
* Can be used to listen when a request is cached or not.
* You'd normally not need to change this, but it is exposed in case you need to use it
* as some sort of listener of know when a request is waiting for other to finish.
*
* @default { }
* @see https://axios-cache-interceptor.js.org/config#waiting
*/
waiting: Record<string, Deferred<CachedResponse>>;
/**
* The function to parse and interpret response headers. Only used if
* cache.interpretHeader is true.
* The function used to interpret all headers from a request and determine a time to
* live (`ttl`) number.
*
* **Many REST backends returns some variation of `Cache-Control: no-cache` or
* `Cache-Control: no-store` headers, which tell us to ignore caching at all. You shall
* disable `headerInterpreter` for those requests.**
*
* **If the debug mode prints `Cache header interpreted as 'dont cache'` this is
* probably the reason.**
*
* The possible returns are:
*
* - `'dont cache'`: the request will not be cached.
* - `'not enough headers'`: the request will find other ways to determine the TTL value.
* - `number`: used as the TTL value.
*
* @default defaultHeaderInterpreter
* @see https://axios-cache-interceptor.js.org/config#headerinterpreter
*/
headerInterpreter: HeadersInterpreter;
headerInterpreter: HeaderInterpreter;
/**
* The request interceptor that will be used to handle the cache.
* The function that will be used to intercept the request before it is sent to the
* axios adapter.
*
* It is the main function of this library, as it is the bridge between the axios
* request and the cache.
*
* _It wasn't meant to be changed, but if you need to, you can do it by passing a new
* function to this property._*
*
* See its code for more information
* [here](https://github.com/arthurfiorette/axios-cache-interceptor/tree/main/src/interceptors).
*
* @default defaultRequestInterceptor
* @see https://axios-cache-interceptor.js.org/config#requestinterceptor
*/
requestInterceptor: AxiosInterceptor<CacheRequestConfig<unknown, unknown>>;
/**
* The response interceptor that will be used to handle the cache.
* The function that will be used to intercept the request after it is returned by the
* axios adapter.
*
* It is the second most important function of this library, as it is the bridge between
* the axios response and the cache.
*
* _It wasn't meant to be changed, but if you need to, you can do it by passing a new
* function to this property._*
*
* See its code for more information
* [here](https://github.com/arthurfiorette/axios-cache-interceptor/tree/main/src/interceptors).
*
* @default defaultResponseInterceptor
* @see https://axios-cache-interceptor.js.org/config#responseinterceptor
*/
responseInterceptor: AxiosInterceptor<CacheAxiosResponse<unknown, unknown>>;
/**
* Logs useful information in the console
* The debug option will print debug information in the console. It is good if you need
* to trace any undesired behavior or issue. You can enable it by setting `debug` to a
* function that receives an string and returns nothing.
*
* **Note**: This is only available with development mode enabled
* Read the [Debugging](https://axios-cache-interceptor.js.org/guide/debugging) page for
* the complete guide.
*
* @default {console.log}
* @default undefined
* @see https://axios-cache-interceptor.js.org/#/pages/development-mode

@@ -180,9 +310,11 @@ */

* An object with any possible type that can be used to log and debug information in
* `development` mode (a.k.a `__ACI_DEV__ === true`)
* `development` mode _(a.k.a `__ACI_DEV__ === true`)_
*
* @see https://axios-cache-interceptor.js.org/#/pages/development-mode
*/
export type DebugObject = Partial<{
id: string;
msg: string;
data: unknown;
}>;
export type DebugObject = {
id?: string;
msg?: string;
data?: unknown;
};
//# sourceMappingURL=cache.d.ts.map

@@ -8,36 +8,16 @@ import type { AxiosInstance } from 'axios';

*
* @example
*
* ```ts
* import Axios from 'axios';
* import { setupCache, AxiosCacheInstance } from 'axios-cache-interceptor';
* const axios = setupCache(axios, OPTIONS);
* ```
*
* // instance will have our custom typings from the return of this function
* const instance = setupCache(
* Axios.create({
* // Axios options
* }),
* {
* // Axios-cache-interceptor options
* }
* );
* The `setupCache` function receives global options and all [request
* specifics](https://axios-cache-interceptor.js.org/config/request-specifics) ones too.
* This way, you can customize the defaults for all requests.
*
* // OR
*
* const instance = axios.create({
* // Axios options
* }) as AxiosCacheInstance;
*
* // As this functions returns the same axios instance but only with
* // different typings, you can ignore the function return.
* setupCache(instance, {
* // Axios-cache-interceptor options
* });
* ```
*
* @param axios The already created axios instance
* @param config The config for the caching interceptors
* @returns The same instance with extended typescript types.
* @see https://axios-cache-interceptor.js.org/config
*/
export declare function setupCache(axios: AxiosInstance, options?: CacheOptions): AxiosCacheInstance;
//# sourceMappingURL=create.d.ts.map

@@ -1,3 +0,3 @@

import type { HeadersInterpreter } from './types';
export declare const defaultHeaderInterpreter: HeadersInterpreter;
import type { HeaderInterpreter } from './types';
export declare const defaultHeaderInterpreter: HeaderInterpreter;
//# sourceMappingURL=interpreter.d.ts.map

@@ -1,22 +0,31 @@

import type { AxiosRequestHeaders } from 'axios';
import type { CacheAxiosResponse } from '../cache/axios';
export type InterpreterResult = 'dont cache' | 'not enough headers' | number;
/**
* Interpret all http headers to determina a time to live.
*
* @param header The header object to interpret.
* @returns `false` if cache should not be used. `undefined` when provided headers was not
* enough to determine a valid value. Or a `number` containing the number of
* **milliseconds** to cache the response.
* The possible values are:
* - `'dont cache'`: the request will not be cached.
* - `'not enough headers'`: the request will find other ways to determine the TTL value.
* - `number`: used as the TTL value.
* - `{ cache: number, stale: number }: used as the TTL value and stale TTL value`
*/
export type HeadersInterpreter = (headers?: CacheAxiosResponse['headers']) => InterpreterResult;
export type InterpreterResult = 'dont cache' | 'not enough headers' | number | {
cache: number;
stale?: number;
};
/**
* Interpret a single string header
* - If activated, when the response is received, the `ttl` property will be inferred from
* the requests headers. As described in the MDN docs and HTML specification.
*
* @param header The header string to interpret.
* The possible returns are:
*
* - `'dont cache'`: the request will not be cached.
* - `'not enough headers'`: the request will find other ways to determine the TTL value.
* - `number`: used as the TTL value.
* - `{ cache: number, stale: number }: used as the TTL value and stale TTL value`
*
* @param header The header object to interpret.
* @returns `false` if cache should not be used. `undefined` when provided headers was not
* enough to determine a valid value. Or a `number` containing the number of
* **milliseconds** to cache the response.
* @see https://axios-cache-interceptor.js.org/config#headerinterpreter
*/
export type HeaderInterpreter = (header: string, headers: AxiosRequestHeaders) => InterpreterResult;
export type HeaderInterpreter = (headers?: CacheAxiosResponse['headers']) => InterpreterResult;
//# sourceMappingURL=types.d.ts.map

@@ -1,1 +0,1 @@

!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports.AxiosCacheInterceptor=t():e.AxiosCacheInterceptor=t()}("undefined"!=typeof self?self:this,(function(){return function(){"use strict";var e={d:function(t,r){for(var n in r)e.o(r,n)&&!e.o(t,n)&&Object.defineProperty(t,n,{enumerable:!0,get:r[n]})},o:function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},r:function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})}},t={};e.r(t),e.d(t,{Header:function(){return i},buildKeyGenerator:function(){return j},buildMemoryStorage:function(){return I},buildStorage:function(){return C},buildWebStorage:function(){return P},canStale:function(){return x},createCacheResponse:function(){return p},createValidateStatus:function(){return l},defaultHeaderInterpreter:function(){return c},defaultKeyGenerator:function(){return T},defaultRequestInterceptor:function(){return g},defaultResponseInterceptor:function(){return y},isExpired:function(){return S},isMethodIn:function(){return h},isStorage:function(){return w},setupCache:function(){return M},testCachePredicate:function(){return m},updateCache:function(){return b},updateStaleRequest:function(){return v}});var r=Symbol("cache-parser");function n(e){return("string"==typeof e||"number"==typeof e)&&(e=Number(e))>=0&&e<1/0}function a(e){return!0===e||"number"==typeof e||"string"==typeof e&&"false"!==e}var o=Number;var i=Object.freeze({IfModifiedSince:"if-modified-since",LastModified:"last-modified",IfNoneMatch:"if-none-match",CacheControl:"cache-control",Pragma:"pragma",ETag:"etag",Expires:"expires",Age:"age",XAxiosCacheEtag:"x-axios-cache-etag",XAxiosCacheLastModified:"x-axios-cache-last-modified",XAxiosCacheStaleIfError:"x-axios-cache-stale-if-error"}),c=function(e){if(!e)return"not enough headers";var t=e[i.CacheControl];if(t){var c=function(e){var t=Object.defineProperty({},r,{enumerable:!1,value:1});if(!e||"string"!=typeof e)return t;var i=function(e){var t={},r=e.toLowerCase().replace(/\s+/g,"").split(",");for(var n in r){var a,o=r[n].split("=",2);t[o[0]]=null==(a=o[1])||a}return t}(e),c=i["max-age"],s=i["max-stale"],u=i["min-fresh"],d=i["s-maxage"],f=i["stale-if-error"],l=i["stale-while-revalidate"];return a(i.immutable)&&(t.immutable=!0),n(c)&&(t.maxAge=o(c)),n(s)&&(t.maxStale=o(s)),n(u)&&(t.minFresh=o(u)),a(i["must-revalidate"])&&(t.mustRevalidate=!0),a(i["must-understand"])&&(t.mustUnderstand=!0),a(i["no-cache"])&&(t.noCache=!0),a(i["no-store"])&&(t.noStore=!0),a(i["no-transform"])&&(t.noTransform=!0),a(i["only-if-cached"])&&(t.onlyIfCached=!0),a(i.private)&&(t.private=!0),a(i["proxy-revalidate"])&&(t.proxyRevalidate=!0),a(i.public)&&(t.public=!0),n(d)&&(t.sMaxAge=o(d)),n(f)&&(t.staleIfError=o(f)),n(l)&&(t.staleWhileRevalidate=o(l)),t}(String(t)),s=c.noCache,u=c.noStore,d=c.mustRevalidate,f=c.maxAge,l=c.immutable;if(s||u)return"dont cache";if(l)return 31536e6;if(d)return 0;if(void 0!==f){var h=e[i.Age];return h?1e3*(f-Number(h)):1e3*f}}var v=e[i.Expires];if(v){var p=Date.parse(String(v))-Date.now();return p>=0?p:"dont cache"}return"not enough headers"};var s=function(){return s=Object.assign||function(e){for(var t,r=1,n=arguments.length;r<n;r++)for(var a in t=arguments[r])Object.prototype.hasOwnProperty.call(t,a)&&(e[a]=t[a]);return e},s.apply(this,arguments)};function u(e,t,r,n){return new(r||(r=Promise))((function(a,o){function i(e){try{s(n.next(e))}catch(e){o(e)}}function c(e){try{s(n.throw(e))}catch(e){o(e)}}function s(e){var t;e.done?a(e.value):(t=e.value,t instanceof r?t:new r((function(e){e(t)}))).then(i,c)}s((n=n.apply(e,t||[])).next())}))}function d(e,t){var r,n,a,o,i={label:0,sent:function(){if(1&a[0])throw a[1];return a[1]},trys:[],ops:[]};return o={next:c(0),throw:c(1),return:c(2)},"function"==typeof Symbol&&(o[Symbol.iterator]=function(){return this}),o;function c(c){return function(s){return function(c){if(r)throw new TypeError("Generator is already executing.");for(;o&&(o=0,c[0]&&(i=0)),i;)try{if(r=1,n&&(a=2&c[0]?n.return:c[0]?n.throw||((a=n.return)&&a.call(n),0):n.next)&&!(a=a.call(n,c[1])).done)return a;switch(n=0,a&&(c=[2&c[0],a.value]),c[0]){case 0:case 1:a=c;break;case 4:return i.label++,{value:c[1],done:!1};case 5:i.label++,n=c[1],c=[0];continue;case 7:c=i.ops.pop(),i.trys.pop();continue;default:if(!(a=i.trys,(a=a.length>0&&a[a.length-1])||6!==c[0]&&2!==c[0])){i=0;continue}if(3===c[0]&&(!a||c[1]>a[0]&&c[1]<a[3])){i.label=c[1];break}if(6===c[0]&&i.label<a[1]){i.label=a[1],a=c;break}if(a&&i.label<a[2]){i.label=a[2],i.ops.push(c);break}a[2]&&i.ops.pop(),i.trys.pop();continue}c=t.call(e,i)}catch(e){c=[6,e],n=0}finally{r=a=0}if(5&c[0])throw c[1];return{value:c[0]?c[1]:void 0,done:!0}}([c,s])}}}Object.create;Object.create;var f=Symbol();function l(e){return e?function(t){return e(t)||304===t}:function(e){return e>=200&&e<300||304===e}}function h(e,t){return void 0===e&&(e="get"),void 0===t&&(t=[]),e=e.toLowerCase(),t.some((function(t){return t===e}))}function v(e,t){var r;t.headers||(t.headers={});var n=t.cache,a=n.etag,o=n.modifiedSince;if(a){var c=!0===a?null===(r=e.data)||void 0===r?void 0:r.headers[i.ETag]:a;c&&(t.headers[i.IfNoneMatch]=c)}o&&(t.headers[i.IfModifiedSince]=!0===o?e.data.headers[i.LastModified]||new Date(e.createdAt).toUTCString():o.toUTCString())}function p(e,t){return 304===e.status&&t?(e.cached=!0,e.data=t.data,e.status=t.status,e.statusText=t.statusText,e.headers=s(s({},t.headers),e.headers),t):{data:e.data,status:e.status,statusText:e.statusText,headers:e.headers}}function g(e){var t=this,r=function(r){return u(t,void 0,void 0,(function(){var t,n,a,o,c,u,p,g,m,b,y,w,x,S;return d(this,(function(d){switch(d.label){case 0:return t=r.id=e.generateKey(r),!1===r.cache?[2,r]:(r.cache=s(s({},e.defaults.cache),r.cache),r.cache.cacheTakeover&&(null!==(u=(m=r.headers)[b=i.CacheControl])&&void 0!==u||(m[b]="no-cache"),null!==(p=(y=r.headers)[w=i.Pragma])&&void 0!==p||(y[w]="no-cache"),null!==(g=(x=r.headers)[S=i.Expires])&&void 0!==g||(x[S]="0")),h(r.method,r.cache.methods)?[4,e.storage.get(t,r)]:[2,r]);case 1:return n=d.sent(),a=r.cache.override,"empty"===n.state||"stale"===n.state||a?!e.waiting[t]||a?[3,3]:[4,e.storage.get(t,r)]:[3,5];case 2:if("empty"!==(n=d.sent()).state)return[3,5];d.label=3;case 3:return e.waiting[t]=function(){var e,t,r=new Promise((function(r,n){e=r,t=n}));return r.resolve=e,r.reject=t,r[f]=1,r}(),e.waiting[t].catch((function(){})),[4,e.storage.set(t,{state:"loading",previous:a?n.data?"stale":"empty":n.state,data:n.data,createdAt:a&&!n.createdAt?Date.now():n.createdAt},r)];case 4:return d.sent(),"stale"===n.state&&v(n,r),r.validateStatus=l(r.validateStatus),[2,r];case 5:return"loading"!==n.state?[3,12]:(c=e.waiting[t])?[3,7]:[4,e.storage.remove(t,r)];case 6:return d.sent(),[2,r];case 7:0,d.label=8;case 8:return d.trys.push([8,10,,11]),[4,c];case 9:return o=d.sent(),[3,11];case 10:return d.sent(),[2,r];case 11:return[3,13];case 12:o=n.data,d.label=13;case 13:return r.adapter=function(){return Promise.resolve({config:r,data:o.data,headers:o.headers,status:o.status,statusText:o.statusText,cached:!0,id:t})},[2,r]}}))}))};return{onFulfilled:r,apply:function(){return e.interceptors.request.use(r)}}}function m(e,t){var r;return u(this,void 0,void 0,(function(){var n,a,o,i,c,s,u,f,l,h;return d(this,(function(d){switch(d.label){case 0:return"function"==typeof t?[2,t(e)]:(n=t.statusCheck,a=t.responseMatch,o=t.containsHeaders,(c=n)?[4,n(e.status)]:[3,2]);case 1:c=!d.sent(),d.label=2;case 2:return(i=c)?[3,5]:(s=a)?[4,a(e)]:[3,4];case 3:s=!d.sent(),d.label=4;case 4:i=s,d.label=5;case 5:if(i)return[2,!1];if(!o)return[3,9];u=0,f=Object.entries(o),d.label=6;case 6:return u<f.length?(l=f[u],h=l[0],[4,(0,l[1])(null!==(r=e.headers[h.toLowerCase()])&&void 0!==r?r:e.headers[h])]):[3,9];case 7:if(!d.sent())return[2,!1];d.label=8;case 8:return u++,[3,6];case 9:return[2,!0]}}))}))}function b(e,t,r){return u(this,void 0,void 0,(function(){var n,a,o,i,c,s,u;return d(this,(function(d){switch(d.label){case 0:if("function"==typeof r)return[2,r(t)];n=0,a=Object.entries(r),d.label=1;case 1:return n<a.length?(o=a[n],i=o[0],"delete"!==(c=o[1])?[3,3]:[4,e.remove(i,t.config)]):[3,10];case 2:return d.sent(),[3,9];case 3:return[4,e.get(i,t.config)];case 4:return"loading"===(s=d.sent()).state?[3,9]:[4,c(s,t)];case 5:return"delete"!==(u=d.sent())?[3,7]:[4,e.remove(i,t.config)];case 6:return d.sent(),[3,9];case 7:return"ignore"===u?[3,9]:[4,e.set(i,u,t.config)];case 8:d.sent(),d.label=9;case 9:return n++,[3,1];case 10:return[2]}}))}))}function y(e){var t=this,r=function(r,n){return u(t,void 0,void 0,(function(){var t;return d(this,(function(a){switch(a.label){case 0:return[4,e.storage.remove(r,n)];case 1:return a.sent(),null===(t=e.waiting[r])||void 0===t||t.reject(),delete e.waiting[r],[2]}}))}))},n=function(n){return u(t,void 0,void 0,(function(){var t,a,o,c,u,f,l,v,g,y,w,x,S,C,I,A;return d(this,(function(d){switch(d.label){case 0:return t=n.id=null!==(C=(A=n.config).id)&&void 0!==C?C:A.id=e.generateKey(n.config),null!==(I=n.cached)&&void 0!==I||(n.cached=!1),n.cached?[2,n]:(a=n.config,(o=a.cache)?o.update?[4,b(e.storage,n,o.update)]:[3,2]:[2,s(s({},n),{cached:!1})]);case 1:d.sent(),d.label=2;case 2:return h(a.method,o.methods)?[4,e.storage.get(t,a)]:[2,n];case 3:return"loading"!==(c=d.sent()).state?[2,n]:(u=!c.data)?[4,m(n,o.cachePredicate)]:[3,5];case 4:u=!d.sent(),d.label=5;case 5:return u?[4,r(t,a)]:[3,7];case 6:return d.sent(),[2,n];case 7:for(f=0,l=Object.keys(n.headers);f<l.length;f++)(v=l[f]).startsWith("x-axios-cache")&&delete n.headers[v];return o.etag&&!0!==o.etag&&(n.headers[i.XAxiosCacheEtag]=o.etag),o.modifiedSince&&(n.headers[i.XAxiosCacheLastModified]=!0===o.modifiedSince?"use-cache-timestamp":o.modifiedSince.toUTCString()),g=o.ttl||-1,o.interpretHeader?"dont cache"!==(y=e.headerInterpreter(n.headers))?[3,9]:[4,r(t,a)]:[3,10];case 8:return d.sent(),[2,n];case 9:g="not enough headers"===y?g:y,d.label=10;case 10:return w=p(n,c.data),"function"!=typeof g?[3,12]:[4,g(n)];case 11:g=d.sent(),d.label=12;case 12:return o.staleIfError&&(n.headers[i.XAxiosCacheStaleIfError]=String(g)),x={state:"cached",ttl:g,createdAt:Date.now(),data:w},(S=e.waiting[t])&&(S.resolve(x.data),delete e.waiting[t]),[4,e.storage.set(t,x,a)];case 13:return d.sent(),[2,n]}}))}))},a=function(n){return u(t,void 0,void 0,(function(){var t,a,o,i,c,s,u;return d(this,(function(d){switch(d.label){case 0:if(t=n.config,a=t.id,!(o=t.cache)||!a)throw n;if(!h(t.method,o.methods))throw n;return[4,e.storage.get(a,t)];case 1:return"loading"===(i=d.sent()).state&&"stale"===i.previous?[3,3]:[4,r(a,t)];case 2:throw d.sent(),n;case 3:return o.staleIfError?"function"!=typeof o.staleIfError?[3,5]:[4,o.staleIfError(n.response,i,n)]:[3,8];case 4:return s=d.sent(),[3,6];case 5:s=o.staleIfError,d.label=6;case 6:return!0===(c=s)||"number"==typeof c&&i.createdAt+c>Date.now()?(null===(u=e.waiting[a])||void 0===u||u.resolve(i.data),delete e.waiting[a],[4,e.storage.set(a,{state:"stale",createdAt:Date.now(),data:i.data},t)]):[3,8];case 7:return d.sent(),[2,{cached:!0,config:t,id:a,data:i.data.data,headers:i.data.headers,status:i.data.status,statusText:i.data.statusText}];case 8:throw n}}))}))};return{onFulfilled:n,onRejected:a,apply:function(){return e.interceptors.response.use(n,a)}}}var w=function(e){return!!e&&!!e["is-storage"]};function x(e){var t=e.data.headers;return i.ETag in t||i.LastModified in t||i.XAxiosCacheEtag in t||i.XAxiosCacheStaleIfError in t||i.XAxiosCacheLastModified in t}function S(e){return e.createdAt+e.ttl<=Date.now()}function C(e){var t,r=this,n=e.set,a=e.find,o=e.remove;return(t={})["is-storage"]=1,t.set=n,t.remove=o,t.get=function(e,t){return u(r,void 0,void 0,(function(){var r,i;return d(this,(function(c){switch(c.label){case 0:return[4,a(e,t)];case 1:return(r=c.sent())?"cached"===r.state&&S(r)?x(r)?(i={state:"stale",createdAt:r.createdAt,data:r.data},[4,n(e,i,t)]):[3,3]:[2,r]:[2,{state:"empty"}];case 2:return c.sent(),[2,i];case 3:return[4,o(e,t)];case 4:return c.sent(),[2,{state:"empty"}]}}))}))},t}function I(e){void 0===e&&(e=!1);var t=C({set:function(e,r){t.data[e]=r},remove:function(e){delete t.data[e]},find:function(r){var n=t.data[r];return e&&void 0!==n?"function"==typeof structuredClone?structuredClone(n):JSON.parse(JSON.stringify(n)):n}});return t.data=Object.create(null),t}function A(e){var t=typeof e;if(e&&"object"===t&&!(e instanceof Date||e instanceof RegExp)){for(var r=Array.isArray(e)?[]:{},n=Object.keys(e).sort((function(e,t){return e>t?1:-1})),a=n.length;a--;){var o=n[a];r[o]=A(e[o])}return String(e.constructor)+JSON.stringify(r,n)}return t+String(e)}function E(e){e=A(e);for(var t=5381,r=0;r<e.length;)t=33*t^e.charCodeAt(r++);return t}var O=/^\/|\/$/g;function j(e){return function(t){if(t.id)return t.id;var r=e(t);return"".concat("string"==typeof r||"number"==typeof r?r:E(r))}}var T=j((function(e){var t=e.baseURL,r=void 0===t?"":t,n=e.url,a=void 0===n?"":n,o=e.method,i=void 0===o?"get":o,c=e.params,s=e.data;return r&&(r=r.replace(O,"")),a&&(a=a.replace(O,"")),i&&(i=i.toLowerCase()),{url:r+(r&&a?"/":"")+a,params:c,method:i,data:s}}));function M(e,t){var r,n,a,o,i,s;void 0===t&&(t={});var u=e;if(u.defaults.cache)throw new Error("setupCache() should be called only once");if(u.storage=t.storage||I(),!w(u.storage))throw new Error("Use buildStorage() function");return u.waiting=t.waiting||{},u.generateKey=t.generateKey||T,u.headerInterpreter=t.headerInterpreter||c,u.requestInterceptor=t.requestInterceptor||g(u),u.responseInterceptor=t.responseInterceptor||y(u),u.debug=t.debug,u.defaults.cache={update:t.update||{},ttl:null!==(r=t.ttl)&&void 0!==r?r:3e5,methods:t.methods||["get"],cachePredicate:t.cachePredicate||{statusCheck:function(e){return e>=200&&e<400}},etag:null===(n=t.etag)||void 0===n||n,modifiedSince:null!==(a=t.modifiedSince)&&void 0!==a?a:!1===t.etag,interpretHeader:null===(o=t.interpretHeader)||void 0===o||o,cacheTakeover:null===(i=t.cacheTakeover)||void 0===i||i,staleIfError:null===(s=t.staleIfError)||void 0===s||s,override:!1},u.requestInterceptor.apply(),u.responseInterceptor.apply(),u}function P(e,t){return void 0===t&&(t="axios-cache-"),C({find:function(r){var n=e.getItem(t+r);return n?JSON.parse(n):void 0},remove:function(r){e.removeItem(t+r)},set:function(r,n){var a=function(){return e.setItem(t+r,JSON.stringify(n))};try{return a()}catch(n){for(var o=Object.entries(e).filter((function(e){return e[0].startsWith(t)})).map((function(e){return[e[0],JSON.parse(e[1])]})),i=0,c=o;i<c.length;i++){var s=c[i];"cached"===s[1].state&&S(s[1])&&!x(s[1])&&e.removeItem(s[0])}try{return a()}catch(t){for(var u=o.sort((function(e,t){return(e[1].createdAt||0)-(t[1].createdAt||0)})),d=0,f=u;d<f.length;d++){var l=f[d];e.removeItem(l[0]);try{return a()}catch(e){}}}e.removeItem(t+r)}}})}return t}()}));
!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports.AxiosCacheInterceptor=t():e.AxiosCacheInterceptor=t()}("undefined"!=typeof self?self:this,(function(){return function(){"use strict";var e={d:function(t,r){for(var a in r)e.o(r,a)&&!e.o(t,a)&&Object.defineProperty(t,a,{enumerable:!0,get:r[a]})},o:function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},r:function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})}},t={};e.r(t),e.d(t,{Header:function(){return s},buildKeyGenerator:function(){return M},buildMemoryStorage:function(){return E},buildStorage:function(){return A},buildWebStorage:function(){return L},canStale:function(){return C},createCacheResponse:function(){return g},createValidateStatus:function(){return h},defaultHeaderInterpreter:function(){return i},defaultKeyGenerator:function(){return P},defaultRequestInterceptor:function(){return m},defaultResponseInterceptor:function(){return w},isExpired:function(){return I},isMethodIn:function(){return v},isStorage:function(){return x},setupCache:function(){return k},testCachePredicate:function(){return b},updateCache:function(){return y},updateStaleRequest:function(){return p}});var r=Symbol("cache-parser");function a(e){return("string"==typeof e||"number"==typeof e)&&(e=Number(e))>=0&&e<1/0}function n(e){return!0===e||"number"==typeof e||"string"==typeof e&&"false"!==e}var o=Number;function c(e){var t=Object.defineProperty({},r,{enumerable:!1,value:1});if(!e||"string"!=typeof e)return t;var c=function(e){var t={},r=e.toLowerCase().replace(/\s+/g,"").split(",");for(var a in r){var n,o=r[a].split("=",2);t[o[0]]=null==(n=o[1])||n}return t}(e),s=c["max-age"],i=c["max-stale"],u=c["min-fresh"],d=c["s-maxage"],l=c["stale-if-error"],f=c["stale-while-revalidate"];return n(c.immutable)&&(t.immutable=!0),a(s)&&(t.maxAge=o(s)),a(i)&&(t.maxStale=o(i)),a(u)&&(t.minFresh=o(u)),n(c["must-revalidate"])&&(t.mustRevalidate=!0),n(c["must-understand"])&&(t.mustUnderstand=!0),n(c["no-cache"])&&(t.noCache=!0),n(c["no-store"])&&(t.noStore=!0),n(c["no-transform"])&&(t.noTransform=!0),n(c["only-if-cached"])&&(t.onlyIfCached=!0),n(c.private)&&(t.private=!0),n(c["proxy-revalidate"])&&(t.proxyRevalidate=!0),n(c.public)&&(t.public=!0),a(d)&&(t.sMaxAge=o(d)),a(l)&&(t.staleIfError=o(l)),a(f)&&(t.staleWhileRevalidate=o(f)),t}var s=Object.freeze({IfModifiedSince:"if-modified-since",LastModified:"last-modified",IfNoneMatch:"if-none-match",CacheControl:"cache-control",Pragma:"pragma",ETag:"etag",Expires:"expires",Age:"age",XAxiosCacheEtag:"x-axios-cache-etag",XAxiosCacheLastModified:"x-axios-cache-last-modified",XAxiosCacheStaleIfError:"x-axios-cache-stale-if-error"}),i=function(e){if(!e)return"not enough headers";var t=e[s.CacheControl];if(t){var r=c(String(t)),a=r.noCache,n=r.noStore,o=r.maxAge,i=r.immutable,u=r.staleWhileRevalidate;if(a||n)return"dont cache";if(i)return{cache:31536e6};if(void 0!==o){var d=e[s.Age];return{cache:d?1e3*(o-Number(d)):1e3*o,stale:void 0!==u?1e3*u:0}}}var l=e[s.Expires];if(l){var f=Date.parse(String(l))-Date.now();return f>=0?{cache:f}:"dont cache"}return"not enough headers"};var u=function(){return u=Object.assign||function(e){for(var t,r=1,a=arguments.length;r<a;r++)for(var n in t=arguments[r])Object.prototype.hasOwnProperty.call(t,n)&&(e[n]=t[n]);return e},u.apply(this,arguments)};function d(e,t,r,a){return new(r||(r=Promise))((function(n,o){function c(e){try{i(a.next(e))}catch(e){o(e)}}function s(e){try{i(a.throw(e))}catch(e){o(e)}}function i(e){var t;e.done?n(e.value):(t=e.value,t instanceof r?t:new r((function(e){e(t)}))).then(c,s)}i((a=a.apply(e,t||[])).next())}))}function l(e,t){var r,a,n,o,c={label:0,sent:function(){if(1&n[0])throw n[1];return n[1]},trys:[],ops:[]};return o={next:s(0),throw:s(1),return:s(2)},"function"==typeof Symbol&&(o[Symbol.iterator]=function(){return this}),o;function s(s){return function(i){return function(s){if(r)throw new TypeError("Generator is already executing.");for(;o&&(o=0,s[0]&&(c=0)),c;)try{if(r=1,a&&(n=2&s[0]?a.return:s[0]?a.throw||((n=a.return)&&n.call(a),0):a.next)&&!(n=n.call(a,s[1])).done)return n;switch(a=0,n&&(s=[2&s[0],n.value]),s[0]){case 0:case 1:n=s;break;case 4:return c.label++,{value:s[1],done:!1};case 5:c.label++,a=s[1],s=[0];continue;case 7:s=c.ops.pop(),c.trys.pop();continue;default:if(!(n=c.trys,(n=n.length>0&&n[n.length-1])||6!==s[0]&&2!==s[0])){c=0;continue}if(3===s[0]&&(!n||s[1]>n[0]&&s[1]<n[3])){c.label=s[1];break}if(6===s[0]&&c.label<n[1]){c.label=n[1],n=s;break}if(n&&c.label<n[2]){c.label=n[2],c.ops.push(s);break}n[2]&&c.ops.pop(),c.trys.pop();continue}s=t.call(e,c)}catch(e){s=[6,e],a=0}finally{r=n=0}if(5&s[0])throw s[1];return{value:s[0]?s[1]:void 0,done:!0}}([s,i])}}}Object.create;Object.create;var f=Symbol();function h(e){return e?function(t){return e(t)||304===t}:function(e){return e>=200&&e<300||304===e}}function v(e,t){return void 0===e&&(e="get"),void 0===t&&(t=[]),e=e.toLowerCase(),t.some((function(t){return t===e}))}function p(e,t){var r;t.headers||(t.headers={});var a=t.cache,n=a.etag,o=a.modifiedSince;if(n){var c=!0===n?null===(r=e.data)||void 0===r?void 0:r.headers[s.ETag]:n;c&&(t.headers[s.IfNoneMatch]=c)}o&&(t.headers[s.IfModifiedSince]=!0===o?e.data.headers[s.LastModified]||new Date(e.createdAt).toUTCString():o.toUTCString())}function g(e,t){return 304===e.status&&t?(e.cached=!0,e.data=t.data,e.status=t.status,e.statusText=t.statusText,e.headers=u(u({},t.headers),e.headers),t):{data:e.data,status:e.status,statusText:e.statusText,headers:e.headers}}function m(e){var t=this,r=function(r){return d(t,void 0,void 0,(function(){var t,a,n,o,c,i,d,g,m,b,y,w,x,S,C,I,A,E,T,O;return l(this,(function(l){switch(l.label){case 0:return t=r.id=e.generateKey(r),!1===r.cache?[2,r]:(r.cache=u(u({},e.defaults.cache),r.cache),r.cache.cacheTakeover&&(null!==(i=(C=r.headers)[I=s.CacheControl])&&void 0!==i||(C[I]="no-cache"),null!==(d=(A=r.headers)[E=s.Pragma])&&void 0!==d||(A[E]="no-cache"),null!==(g=(T=r.headers)[O=s.Expires])&&void 0!==g||(T[O]="0")),v(r.method,r.cache.methods)?[4,e.storage.get(t,r)]:[2,r]);case 1:return a=l.sent(),n=r.cache.override,"empty"===a.state||"stale"===a.state||n?!e.waiting[t]||n?[3,3]:[4,e.storage.get(t,r)]:[3,7];case 2:if("empty"!==(a=l.sent()).state)return[3,7];l.label=3;case 3:return e.waiting[t]=function(){var e,t,r=new Promise((function(r,a){e=r,t=a}));return r.resolve=e,r.reject=t,r[f]=1,r}(),e.waiting[t].catch((function(){})),[4,e.storage.set(t,{state:"loading",previous:n?a.data?"stale":"empty":a.state,data:a.data,createdAt:n&&!a.createdAt?Date.now():a.createdAt},r)];case 4:return l.sent(),"stale"===a.state&&p(a,r),r.validateStatus=h(r.validateStatus),"stale"===a.state||a.data?[4,null===(b=(m=r.cache).hydrate)||void 0===b?void 0:b.call(m,a)]:[3,6];case 5:l.sent(),l.label=6;case 6:return[2,r];case 7:return"loading"!==a.state?[3,18]:(c=e.waiting[t])?[3,11]:[4,e.storage.remove(t,r)];case 8:return l.sent(),a.data?[4,null===(w=(y=r.cache).hydrate)||void 0===w?void 0:w.call(y,a)]:[3,10];case 9:l.sent(),l.label=10;case 10:return[2,r];case 11:0,l.label=12;case 12:return l.trys.push([12,14,,17]),[4,c];case 13:return o=l.sent(),[3,17];case 14:return l.sent(),a.data?[4,null===(S=(x=r.cache).hydrate)||void 0===S?void 0:S.call(x,a)]:[3,16];case 15:l.sent(),l.label=16;case 16:return[2,r];case 17:return[3,19];case 18:o=a.data,l.label=19;case 19:return r.adapter=function(){return Promise.resolve({config:r,data:o.data,headers:o.headers,status:o.status,statusText:o.statusText,cached:!0,id:t})},[2,r]}}))}))};return{onFulfilled:r,apply:function(){return e.interceptors.request.use(r)}}}function b(e,t){var r;return d(this,void 0,void 0,(function(){var a,n,o,c,s,i,u,d,f,h;return l(this,(function(l){switch(l.label){case 0:return"function"==typeof t?[2,t(e)]:(a=t.statusCheck,n=t.responseMatch,o=t.containsHeaders,(s=a)?[4,a(e.status)]:[3,2]);case 1:s=!l.sent(),l.label=2;case 2:return(c=s)?[3,5]:(i=n)?[4,n(e)]:[3,4];case 3:i=!l.sent(),l.label=4;case 4:c=i,l.label=5;case 5:if(c)return[2,!1];if(!o)return[3,9];u=0,d=Object.entries(o),l.label=6;case 6:return u<d.length?(f=d[u],h=f[0],[4,(0,f[1])(null!==(r=e.headers[h.toLowerCase()])&&void 0!==r?r:e.headers[h])]):[3,9];case 7:if(!l.sent())return[2,!1];l.label=8;case 8:return u++,[3,6];case 9:return[2,!0]}}))}))}function y(e,t,r){return d(this,void 0,void 0,(function(){var a,n,o,c,s,i,u;return l(this,(function(d){switch(d.label){case 0:if("function"==typeof r)return[2,r(t)];a=0,n=Object.entries(r),d.label=1;case 1:return a<n.length?(o=n[a],c=o[0],"delete"!==(s=o[1])?[3,3]:[4,e.remove(c,t.config)]):[3,10];case 2:return d.sent(),[3,9];case 3:return[4,e.get(c,t.config)];case 4:return"loading"===(i=d.sent()).state?[3,9]:[4,s(i,t)];case 5:return"delete"!==(u=d.sent())?[3,7]:[4,e.remove(c,t.config)];case 6:return d.sent(),[3,9];case 7:return"ignore"===u?[3,9]:[4,e.set(c,u,t.config)];case 8:d.sent(),d.label=9;case 9:return a++,[3,1];case 10:return[2]}}))}))}function w(e){var t=this,r=function(r,a){return d(t,void 0,void 0,(function(){var t;return l(this,(function(n){switch(n.label){case 0:return[4,e.storage.remove(r,a)];case 1:return n.sent(),null===(t=e.waiting[r])||void 0===t||t.reject(),delete e.waiting[r],[2]}}))}))},a=function(a){return d(t,void 0,void 0,(function(){var t,n,o,c,i,d,f,h,p,m,w,x,S,C,I,A,E;return l(this,(function(l){switch(l.label){case 0:return a.config,t=a.id=null!==(I=(E=a.config).id)&&void 0!==I?I:E.id=e.generateKey(a.config),null!==(A=a.cached)&&void 0!==A||(a.cached=!1),a.cached?[2,a]:(n=a.config,(o=n.cache)?o.update?[4,y(e.storage,a,o.update)]:[3,2]:[2,u(u({},a),{cached:!1})]);case 1:l.sent(),l.label=2;case 2:return v(n.method,o.methods)?[4,e.storage.get(t,n)]:[2,a];case 3:return"loading"!==(c=l.sent()).state?[2,a]:(i=!c.data)?[4,b(a,o.cachePredicate)]:[3,5];case 4:i=!l.sent(),l.label=5;case 5:return i?[4,r(t,n)]:[3,7];case 6:return l.sent(),[2,a];case 7:for(d=0,f=Object.keys(a.headers);d<f.length;d++)(h=f[d]).startsWith("x-axios-cache")&&delete a.headers[h];return o.etag&&!0!==o.etag&&(a.headers[s.XAxiosCacheEtag]=o.etag),o.modifiedSince&&(a.headers[s.XAxiosCacheLastModified]=!0===o.modifiedSince?"use-cache-timestamp":o.modifiedSince.toUTCString()),p=o.ttl||-1,o.interpretHeader?"dont cache"!==(w=e.headerInterpreter(a.headers))?[3,9]:[4,r(t,n)]:[3,10];case 8:return l.sent(),[2,a];case 9:"not enough headers"!==w&&("number"==typeof w?p=w:(p=w.cache,m=w.stale)),l.label=10;case 10:return x=g(a,c.data),"function"!=typeof p?[3,12]:[4,p(a)];case 11:p=l.sent(),l.label=12;case 12:return o.staleIfError&&(a.headers[s.XAxiosCacheStaleIfError]=String(p)),S={state:"cached",ttl:p,staleTtl:m,createdAt:Date.now(),data:x},(C=e.waiting[t])&&(C.resolve(S.data),delete e.waiting[t]),[4,e.storage.set(t,S,n)];case 13:return l.sent(),[2,a]}}))}))},n=function(a){return d(t,void 0,void 0,(function(){var t,n,o,i,u,d,f,h,p,g;return l(this,(function(l){switch(l.label){case 0:if(t=a.config,n=t.id,o=t.cache,i=a.response,!o||!n)throw a;if(!v(t.method,o.methods))throw a;return[4,e.storage.get(n,t)];case 1:return"loading"===(u=l.sent()).state&&"stale"===u.previous?[3,3]:[4,r(n,t)];case 2:throw l.sent(),a;case 3:return o.staleIfError?(d=String(null==i?void 0:i.headers[s.CacheControl]),f=d&&c(d).staleIfError,"function"!=typeof o.staleIfError?[3,5]:[4,o.staleIfError(i,u,a)]):[3,8];case 4:return p=l.sent(),[3,6];case 5:p=!0===o.staleIfError&&f?1e3*f:o.staleIfError,l.label=6;case 6:return!0===(h=p)||"number"==typeof h&&u.createdAt+h>Date.now()?(null===(g=e.waiting[n])||void 0===g||g.resolve(u.data),delete e.waiting[n],[4,e.storage.set(n,{state:"stale",createdAt:Date.now(),data:u.data},t)]):[3,8];case 7:return l.sent(),[2,{cached:!0,config:t,id:n,data:u.data.data,headers:u.data.headers,status:u.data.status,statusText:u.data.statusText}];case 8:throw a}}))}))};return{onFulfilled:a,onRejected:n,apply:function(){return e.interceptors.response.use(a,n)}}}var x=function(e){return!!e&&!!e["is-storage"]};function S(e){var t=e.data.headers;return s.ETag in t||s.LastModified in t||s.XAxiosCacheEtag in t||s.XAxiosCacheLastModified in t}function C(e){return!String(e.data.headers[s.CacheControl]).includes("must-revalidate")&&(!!S(e)||"cached"===e.state&&void 0!==e.staleTtl&&e.createdAt+e.ttl+e.staleTtl<=Date.now())}function I(e){return void 0!==e.ttl&&e.createdAt+e.ttl<=Date.now()}function A(e){var t,r=this,a=e.set,n=e.find,o=e.remove;return(t={})["is-storage"]=1,t.set=a,t.remove=o,t.get=function(e,t){return d(r,void 0,void 0,(function(){var r;return l(this,(function(c){switch(c.label){case 0:return[4,n(e,t)];case 1:return(r=c.sent())?"empty"===r.state||"loading"===r.state?[2,r]:"cached"!==r.state?[3,5]:I(r)?C(r)?[3,3]:[4,o(e,t)]:[2,r]:[2,{state:"empty"}];case 2:return c.sent(),[2,{state:"empty"}];case 3:return r={state:"stale",createdAt:r.createdAt,data:r.data,ttl:void 0!==r.staleTtl?r.staleTtl+r.ttl:void 0},[4,a(e,r,t)];case 4:c.sent(),c.label=5;case 5:return I(r)?S(r)?[2,r]:[4,o(e,t)]:[2,r];case 6:return c.sent(),[2,{state:"empty"}]}}))}))},t}function E(e,t){void 0===e&&(e=!1),void 0===t&&(t=!1);var r=A({set:function(e,t){r.data[e]=t},remove:function(e){delete r.data[e]},find:function(t){var a=r.data[t];return e&&void 0!==a?"function"==typeof structuredClone?structuredClone(a):JSON.parse(JSON.stringify(a)):a}});return r.data=Object.create(null),t&&(r.cleaner=setInterval((function(){for(var e,t,a=Object.keys(r.data),n=-1;++n<a.length;)t=a[n],"empty"!==(e=r.data[t]).state?"cached"===e.state&&I(e)&&!C(e)&&r.remove(t):r.remove(t)}),t)),r}function T(e){var t=typeof e;if(e&&"object"===t&&!(e instanceof Date||e instanceof RegExp)){for(var r=Array.isArray(e)?[]:{},a=Object.keys(e).sort((function(e,t){return e>t?1:-1})),n=a.length;n--;){var o=a[n];r[o]=T(e[o])}return String(e.constructor)+JSON.stringify(r,a)}return t+String(e)}function O(e){e=T(e);for(var t=5381,r=0;r<e.length;)t=33*t^e.charCodeAt(r++);return t}var j=/^\/|\/$/g;function M(e){return function(t){if(t.id)return t.id;var r=e(t);return"".concat("string"==typeof r||"number"==typeof r?r:O(r))}}var P=M((function(e){var t=e.baseURL,r=void 0===t?"":t,a=e.url,n=void 0===a?"":a,o=e.method,c=void 0===o?"get":o,s=e.params,i=e.data;return r&&(r=r.replace(j,"")),n&&(n=n.replace(j,"")),c&&(c=c.toLowerCase()),{url:r+(r&&n?"/":"")+n,params:s,method:c,data:i}}));function k(e,t){var r,a,n,o,c,s;void 0===t&&(t={});var u=e;if(u.defaults.cache)throw new Error("setupCache() should be called only once");if(u.storage=t.storage||E(),!x(u.storage))throw new Error("Use buildStorage() function");return u.waiting=t.waiting||{},u.generateKey=t.generateKey||P,u.headerInterpreter=t.headerInterpreter||i,u.requestInterceptor=t.requestInterceptor||m(u),u.responseInterceptor=t.responseInterceptor||w(u),u.debug=t.debug,u.defaults.cache={update:t.update||{},ttl:null!==(r=t.ttl)&&void 0!==r?r:3e5,methods:t.methods||["get","head"],cachePredicate:t.cachePredicate||{statusCheck:function(e){return[200,203,300,301,302,404,405,410,414,501].includes(e)}},etag:null===(a=t.etag)||void 0===a||a,modifiedSince:null!==(n=t.modifiedSince)&&void 0!==n?n:!1===t.etag,interpretHeader:null===(o=t.interpretHeader)||void 0===o||o,cacheTakeover:null===(c=t.cacheTakeover)||void 0===c||c,staleIfError:null===(s=t.staleIfError)||void 0===s||s,override:!1,hydrate:void 0},u.requestInterceptor.apply(),u.responseInterceptor.apply(),u}function L(e,t){return void 0===t&&(t="axios-cache-"),A({find:function(r){var a=e.getItem(t+r);return a?JSON.parse(a):void 0},remove:function(r){e.removeItem(t+r)},set:function(r,a){var n=function(){return e.setItem(t+r,JSON.stringify(a))};try{return n()}catch(a){for(var o=Object.entries(e).filter((function(e){return e[0].startsWith(t)})).map((function(e){return[e[0],JSON.parse(e[1])]})),c=0,s=o;c<s.length;c++){var i=s[c];"cached"===i[1].state&&I(i[1])&&!C(i[1])&&e.removeItem(i[0])}try{return n()}catch(t){for(var u=o.sort((function(e,t){return(e[1].createdAt||0)-(t[1].createdAt||0)})),d=0,l=u;d<l.length;d++){var f=l[d];e.removeItem(f[0]);try{return n()}catch(e){}}}e.removeItem(t+r)}}})}return t}()}));
import type { CacheRequestConfig } from '../cache/axios';
import type { MaybePromise } from '../util/types';
import type { AxiosStorage, CachedStorageValue, StorageValue } from './types';
import type { AxiosStorage, CachedStorageValue, StaleStorageValue, StorageValue } from './types';
/** Returns true if the provided object was created from {@link buildStorage} function. */

@@ -12,3 +12,3 @@ export declare const isStorage: (obj: unknown) => obj is AxiosStorage;

*/
export declare function isExpired(value: CachedStorageValue): boolean;
export declare function isExpired(value: CachedStorageValue | StaleStorageValue): boolean;
export type BuildStorage = Omit<AxiosStorage, 'get'> & {

@@ -21,2 +21,3 @@ /**

* @param currentRequest The current {@link CacheRequestConfig}, if any
* @see https://axios-cache-interceptor.js.org/guide/storages#buildstorage
*/

@@ -26,4 +27,8 @@ find: (key: string, currentRequest?: CacheRequestConfig) => MaybePromise<StorageValue | undefined>;

/**
* Builds a custom storage.
* All integrated storages are wrappers around the `buildStorage` function. External
* libraries use it and if you want to build your own, `buildStorage` is the way to go!
*
* The exported `buildStorage` function abstracts the storage interface and requires a
* super simple object to build the storage.
*
* **Note**: You can only create an custom storage with this function.

@@ -42,4 +47,6 @@ *

* ```
*
* @see https://axios-cache-interceptor.js.org/guide/storages#buildstorage
*/
export declare function buildStorage({ set, find, remove }: BuildStorage): AxiosStorage;
//# sourceMappingURL=build.d.ts.map

@@ -26,7 +26,12 @@ import type { AxiosStorage, StorageValue } from './types';

* mutating the original data outside the `set()` method.
*
* @param {number | false} cleanupInterval The interval in milliseconds to run a
* setInterval job of cleaning old entries. If false, the job will not be created. Disabled is default
*/
export declare function buildMemoryStorage(cloneData?: boolean): MemoryStorage;
export declare function buildMemoryStorage(cloneData?: boolean, cleanupInterval?: number | false): MemoryStorage;
export type MemoryStorage = AxiosStorage & {
data: Record<string, StorageValue>;
/** The job responsible to cleaning old entries */
cleaner: ReturnType<typeof setInterval>;
};
//# sourceMappingURL=memory.d.ts.map

@@ -14,3 +14,4 @@ import type { CacheAxiosResponse, CacheRequestConfig } from '../cache/axios';

data: CachedResponse;
ttl?: undefined;
ttl?: number;
staleTtl?: undefined;
createdAt: number;

@@ -26,15 +27,20 @@ state: 'stale';

ttl: number;
staleTtl?: number;
createdAt: number;
state: 'cached';
};
export type LoadingStorageValue = {
export type LoadingStorageValue = LoadingEmptiedStorageValue | LoadingStaledStorageValue;
export type LoadingEmptiedStorageValue = {
data?: undefined;
ttl?: undefined;
staleTtl?: undefined;
createdAt?: undefined;
state: 'loading';
previous: 'empty';
} | {
};
export type LoadingStaledStorageValue = {
state: 'loading';
data: CachedResponse;
ttl?: undefined;
staleTtl?: undefined;
createdAt: number;

@@ -46,2 +52,3 @@ previous: 'stale';

ttl?: undefined;
staleTtl?: undefined;
/** Defined when the state is cached */

@@ -52,17 +59,7 @@ createdAt?: undefined;

/**
* A storage implementation that stores data in memory.
* A storage interface is the entity responsible for saving, retrieving and serializing
* data received from network and requested when a axios call is made.
*
* **You can create yours with {@link buildStorage} function**
*
* @example
*
* ```js
* const myStorage = buildStorage({
* find: () => {...},
* set: () => {...},
* remove: () => {...}
* });
*
* const axios = setupCache(axios, { storage: myStorage });
* ```
* @default buildMemoryStorage
* @see https://axios-cache-interceptor.js.org/guide/storages
*/

@@ -78,2 +75,3 @@ export type AxiosStorage = {

* @param currentRequest The current {@link CacheRequestConfig}, if any
* @see https://axios-cache-interceptor.js.org/guide/storages#buildstorage
*/

@@ -86,2 +84,3 @@ set: (key: string, value: NotEmptyStorageValue, currentRequest?: CacheRequestConfig) => MaybePromise<void>;

* @param currentRequest The current {@link CacheRequestConfig}, if any
* @see https://axios-cache-interceptor.js.org/guide/storages#buildstorage
*/

@@ -93,3 +92,3 @@ remove: (key: string, currentRequest?: CacheRequestConfig) => MaybePromise<void>;

*
* If the provided `find()` method returned null, this will map it to a `'empty'`
* If the internal `find()` method returned null, this will map it to a `'empty'`
* storage value.

@@ -100,2 +99,3 @@ *

* @returns The saved value for the given key.
* @see https://axios-cache-interceptor.js.org/guide/storages#buildstorage
*/

@@ -102,0 +102,0 @@ get: (key: string, currentRequest?: CacheRequestConfig) => MaybePromise<StorageValue>;

{
"name": "axios-cache-interceptor",
"version": "1.0.1",
"version": "1.1.0",
"description": "Cache interceptor for axios",
"keywords": [
"axios",
"cache",
"interceptor",
"adapter",
"http",
"plugin",
"wrapper"
],
"homepage": "https://axios-cache-interceptor.js.org",
"bugs": "https://github.com/arthurfiorette/axios-cache-interceptor/issues",
"repository": "https://github.com/arthurfiorette/axios-cache-interceptor.git",
"funding": "https://github.com/ArthurFiorette/axios-cache-interceptor?sponsor=1",
"license": "MIT",
"main": "./dist/index.cjs",
"types": "./dist/index.d.ts",
"module": "./dist/index.mjs",
"author": "Arthur Fiorette <npm@arthur.place>",
"sideEffects": false,
"exports": {

@@ -23,32 +35,10 @@ ".": {

},
"main": "./dist/index.cjs",
"jsdelivr": "./dist/index.bundle.js",
"unpkg": "./dist/index.bundle.js",
"sideEffects": false,
"runkitExampleFilename": "./examples/runkit.js",
"scripts": {
"build": "sh build/build.sh",
"test": "jest --coverage",
"check": "sh build/check.sh",
"format": "prettier --write .",
"lint": "eslint . --ext .ts",
"version": "auto-changelog -p && git add CHANGELOG.md",
"benchmark": "cd benchmark && yarn start",
"docs:dev": "vitepress dev docs --port 1227",
"docs:build": "vitepress build docs",
"docs:serve": "vitepress serve docs"
"module": "./dist/index.mjs",
"types": "./dist/index.d.ts",
"resolutions": {
"colors": "1.4.0"
},
"funding": "https://github.com/ArthurFiorette/axios-cache-interceptor?sponsor=1",
"repository": "https://github.com/arthurfiorette/axios-cache-interceptor.git",
"author": "Arthur Fiorette <npm@arthur.place>",
"bugs": "https://github.com/arthurfiorette/axios-cache-interceptor/issues",
"homepage": "https://axios-cache-interceptor.js.org",
"keywords": [
"axios",
"cache",
"interceptor",
"adapter",
"http",
"plugin",
"wrapper"
],
"dependencies": {

@@ -62,2 +52,3 @@ "cache-parser": "^1.2.4",

"@types/jest": "^29.2.4",
"@types/node": "^18.13.0",
"@types/webpack": "^5.28.0",

@@ -80,3 +71,3 @@ "@typescript-eslint/eslint-plugin": "^5.50.0",

"tslib": "^2.3.1",
"typescript": "^4.9.5",
"typescript": "^5.0.4",
"vitepress": "^1.0.0-alpha.45",

@@ -89,9 +80,20 @@ "webpack": "^5.66.0",

},
"packageManager": "yarn@1.22.19",
"resolutions": {
"colors": "1.4.0"
},
"packageManager": "pnpm@7.27.0",
"engines": {
"node": ">=12"
},
"runkitExampleFilename": "./examples/runkit.js",
"scripts": {
"benchmark": "cd benchmark && pnpm start",
"build": "sh build/build.sh",
"check": "sh build/check.sh",
"docs:build": "vitepress build docs",
"docs:dev": "vitepress dev docs --port 1227",
"docs:serve": "vitepress serve docs",
"format": "prettier --write .",
"preinstall": "npx only-allow pnpm",
"lint": "eslint . --ext .ts",
"test": "jest --verbose --coverage",
"version": "auto-changelog -p && cp CHANGELOG.md docs/src/others/changelog.md && git add CHANGELOG.md docs/src/others/changelog.md"
}
}
}
<p align="center">
<i>
Help axios-cache-interceptor grow! Star and share this amazing repo with your friends and co-workers!
</i>
<b>Using this package?</b> Please consider <a href="https://github.com/sponsors/arthurfiorette" target="_blank">donating</a> to support my open source work ❤️
<br />
<sup>
Help axios-cache-interceptor grow! Star and share this amazing repository with your friends and co-workers!
</sup>
</p>

@@ -9,23 +11,47 @@

[![Issues](https://img.shields.io/github/issues/arthurfiorette/axios-cache-interceptor?logo=github&label=Issues)](https://github.com/arthurfiorette/axios-cache-interceptor/issues)
[![Stars](https://img.shields.io/github/stars/arthurfiorette/axios-cache-interceptor?logo=github&label=Stars)](https://github.com/arthurfiorette/axios-cache-interceptor/stargazers)
[![License](https://img.shields.io/github/license/arthurfiorette/axios-cache-interceptor?logo=githu&label=License)](https://github.com/arthurfiorette/axios-cache-interceptor/blob/main/LICENSE)
[![Try on Runkit](https://img.shields.io/badge/try%20on-RunKit-brightgreen?logo=runkit&logoColor=e83e8c)](https://npm.runkit.com/axios-cache-interceptor)
[![Codecov](https://codecov.io/gh/arthurfiorette/axios-cache-interceptor/branch/main/graph/badge.svg?token=ML0KGCU0VM)](https://codecov.io/gh/arthurfiorette/axios-cache-interceptor)
[![Downloads](https://img.shields.io/npm/dw/axios-cache-interceptor?style=flat)](https://www.npmjs.com/package/axios-cache-interceptor)
[![Bundlephobia](https://img.shields.io/bundlephobia/minzip/axios-cache-interceptor/latest?style=flat)](https://bundlephobia.com/package/axios-cache-interceptor@latest)
[![Packagephobia](https://packagephobia.com/badge?p=axios-cache-interceptor@latest)](https://packagephobia.com/result?p=axios-cache-interceptor@latest)
[![FOSSA Status](https://app.fossa.com/api/projects/git%2Bgithub.com%2Farthurfiorette%2Faxios-cache-interceptor.svg?type=shield)](https://app.fossa.com/projects/git%2Bgithub.com%2Farthurfiorette%2Faxios-cache-interceptor?ref=badge_shield)
[![Join the chat at https://gitter.im/axios-cache-interceptor/community](https://badges.gitter.im/axios-cache-interceptor/community.svg)](https://gitter.im/axios-cache-interceptor/community?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
<p align="center" title="We need a designer :)">
<a href="https://axios-cache-interceptor.js.org" target="_blank" rel="noopener noreferrer">
<img src="docs/src/public/rocket.png" width="180" alt="Axios Cache Interceptor logo" />
</a>
</p>
<br />
<h3 align="center">
<b>⚡Axios Cache Interceptor</b> is a small and efficient cache interceptor for axios.
<br />
<br />
</h3>
<p align="center">
<a title="MIT license" target="_blank" href="https://github.com/arthurfiorette/axios-cache-interceptor/blob/main/LICENSE"><img alt="License" src="https://img.shields.io/github/license/arthurfiorette/axios-cache-interceptor?color=bfb434"></a>
<a title="Codecov" target="_blank" href="https://app.codecov.io/gh/arthurfiorette/axios-cache-interceptor"><img alt="Codecov" src="https://img.shields.io/codecov/c/github/arthurfiorette/axios-cache-interceptor?token=ML0KGCU0VM&color=d2a72d"></a>
<a title="NPM Package" target="_blank" href="https://www.npmjs.com/package/axios-cache-interceptor"><img alt="Downloads" src="https://img.shields.io/npm/dw/axios-cache-interceptor?style=flat&color=de8f2e"></a>
<a title="Bundle size" target="_blank" href="https://bundlephobia.com/package/axios-cache-interceptor"><img alt="Bundlephobia" src="https://img.shields.io/bundlephobia/minzip/axios-cache-interceptor/latest?style=flat&color=e87430"></a>
<a title="Last Commit" target="_blank" href="https://github.com/arthurfiorette/axios-cache-interceptor/commits/main"><img alt="Last commit" src="https://img.shields.io/github/last-commit/arthurfiorette/axios-cache-interceptor?color=f15633"></a>
<a title="Blazingly fast" target="_blank" href="https://twitter.com/acdlite/status/974390255393505280"><img src="https://img.shields.io/badge/blazingly-fast-fa3737"/></a>
</p>
<br />
<br />
# Axios Cache Interceptor
> Cache interceptor for axios made with developers and performance in mind.
<br />
- ⚡ Faster!
- 📦 Handy builds!
- 🔩 Hassle free!
- 🛠️ Rich Features!
- 🌐 No network waste!
- 🔑 TypeScript!
Axios Cache Interceptor is, as it name says, a interceptor for axios to handle caching. It
was created to help developers call axios multiple times without having to worry about
overloading the network or coding himself a simple and buggy cache system.
<br />
[Read the docs to **Learn More**.](https://axios-cache-interceptor.js.org)
<br />
<br />
```ts

@@ -35,7 +61,7 @@ import Axios from 'axios';

// same object, but with updated typings.
// Same object, new types.
const axios = setupCache(Axios);
const req1 = axios.get('https://api.example.com/');
const req2 = axios.get('https://api.example.com/');
const req1 = axios.get('https://arthur.place/');
const req2 = axios.get('https://arthur.place/');

@@ -50,8 +76,2 @@ const [res1, res2] = await Promise.all([req1, req2]);

<h3 align=center>
<a href="https://axios-cache-interceptor.js.org/" target="_blank">Documentation at <code>axios-cache-interceptor.js.org</code> 🎉🎉</a>
</h3>
<br />
## License

@@ -64,8 +84,1 @@

<br />
## Contact
See my contact information on my [github profile](https://github.com/arthurfiorette) or
open a new issue.
<br />

@@ -14,4 +14,8 @@ /* eslint-disable @typescript-eslint/no-explicit-any */

/**
* A slightly changed than the original axios response. Containing information about the
* cache and other needed properties.
*
* @template R The type returned by this response
* @template D The type that the request body was
* @see https://axios-cache-interceptor.js.org/config/response-object
*/

@@ -21,6 +25,26 @@ export type CacheAxiosResponse<R = any, D = any> = AxiosResponse<R, D> & {

/** The id used for this request. if config specified an id, the id will be returned */
/**
* The [Request ID](https://axios-cache-interceptor.js.org/guide/request-id) used in
* this request.
*
* It may have been generated by the [Key
* Generator](https://axios-cache-interceptor.js.org/guide/request-id#custom-generator)
* or a custom one provided by
* [`config.id`](https://axios-cache-interceptor.js.org/config/request-specifics#id)
*
* @see https://axios-cache-interceptor.js.org/config/response-object#id
*/
id: string;
/** A simple boolean to check whether this request was cached or not */
/**
* A simple boolean indicating if the request returned data from the cache or from the
* network call.
*
* This does not indicated if the request was capable of being cached or not, as options
* like
* [`cache.override`](https://axios-cache-interceptor.js.org/config/request-specifics#cache-override)
* may have been enabled.
*
* @see https://axios-cache-interceptor.js.org/config/response-object#cached
*/
cached: boolean;

@@ -37,6 +61,12 @@ };

/**
* An id for this request, if this request is used in cache, only the last request made
* with this id will be returned.
* The [Request ID](https://axios-cache-interceptor.js.org/guide/request-id) used in
* this request.
*
* @default undefined
* It may have been generated by the [Key
* Generator](https://axios-cache-interceptor.js.org/guide/request-id#custom-generator)
* or a custom one provided by
* [`config.id`](https://axios-cache-interceptor.js.org/config/request-specifics#id)
*
* @default 'auto generated by the current key generator'
* @see https://axios-cache-interceptor.js.org/config/response-object#id
*/

@@ -46,5 +76,11 @@ id?: string;

/**
* All cache options for the request.
* The cache option available through the request config is where all the cache
* customization happens.
*
* False means ignore everything about cache, for this request.
* Setting the `cache` property to `false` will disable the cache for this request.
*
* This does not mean that the current cache will be excluded from the storage.
*
* @default 'inherits from global configuration'
* @see https://axios-cache-interceptor.js.org/config/response-object#cache
*/

@@ -63,5 +99,3 @@ cache?: false | Partial<CacheProperties<R, D>>;

*
* @see AxiosInstance
* @see CacheRequestConfig
* @see CacheInstance
* @see https://axios-cache-interceptor.js.org/guide/getting-started
*/

@@ -68,0 +102,0 @@ export interface AxiosCacheInstance extends CacheInstance, AxiosInstance {

import type { Method } from 'axios';
import type { Deferred } from 'fast-defer';
import type { HeadersInterpreter } from '../header/types';
import type { HeaderInterpreter } from '../header/types';
import type { AxiosInterceptor } from '../interceptors/build';
import type { AxiosStorage, CachedResponse } from '../storage/types';
import type {
AxiosStorage,
CachedResponse,
CachedStorageValue,
LoadingStorageValue,
StaleStorageValue
} from '../storage/types';
import type {
CachePredicate,

@@ -29,2 +35,3 @@ CacheUpdater,

* @default 1000 * 60 * 5 // 5 Minutes
* @see https://axios-cache-interceptor.js.org/config/request-specifics#cache-ttl
*/

@@ -34,6 +41,11 @@ ttl: number | ((response: CacheAxiosResponse<R, D>) => number | Promise<number>);

/**
* If this interceptor should configure the cache from the request cache header When
* used, the ttl property is ignored
* If activated, when the response is received, the `ttl` property will be inferred from
* the requests headers. As described in the MDN docs and HTML specification.
*
* See the actual implementation of the
* [`interpretHeader`](https://github.com/arthurfiorette/axios-cache-interceptor/blob/main/src/header/interpreter.ts)
* method for more information.
*
* @default true
* @see https://axios-cache-interceptor.js.org/config/request-specifics#cache-interpretheader
*/

@@ -43,6 +55,28 @@ interpretHeader: boolean;

/**
* If this interceptor should include some headers in the request to tell any possible
* adapter / client that only we should use cache mechanisms to this request.
* As most of our cache strategies depends on well known defined HTTP headers, most
* browsers also use those headers to define their own cache strategies and storages.
*
* When your requested routes includes `Cache-Control` in their responses, you may end
* up with we and your browser caching the response, resulting in a **double layer of
* cache**.
*
* This option solves this by including some predefined headers in the request, that
* should tell any client / adapter to not cache the response, thus only we will cache
* it.
*
* _These are headers used in our specific request, it won't affect any other request or
* response that the server may handle._*
*
* Headers included:
*
* - `Cache-Control: no-cache`
* - `Pragma: no-cache`
* - `Expires: 0`
*
* Learn more at
* [#437](https://github.com/arthurfiorette/axios-cache-interceptor/issues/437#issuecomment-1361262194)
* and in this [StackOverflow](https://stackoverflow.com/a/62781874/14681561) answer.
*
* @default true
* @see https://axios-cache-interceptor.js.org/config/request-specifics#cache-cachetakeover
*/

@@ -52,5 +86,10 @@ cacheTakeover: boolean;

/**
* All methods that should be cached.
* Specifies which methods we should handle and cache. This is where you can enable
* caching to `POST`, `PUT`, `DELETE` and other methods, as the default is only `GET`.
*
* We use `methods` in a per-request configuration setup because sometimes you have
* exceptions to the method rule.
*
* @default ['get']
* @see https://axios-cache-interceptor.js.org/config/request-specifics#cache-methods
*/

@@ -60,5 +99,7 @@ methods: Lowercase<Method>[];

/**
* The function to check if the response code permit being cached.
* An object or function that will be tested against the response to indicate if it can
* be cached.
*
* @default {statusCheck: (status) => status >= 200 && status < 400}
* @default { statusCheck: (status) => [200, 203, 300, 301, 302, 404, 405, 410, 414, 501].includes(status) }
* @see https://axios-cache-interceptor.js.org/config/request-specifics#cache-cachepredicate
*/

@@ -68,17 +109,14 @@ cachePredicate: CachePredicate<R, D>;

/**
* Once the request is resolved, this specifies what requests should we change the
* cache. Can be used to update the request or delete other caches.
* Once the request is resolved, this specifies what other responses should change their
* cache. Can be used to update the request or delete other caches. It is a simple
* `Record` with the request id.
*
* This is independent if the request made was cached or not.
* Here's an example with some basic login:
*
* If an provided id represents and loading cache, he will be ignored.
*
* The id used is the same as the id on `CacheRequestConfig['id']`, auto-generated or
* not.
*
* **Using a function instead of an object is supported but not recommended, as it's
* Using a function instead of an object is supported but not recommended, as it's
* better to just consume the response normally and write your own code after it. But
* it`s here in case you need it.**
* it`s here in case you need it.
*
* @default {{}}
* @see https://axios-cache-interceptor.js.org/config/request-specifics#cache-update
*/

@@ -88,7 +126,14 @@ update: CacheUpdater<R, D>;

/**
* If the request should handle `ETag` and `If-None-Match` support. Use a string to
* force a custom value or true to use the response ETag
* If the request should handle
* [`ETag`](https://developer.mozilla.org/pt-BR/docs/Web/HTTP/Headers/ETag) and
* [`If-None-Match
* support`](https://developer.mozilla.org/pt-BR/docs/Web/HTTP/Headers/If-None-Match).
* Use a string to force a custom static value or true to use the previous response
* ETag.
*
* To use `true` (automatic ETag handling), `interpretHeader` option must be set to
* `true`.
*
* @default true
* @link https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/ETag
* @see https://axios-cache-interceptor.js.org/config/request-specifics#cache-etag
*/

@@ -98,8 +143,17 @@ etag: string | boolean;

/**
* Use `If-Modified-Since` header in this request. Use a date to force a custom value or
* true to use the last cached timestamp. If never cached before, the header is not
* set.
* Use
* [`If-Modified-Since`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/If-Modified-Since)
* header in this request. Use a date to force a custom static value or true to use the
* last cached timestamp.
*
* If never cached before, the header is not set.
*
* If `interpretHeader` is set and a
* [`Last-Modified`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Last-Modified)
* header is sent to us, then value from that header is used, otherwise cache creation
* timestamp will be sent in
* [`If-Modified-Since`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/If-Modified-Since).
*
* @default false // The opposite of the resulting `etag` option.
* @link https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/If-Modified-Since
* @see https://axios-cache-interceptor.js.org/config/request-specifics#cache-modifiedsince
*/

@@ -113,22 +167,16 @@ modifiedSince: Date | boolean;

*
* **Note**: If the response is treated as error because of invalid status code _(like
* from AxiosRequestConfig#invalidateStatus)_, and this ends up `true`, the cache will
* be preserved over the "invalid" request. So, if you want to preserve the response,
* you can use this predicate:
* **If the response is treated as error because of invalid status code _(like when
* using
* [statusCheck](https://axios-cache-interceptor.js.org/config/request-specifics#cache-cachepredicate))_,
* and this ends up `true`, the cache will be preserved over the "invalid" request.**
*
* ```js
* const customPredicate = (response, cache, error) => {
* // Return false if has a response
* return !response;
* };
* ```
* Types:
*
* Possible types:
*
* - `number` -> the max time (in seconds) that the cache can be reused.
* - `boolean` -> `false` disables and `true` enables with infinite time.
* - `boolean` -> `false` disables and `true` enables with infinite time if no value is
* present on `stale-if-error` in Cache-Control.
* - `function` -> a predicate that can return `number` or `boolean` as described above.
*
* @default true
* @link https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control#stale-if-error
* @see https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control#stale-if-error
*/

@@ -147,11 +195,55 @@ staleIfError: StaleIfErrorPredicate<R, D>;

* @default false
* @see https://axios-cache-interceptor.js.org/config/request-specifics#cache-override
*/
override: boolean;
/**
* Asynchronously called when a network request is needed to resolve the data, but an
* older one **and probably expired** cache exists. Its with the current data **BEFORE**
* the network travel starts, so you can use it to temporarily update your UI with
* expired data before the network returns.
*
* Hydrating your components with old data before the network resolves with the newer
* one is better than _flickering_ your entire UI. This is even better when dealing with
* slower networks and persisted cache, like for mobile apps.
*
* If the request can return cached data, as no extensive network travel is needed, the
* hydrate **IS NOT CALLED**, as the axios promise will be resolved instantly.
*
* @default undefined
* @see https://axios-cache-interceptor.js.org/config/request-specifics#cache-hydrate
*/
hydrate:
| undefined
| ((
cache:
| (LoadingStorageValue & { previous: 'stale' })
| CachedStorageValue
| StaleStorageValue
) => void | Promise<void>);
};
/**
* These are properties that are used and shared by the entire application.
*
* ```ts
* const axios = setupCache(axios, OPTIONS);
* ```
*
* The `setupCache` function receives global options and all [request
* specifics](https://axios-cache-interceptor.js.org/config/request-specifics) ones too.
* This way, you can customize the defaults for all requests.
*
* @see https://axios-cache-interceptor.js.org/config/request-specifics
*/
export interface CacheInstance {
/**
* The storage to save the cache data. Defaults to an in-memory storage.
* A storage interface is the entity responsible for saving, retrieving and serializing
* data received from network and requested when a axios call is made.
*
* See the [Storages](https://axios-cache-interceptor.js.org/guide/storages) page for
* more information.
*
* @default buildMemoryStorage
* @see https://axios-cache-interceptor.js.org/config#storage
*/

@@ -162,4 +254,10 @@ storage: AxiosStorage;

* The function used to create different keys for each request. Defaults to a function
* that priorizes the id, and if not specified, a string is generated using the method,
* baseURL, params, and url
* that priorizes the id, and if not specified, a string is generated using the
* `method`, `baseURL`, `params`, `data` and `url`.
*
* You can learn on how to use them on the [Request
* ID](https://axios-cache-interceptor.js.org/guide/request-id#custom-generator) page.
*
* @default defaultKeyGenerator
* @see https://axios-cache-interceptor.js.org/config#generatekey
*/

@@ -169,5 +267,10 @@ generateKey: KeyGenerator;

/**
* A simple object that holds all deferred objects until it is resolved or rejected.
* A simple object that will hold a promise for each pending request. Used to handle
* concurrent requests.
*
* Can be used to listen when a request is cached or not.
* You'd normally not need to change this, but it is exposed in case you need to use it
* as some sort of listener of know when a request is waiting for other to finish.
*
* @default { }
* @see https://axios-cache-interceptor.js.org/config#waiting
*/

@@ -177,13 +280,38 @@ waiting: Record<string, Deferred<CachedResponse>>;

/**
* The function to parse and interpret response headers. Only used if
* cache.interpretHeader is true.
* The function used to interpret all headers from a request and determine a time to
* live (`ttl`) number.
*
* **Many REST backends returns some variation of `Cache-Control: no-cache` or
* `Cache-Control: no-store` headers, which tell us to ignore caching at all. You shall
* disable `headerInterpreter` for those requests.**
*
* **If the debug mode prints `Cache header interpreted as 'dont cache'` this is
* probably the reason.**
*
* The possible returns are:
*
* - `'dont cache'`: the request will not be cached.
* - `'not enough headers'`: the request will find other ways to determine the TTL value.
* - `number`: used as the TTL value.
*
* @default defaultHeaderInterpreter
* @see https://axios-cache-interceptor.js.org/config#headerinterpreter
*/
headerInterpreter: HeadersInterpreter;
headerInterpreter: HeaderInterpreter;
/**
* The request interceptor that will be used to handle the cache.
* The function that will be used to intercept the request before it is sent to the
* axios adapter.
*
* It is the main function of this library, as it is the bridge between the axios
* request and the cache.
*
* _It wasn't meant to be changed, but if you need to, you can do it by passing a new
* function to this property._*
*
* See its code for more information
* [here](https://github.com/arthurfiorette/axios-cache-interceptor/tree/main/src/interceptors).
*
* @default defaultRequestInterceptor
* @see https://axios-cache-interceptor.js.org/config#requestinterceptor
*/

@@ -193,5 +321,16 @@ requestInterceptor: AxiosInterceptor<CacheRequestConfig<unknown, unknown>>;

/**
* The response interceptor that will be used to handle the cache.
* The function that will be used to intercept the request after it is returned by the
* axios adapter.
*
* It is the second most important function of this library, as it is the bridge between
* the axios response and the cache.
*
* _It wasn't meant to be changed, but if you need to, you can do it by passing a new
* function to this property._*
*
* See its code for more information
* [here](https://github.com/arthurfiorette/axios-cache-interceptor/tree/main/src/interceptors).
*
* @default defaultResponseInterceptor
* @see https://axios-cache-interceptor.js.org/config#responseinterceptor
*/

@@ -201,7 +340,10 @@ responseInterceptor: AxiosInterceptor<CacheAxiosResponse<unknown, unknown>>;

/**
* Logs useful information in the console
* The debug option will print debug information in the console. It is good if you need
* to trace any undesired behavior or issue. You can enable it by setting `debug` to a
* function that receives an string and returns nothing.
*
* **Note**: This is only available with development mode enabled
* Read the [Debugging](https://axios-cache-interceptor.js.org/guide/debugging) page for
* the complete guide.
*
* @default {console.log}
* @default undefined
* @see https://axios-cache-interceptor.js.org/#/pages/development-mode

@@ -214,4 +356,6 @@ */

* An object with any possible type that can be used to log and debug information in
* `development` mode (a.k.a `__ACI_DEV__ === true`)
* `development` mode _(a.k.a `__ACI_DEV__ === true`)_
*
* @see https://axios-cache-interceptor.js.org/#/pages/development-mode
*/
export type DebugObject = Partial<{ id: string; msg: string; data: unknown }>;
export type DebugObject = { id?: string; msg?: string; data?: unknown };

@@ -16,34 +16,14 @@ import type { AxiosInstance } from 'axios';

*
* @example
*
* ```ts
* import Axios from 'axios';
* import { setupCache, AxiosCacheInstance } from 'axios-cache-interceptor';
* const axios = setupCache(axios, OPTIONS);
* ```
*
* // instance will have our custom typings from the return of this function
* const instance = setupCache(
* Axios.create({
* // Axios options
* }),
* {
* // Axios-cache-interceptor options
* }
* );
* The `setupCache` function receives global options and all [request
* specifics](https://axios-cache-interceptor.js.org/config/request-specifics) ones too.
* This way, you can customize the defaults for all requests.
*
* // OR
*
* const instance = axios.create({
* // Axios options
* }) as AxiosCacheInstance;
*
* // As this functions returns the same axios instance but only with
* // different typings, you can ignore the function return.
* setupCache(instance, {
* // Axios-cache-interceptor options
* });
* ```
*
* @param axios The already created axios instance
* @param config The config for the caching interceptors
* @returns The same instance with extended typescript types.
* @see https://axios-cache-interceptor.js.org/config
*/

@@ -86,6 +66,10 @@ export function setupCache(

methods: options.methods || ['get'],
// Although RFC 7231 also marks POST as cacheable, most users don't know that
// and may have problems about why their "create X" route not working.
methods: options.methods || ['get', 'head'],
cachePredicate: options.cachePredicate || {
statusCheck: (status) => status >= 200 && status < 400
// All cacheable status codes defined in RFC 7231
statusCheck: (status) =>
[200, 203, 300, 301, 302, 404, 405, 410, 414, 501].includes(status)
},

@@ -105,3 +89,5 @@

override: false
override: false,
hydrate: undefined
};

@@ -108,0 +94,0 @@

import { parse } from 'cache-parser';
import { Header } from './headers';
import type { HeadersInterpreter } from './types';
import type { HeaderInterpreter } from './types';
export const defaultHeaderInterpreter: HeadersInterpreter = (headers) => {
export const defaultHeaderInterpreter: HeaderInterpreter = (headers) => {
if (!headers) return 'not enough headers';

@@ -11,3 +11,3 @@

if (cacheControl) {
const { noCache, noStore, mustRevalidate, maxAge, immutable } = parse(
const { noCache, noStore, maxAge, immutable, staleWhileRevalidate } = parse(
String(cacheControl)

@@ -24,18 +24,18 @@ );

// It might not be the best way, but a year is better than none.
return 1000 * 60 * 60 * 24 * 365;
return {
cache: 1000 * 60 * 60 * 24 * 365
};
}
// Already out of date, for cache can be saved, but must be requested again
if (mustRevalidate) {
return 0;
}
if (maxAge !== undefined) {
const age: unknown = headers[Header.Age];
if (!age) {
return maxAge * 1000;
}
return (maxAge - Number(age)) * 1000;
return {
cache: age
? // If age is present, we must subtract it from maxAge
(maxAge - Number(age)) * 1000
: maxAge * 1000,
// Already out of date, for cache can be saved, but must be requested again
stale: staleWhileRevalidate !== undefined ? staleWhileRevalidate * 1000 : 0
};
}

@@ -48,3 +48,3 @@ }

const milliseconds = Date.parse(String(expires)) - Date.now();
return milliseconds >= 0 ? milliseconds : 'dont cache';
return milliseconds >= 0 ? { cache: milliseconds } : 'dont cache';
}

@@ -51,0 +51,0 @@

@@ -1,29 +0,38 @@

import type { AxiosRequestHeaders } from 'axios';
import type { CacheAxiosResponse } from '../cache/axios';
export type InterpreterResult = 'dont cache' | 'not enough headers' | number;
/**
* Interpret all http headers to determina a time to live.
*
* @param header The header object to interpret.
* @returns `false` if cache should not be used. `undefined` when provided headers was not
* enough to determine a valid value. Or a `number` containing the number of
* **milliseconds** to cache the response.
* The possible values are:
* - `'dont cache'`: the request will not be cached.
* - `'not enough headers'`: the request will find other ways to determine the TTL value.
* - `number`: used as the TTL value.
* - `{ cache: number, stale: number }: used as the TTL value and stale TTL value`
*/
export type HeadersInterpreter = (
headers?: CacheAxiosResponse['headers']
) => InterpreterResult;
export type InterpreterResult =
| 'dont cache'
| 'not enough headers'
| number
| {
cache: number;
stale?: number;
};
/**
* Interpret a single string header
* - If activated, when the response is received, the `ttl` property will be inferred from
* the requests headers. As described in the MDN docs and HTML specification.
*
* @param header The header string to interpret.
* The possible returns are:
*
* - `'dont cache'`: the request will not be cached.
* - `'not enough headers'`: the request will find other ways to determine the TTL value.
* - `number`: used as the TTL value.
* - `{ cache: number, stale: number }: used as the TTL value and stale TTL value`
*
* @param header The header object to interpret.
* @returns `false` if cache should not be used. `undefined` when provided headers was not
* enough to determine a valid value. Or a `number` containing the number of
* **milliseconds** to cache the response.
* @see https://axios-cache-interceptor.js.org/config#headerinterpreter
*/
export type HeaderInterpreter = (
header: string,
headers: AxiosRequestHeaders
headers?: CacheAxiosResponse['headers']
) => InterpreterResult;

@@ -23,5 +23,6 @@ export * from './cache/axios';

/**
* Global variable defined at compile time. Use to write code that will only be executed
* at development time.
* **This declaration is erased at compile time.**
*
* Use to write code that will only be executed at development time.
*
* @internal

@@ -34,4 +35,4 @@ */

console.error(
'You are using a development build. Make sure to use the correct build in production\nhttps://axios-cache-interceptor.js.org/#/pages/installing\n\n'
'You are using a development build. Make sure to use the correct build in production\nhttps://axios-cache-interceptor.js.org/guide/getting-started\n\n'
);
}

@@ -154,2 +154,7 @@ import { deferred } from 'fast-defer';

// Hydrates any UI temporarily, if cache is available
if (cache.state === 'stale' || cache.data) {
await config.cache.hydrate?.(cache);
}
return config;

@@ -167,2 +172,8 @@ }

await axios.storage.remove(id, config);
// Hydrates any UI temporarily, if cache is available
if (cache.data) {
await config.cache.hydrate?.(cache);
}
return config;

@@ -189,2 +200,7 @@ }

// Hydrates any UI temporarily, if cache is available
if (cache.data) {
await config.cache.hydrate?.(cache);
}
// The deferred is rejected when the request that we are waiting rejected cache.

@@ -191,0 +207,0 @@ return config;

import type { AxiosResponseHeaders } from 'axios';
import { parse } from 'cache-parser';
import type {

@@ -34,2 +35,14 @@ AxiosCacheInstance,

const onFulfilled: ResponseInterceptor['onFulfilled'] = async (response) => {
// When response.config is not present, the response is indeed a error.
if (!response.config) {
if (__ACI_DEV__) {
axios.debug?.({
msg: 'Response interceptor received an unknown response.',
data: response
});
throw response;
}
}
const id = (response.id = response.config.id ??= axios.generateKey(response.config));

@@ -139,2 +152,3 @@ response.cached ??= false;

let ttl = cacheConfig.ttl || -1; // always set from global config
let staleTtl: number | undefined;

@@ -159,3 +173,10 @@ if (cacheConfig.interpretHeader) {

ttl = expirationTime === 'not enough headers' ? ttl : expirationTime;
if (expirationTime !== 'not enough headers') {
if (typeof expirationTime === 'number') {
ttl = expirationTime;
} else {
ttl = expirationTime.cache;
staleTtl = expirationTime.stale;
}
}
}

@@ -184,2 +205,3 @@

ttl,
staleTtl,
createdAt: Date.now(),

@@ -224,2 +246,3 @@ data

const cacheConfig = config.cache as CacheProperties;
const response = error.response as CacheAxiosResponse | undefined;

@@ -263,3 +286,3 @@ // config.cache should always exist, at least from global config merge.

msg: 'Caught an error in the request interceptor',
data: { error, config }
data: { cache, error, config }
});

@@ -272,9 +295,10 @@ }

if (cacheConfig.staleIfError) {
const cacheControl = String(response?.headers[Header.CacheControl]);
const staleHeader = cacheControl && parse(cacheControl).staleIfError;
const staleIfError =
typeof cacheConfig.staleIfError === 'function'
? await cacheConfig.staleIfError(
error.response as CacheAxiosResponse,
cache,
error
)
? await cacheConfig.staleIfError(response, cache, error)
: cacheConfig.staleIfError === true && staleHeader
? staleHeader * 1000 //staleIfError is in seconds
: cacheConfig.staleIfError;

@@ -281,0 +305,0 @@

@@ -15,4 +15,5 @@ import type { CacheRequestConfig } from '../cache/axios';

/** Returns true if this has sufficient properties to stale instead of expire. */
export function canStale(value: CachedStorageValue): boolean {
function hasUniqueIdentifierHeader(
value: CachedStorageValue | StaleStorageValue
): boolean {
const headers = value.data.headers;

@@ -24,3 +25,2 @@

Header.XAxiosCacheEtag in headers ||
Header.XAxiosCacheStaleIfError in headers ||
Header.XAxiosCacheLastModified in headers

@@ -30,2 +30,24 @@ );

/** Returns true if this has sufficient properties to stale instead of expire. */
export function canStale(value: CachedStorageValue): boolean {
// Must revalidate is a special case and should not be staled
if (
String(value.data.headers[Header.CacheControl])
// We could use cache-control's parse function, but this is way faster and simpler
.includes('must-revalidate')
) {
return false;
}
if (hasUniqueIdentifierHeader(value)) {
return true;
}
return (
value.state === 'cached' &&
value.staleTtl !== undefined &&
value.createdAt + value.ttl + value.staleTtl <= Date.now()
);
}
/**

@@ -35,4 +57,4 @@ * Checks if the provided cache is expired. You should also check if the cache

*/
export function isExpired(value: CachedStorageValue): boolean {
return value.createdAt + value.ttl <= Date.now();
export function isExpired(value: CachedStorageValue | StaleStorageValue): boolean {
return value.ttl !== undefined && value.createdAt + value.ttl <= Date.now();
}

@@ -47,2 +69,3 @@

* @param currentRequest The current {@link CacheRequestConfig}, if any
* @see https://axios-cache-interceptor.js.org/guide/storages#buildstorage
*/

@@ -56,4 +79,8 @@ find: (

/**
* Builds a custom storage.
* All integrated storages are wrappers around the `buildStorage` function. External
* libraries use it and if you want to build your own, `buildStorage` is the way to go!
*
* The exported `buildStorage` function abstracts the storage interface and requires a
* super simple object to build the storage.
*
* **Note**: You can only create an custom storage with this function.

@@ -72,6 +99,8 @@ *

* ```
*
* @see https://axios-cache-interceptor.js.org/guide/storages#buildstorage
*/
export function buildStorage({ set, find, remove }: BuildStorage): AxiosStorage {
return {
//@ts-expect-error - we don't want to expose thi
//@ts-expect-error - we don't want to expose this
['is-storage']: 1,

@@ -81,3 +110,3 @@ set,

get: async (key, config) => {
const value = await find(key, config);
let value = await find(key, config);

@@ -88,21 +117,37 @@ if (!value) {

if (
// Not cached or fresh value
value.state !== 'cached' ||
!isExpired(value)
) {
if (value.state === 'empty' || value.state === 'loading') {
return value;
}
if (canStale(value)) {
const stale: StaleStorageValue = {
// Handle cached values
if (value.state === 'cached') {
if (!isExpired(value)) {
return value;
}
// Tries to stale expired value
if (!canStale(value)) {
await remove(key, config);
return { state: 'empty' };
}
value = {
state: 'stale',
createdAt: value.createdAt,
data: value.data
data: value.data,
ttl: value.staleTtl !== undefined ? value.staleTtl + value.ttl : undefined
};
await set(key, stale, config);
return stale;
await set(key, value, config);
}
// A second check in case the new stale value was created already expired.
if (!isExpired(value)) {
return value;
}
if (hasUniqueIdentifierHeader(value)) {
return value;
}
await remove(key, config);

@@ -109,0 +154,0 @@ return { state: 'empty' };

@@ -1,2 +0,2 @@

import { buildStorage } from './build';
import { buildStorage, canStale, isExpired } from './build';
import type { AxiosStorage, StorageValue } from './types';

@@ -35,4 +35,10 @@

* mutating the original data outside the `set()` method.
*
* @param {number | false} cleanupInterval The interval in milliseconds to run a
* setInterval job of cleaning old entries. If false, the job will not be created. Disabled is default
*/
export function buildMemoryStorage(cloneData = false) {
export function buildMemoryStorage(
cloneData = false,
cleanupInterval: number | false = false
) {
const storage = buildStorage({

@@ -50,4 +56,4 @@ set: (key, value) => {

/* istanbul ignore if 'only available on super recent browsers' */
if (cloneData && value !== undefined) {
/* istanbul ignore if 'only available on super recent browsers' */
if (typeof structuredClone === 'function') {

@@ -66,2 +72,36 @@ return structuredClone(value);

// When this program gets running for more than the specified interval, there's a good
// chance of it being a long-running process or at least have a lot of entries. Therefore,
// "faster" loop is more important than code readability.
if (cleanupInterval) {
storage.cleaner = setInterval(() => {
const keys = Object.keys(storage.data);
let i = -1,
value: StorageValue,
key: string;
// Looping forward, as older entries are more likely to be expired
// than newer ones.
while (++i < keys.length) {
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
(key = keys[i]!), (value = storage.data[key]!);
if (value.state === 'empty') {
// this storage returns void.
// eslint-disable-next-line @typescript-eslint/no-floating-promises
storage.remove(key);
continue;
}
// If the value is expired and can't be stale, remove it
if (value.state === 'cached' && isExpired(value) && !canStale(value)) {
// this storage returns void.
// eslint-disable-next-line @typescript-eslint/no-floating-promises
storage.remove(key);
}
}
}, cleanupInterval);
}
return storage;

@@ -72,2 +112,4 @@ }

data: Record<string, StorageValue>;
/** The job responsible to cleaning old entries */
cleaner: ReturnType<typeof setInterval>;
};

@@ -22,3 +22,4 @@ import type { CacheAxiosResponse, CacheRequestConfig } from '../cache/axios';

data: CachedResponse;
ttl?: undefined;
ttl?: number;
staleTtl?: undefined;
createdAt: number;

@@ -35,2 +36,3 @@ state: 'stale';

ttl: number;
staleTtl?: number;
createdAt: number;

@@ -40,21 +42,26 @@ state: 'cached';

export type LoadingStorageValue =
| {
data?: undefined;
ttl?: undefined;
createdAt?: undefined;
state: 'loading';
previous: 'empty';
}
| {
state: 'loading';
data: CachedResponse;
ttl?: undefined;
createdAt: number;
previous: 'stale';
};
export type LoadingStorageValue = LoadingEmptiedStorageValue | LoadingStaledStorageValue;
export type LoadingEmptiedStorageValue = {
data?: undefined;
ttl?: undefined;
staleTtl?: undefined;
createdAt?: undefined;
state: 'loading';
previous: 'empty';
};
export type LoadingStaledStorageValue = {
state: 'loading';
data: CachedResponse;
ttl?: undefined;
staleTtl?: undefined;
createdAt: number;
previous: 'stale';
};
export type EmptyStorageValue = {
data?: undefined;
ttl?: undefined;
staleTtl?: undefined;

@@ -67,17 +74,7 @@ /** Defined when the state is cached */

/**
* A storage implementation that stores data in memory.
* A storage interface is the entity responsible for saving, retrieving and serializing
* data received from network and requested when a axios call is made.
*
* **You can create yours with {@link buildStorage} function**
*
* @example
*
* ```js
* const myStorage = buildStorage({
* find: () => {...},
* set: () => {...},
* remove: () => {...}
* });
*
* const axios = setupCache(axios, { storage: myStorage });
* ```
* @default buildMemoryStorage
* @see https://axios-cache-interceptor.js.org/guide/storages
*/

@@ -93,2 +90,3 @@ export type AxiosStorage = {

* @param currentRequest The current {@link CacheRequestConfig}, if any
* @see https://axios-cache-interceptor.js.org/guide/storages#buildstorage
*/

@@ -106,2 +104,3 @@ set: (

* @param currentRequest The current {@link CacheRequestConfig}, if any
* @see https://axios-cache-interceptor.js.org/guide/storages#buildstorage
*/

@@ -114,3 +113,3 @@ remove: (key: string, currentRequest?: CacheRequestConfig) => MaybePromise<void>;

*
* If the provided `find()` method returned null, this will map it to a `'empty'`
* If the internal `find()` method returned null, this will map it to a `'empty'`
* storage value.

@@ -121,4 +120,5 @@ *

* @returns The saved value for the given key.
* @see https://axios-cache-interceptor.js.org/guide/storages#buildstorage
*/
get: (key: string, currentRequest?: CacheRequestConfig) => MaybePromise<StorageValue>;
};

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc