Coder Social home page Coder Social logo

arthurfiorette / axios-cache-interceptor Goto Github PK

View Code? Open in Web Editor NEW
519.0 5.0 48.0 11.5 MB

๐Ÿ“ฌ Small and efficient cache interceptor for axios. Etag, Cache-Control, TTL, HTTP headers and more!

Home Page: https://axios-cache-interceptor.js.org

License: MIT License

TypeScript 96.81% JavaScript 1.74% Shell 1.45%
axios cache adapter http request web axios-cache axios-cache-interceptor nodejs cachecontrol

axios-cache-interceptor's Introduction

Using this package? Please consider donating to support my open source work โค๏ธ
Help axios-cache-interceptor grow! Star and share this amazing repository with your friends and co-workers!


Axios Cache Interceptor logo


License Codecov Downloads Bundlephobia Last commit



Axios Cache Interceptor

Cache interceptor for axios made with developers and performance in mind.


  • โšก 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.


Read the docs to Learn More.



import Axios from 'axios';
import { setupCache } from 'axios-cache-interceptor';

const instance = Axios.create();
const axios = setupCache(instance);

const req1 = axios.get('https://arthur.place/');
const req2 = axios.get('https://arthur.place/');

const [res1, res2] = await Promise.all([req1, req2]);

res1.cached; // false
res2.cached; // true

License

Licensed under the MIT. See LICENSE for more informations.

FOSSA Status


axios-cache-interceptor's People

Contributors

adamdehaven avatar afurculita avatar amrendr-cb avatar arthurfiorette avatar bhallionohbibi avatar brianreidy avatar catchabus avatar ckopanos avatar denis-rossati avatar dependabot[bot] avatar edwinveldhuizen avatar fjeldstad avatar fossabot avatar gmazoni avatar heiko-r avatar jordan-schnur avatar joseiedo avatar kcsujeet avatar marcellofabrizio avatar mayureshd-18 avatar pvinis avatar richardgarnier avatar rototu avatar sarahsporck avatar spiderpig86 avatar stoyz avatar subhradeepnag avatar super-ppx avatar tupe12334 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

axios-cache-interceptor's Issues

POST method support

Hi,
I looked at this library and really superb for caching. But if this library had post method support it would have been better. Because the post method can also be cached in the axios-cache-adapter library.

Can't make it work with custom storage

Describe the bug

I read all the docs, all examples, all Google and most of the issues ;) And I still can't make custom storage work.

To Reproduce

For example (I took the code from an other issue yet it works the same as my original code that used file system):

my-cache.js:

const CACHE = new Map();
const STORAGE = buildStorage({
  find: (key) => {
    const found = CACHE.get(key);
    if (found?.data) {
      return { ...found, data: JSON.parse(JSON.stringify(found.data)) };
    }
    return found;
  },
  set: (key, value) => {
    console.log(value); // HERE
    if (value?.data) {
      CACHE.set(key, {
        ...value,
        data: JSON.parse(JSON.stringify(value.data)),
      });
    } else {
      CACHE.set(key, value);
    }
  },
  remove: (key) => {
    CACHE.delete(key);
  },
});

const INSTANCE = setupCache(axios.create(), {
  ttl: 2000,
  storage: STORAGE,
});

function getAxiosWithCache() {
  return INSTANCE;
}
module.exports = { getAxiosWithCache };

Usage:

const { getAxiosWithCache } = require('./my-cache');
const axios = getAxiosWithCache();

async function parseSearchPage(url) {
  const res = await axios.get(url);
  const html = res.data;
  console.log(html); // HERE 2
}

Actual behavior

HERE 2 reports the downloaded URL's content.

HERE reports only:

{
  state: 'loading',
  previous: 'empty',
  data: undefined,
  createdAt: undefined
}

Expected behavior

HERE reports the downloaded URL's content, just as HERE 2 does

Additional context

  • Axios: v0.27.2
  • Axios Cache Interceptor: v0.10.7
  • What storage is being used: custom
  • Node Version: v16.16.0

[Bug] Cache is not deleted on memoryStorage

Describe the bug

I am caching a get request with an id of blog-posts on a vue 2 app. Then I am trying to delete blog-posts entry on memoryStorage by adding cache.update to my post request whenever create, update or delete requests are called to blog API.

cache: {
    interpretHeader: false,
    override: true,
    // Allows the update key to be executed
    methods: [...axios.defaults.cache.methods, 'post'],
    update: {
        'blog-posts': 'delete'
    }
},

Logging axios.storage after each request (create, update or delete) shows that blog-posts no longer exists. But when I navigate on the blog index page, request to blog-posts returns old data, weird thing is that response.cache shows false. On the chrome devtools Network tab, I see that the request is loaded from disk cache. Can confirm that axios.storage has the old data, does this mean that the blog-posts key was never deleted from memoryStorage?

I even tried doing delete window.memoryStorage.data[response.id] but to no avail.

Also nginx is returning cache-control: max-age=172800 header on the response, don't know if that's related. But I have window.axios.defaults.cache.interpretHeader = false so it should not be the case right?

To Reproduce

// initialize axios and setupCache
window.axios = require('axios');
window.axiosCacheInterceptor = require('axios-cache-interceptor/dev')
const { setupCache, buildMemoryStorage } = window.axiosCacheInterceptor
window.memoryStorage = buildMemoryStorage(true)
window.axios = setupCache(window.axios, {
    storage: window.memoryStorage,
    debug: console.log,
})
window.axios.defaults.baseURL = process.env.MIX_API_BASE_URL;
window.axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';
window.axios.defaults.cache.interpretHeader = false
// GET request to blog posts
axios.get(`${window.location.origin}/api/blog/posts`, {
      id: 'blog-posts',
  })
  .then((response) => {
      const posts = response.data
      console.log('id: ', response.id)
      console.log('cached: ', response.cached)
      console.log('storage: ', axios.storage)
      console.log('posts: ', posts)
  })
  .catch((error) => {
      console.warn(error)
  });
// this request should delete `blog-posts` in memoryStorage
// which it does but when GET request to blog posts is called again, old data appears
axios.post(`${window.location.origin}/api/blog/post/create`, {
      data,
  }, {
      id: 'editor-create',
      cache: {
          interpretHeader: false,
          override: true,
          // Allows the update key to be executed
          methods: [...axios.defaults.cache.methods, 'post'],
          update: {
              'blog-posts': 'delete'
          }
      },
      headers: { 'Cache-Control': 'no-cache' },
  })
  .then((response) => {
      console.log('create-post: ', response.data)
      console.log('storage: ', axios.storage)
      delete window.memoryStorage.data[response.id]
  })
  .catch((error) => {console.warn(error)});

Expected behavior

blog-posts entry in memoryStorage should have been deleted and request should not use response from disk cache

Additional context

  • Vue: v2.7.8
  • Axios: v1.2.1
  • Axios Cache Interceptor: v0.10.7
  • What storage is being used: Memory Storage
  • Node Version: v14.0.0
  • Browser (if applicable): Version 107.0.5304.110 (Official Build) (x86_64)

bug: unexpected behavior when ttl set to 0

Describe the bug

  • defalt cache option ttl set 0
setupCache(axioInstance, {
  ttl: 0
});
  • but responses are cached

To Reproduce

  • If ttl is 0, in create.ts ?? check, but in response.ts || check
    This seems to be the cause.

image

image

Expected behavior

Additional context

  • Axios: v0.27.2
  • Axios Cache Interceptor: v0.10.7
  • What storage is being used: MemoryStorage
  • Node Version: v16.14.0
  • Browser (if applicable): Chrome 104.0.5112.81

[localStorage] SyntaxError: JSON.parse: unexpected character at line 1 column 1 of the JSON data

Describe the bug

In firefox, there are times when my local storage hits the limit.
This results in DOMException: The quota has been exceeded. error which is caught by cache-interceptor plugin.

When it's caught, plugin tries to free some space:

.map((item) => [item[0], JSON.parse(item[1]) as StorageValue]);

The issue here is I might have other values stored in localStorage and cache-interceptor will attempt to meddle with them at the location I mentioned above.
If I store a value like localStorage.set("mytheme", "dark");, plugin will attempt to call JSON.parse with "dark" as an argument.
This results in SyntaxError: JSON.parse: unexpected character at line 1 column 1 of the JSON data.

This may not occur if I set a prefix for my storage.
My suggestion to avoiding this is to perhaps add a default prefix value to plugin.

- export function buildWebStorage(storage: Storage, prefix = '')
+ export function buildWebStorage(storage: Storage, prefix = 'axios-cache')

To Reproduce

Make sure localStorage gets full.

Expected behavior

Should not throw errors.

Type error: Cannot find name 'Storage'

Describe the bug

A type error emitted from tsc when building

node_modules/axios-cache-interceptor/dist/storage/web-api.d.ts:21:50 - error TS2304: Cannot find name 'Storage'.

21 export declare function buildWebStorage(storage: Storage, prefix?: string): import("./types").AxiosStorage;        
                                                    ~~~~~~~


Found 1 error in node_modules/axios-cache-interceptor/dist/storage/web-api.d.ts:21

it seems that the type Storage is not defined on the line below

export function buildWebStorage(storage: Storage, prefix = '') {

To Reproduce

build a package with it as a dep

Expected behavior

Builds with no type errors

Additional context

  • Axios: v0.27.2
  • Axios Cache Interceptor: v0.10.7
  • Node Version: v16.16.0

Is it possible to use cache with post method?

I'm looking for a cache mechanism for http request in my frontend project these days and I found Axios Cache Interceptor fit my project, but the problem I have now is that most of the APIs in my project is using post method to fetch data instead of get.

so, when I use axios.post, the cache doesn't work:

const req1 = await axios.post('/api-1', body);
const req2 = await axios.post('/api-2', body);
console.log(req1.cached) // false
console.log(req2.cached) // false

how can I make cache work using axios.post? please help!

bug: typescript tsc build throwing complier error

Describe the bug

tsc (typescript compiler) is throwing below error
#16 5.784 node_modules/axios-cache-interceptor/dist/storage/web-api.d.ts(21,50): error TS2304: Cannot find name 'Storage'.

To Reproduce

Additional context

  • Axios: ^0.26.0
  • Axios Cache Interceptor: ^0.10.6
  • What storage is being used: Redis
  • Node Version: v14.8.1
  • typescript : v4.7.4

`canStale` should return false if `Cache-Control: must-revalidate` is present

Describe the bug

The canStale function is used by the buildStorage function to determine when the cache can become state: 'stale' or not, but must-revalidate is not being respected.

Currently, mustRevalidate disables the cache, which is a bug

To Reproduce

import { canStale } from 'axios-cache-interceptor';

const { id } = await axios.get('url to a server that returns must-revalidate and etag');
const storage = await axios.storage.get(id);

canStale(storage) === true;

Expected behavior

canStale() should return false when must-revalidate is present in Cache-Control

Additional context

  • Axios: v1.3.1
  • Axios Cache Interceptor: v1.0.1

Working with Vue 3 Suspense

Is there a specific way of making this play nice with Suspense?

I'm using LocalStorage as my cache, and the data gets cached from my API, but using a to the page doesn't seem to display my template #fallback after the data has been cached.

I assume that this is because the data is already cached, and it's not making another request.

Is there a way to display something while the template gets populated from the cache?

My Index.vue:

<script setup lang="ts">
const Preloader = defineAsyncComponent(() =>
  import('~/components/preloader.vue'),
)
const Packages = defineAsyncComponent(() =>
  import('~/components/api/getPackages.vue'),
)
</script>

<template>
  <Suspense>
    <template #default>
      <Packages />
    </template>
    <template #fallback>
      <Preloader />
    </template>
  </Suspense>
</template>

The component making the API call:

<script setup lang="ts">
import axios from 'axios'
import { buildWebStorage, defaultHeaderInterpreter, defaultKeyGenerator, setupCache } from 'axios-cache-interceptor/dev'

const url = 'REDACTED'

const localStore = buildWebStorage(localStorage, 'packagesCache: ')

const axiosCache = setupCache(axios.create(), {
  storage: localStore,
  generateKey: defaultKeyGenerator,
  headerInterpreter: defaultHeaderInterpreter,
  debug: console.log,
})

const { data } = await axiosCache.get(url, {
  id: 'getAllPackages',
  cache: {
    ttl: 1000 * 60 * 5,
    interpretHeader: false,
    methods: ['get'],
    cachePredicate: {
      statusCheck: status => status >= 200 && status < 400,
    },
    etag: false,
    modifiedSince: false,
    staleIfError: false,
  },
})

const { cached } = await axiosCache.get(url, { id: 'getAllPackages' })
</script>

<template>
<div id="main-content" class="container mx-auto grid md:grid-cols-3 gap-3">
    <div v-for="entry in data.packages" id="list-wrapper" :key="entry.id">
        <ul class="list-none">
            <li class="rounded-xl">
                <div class="alert shadow-2xl border-x-4 border-info">
                    <div class="avatar">
                        <div class="w-20 rounded-full ring ring-info ring-offset-base-100 ring-offset-4 ">
                            <img :src="entry.icon_path">
                        </div>
                    </div>
                    <div>
                        <h3 class="font-bold">
                            <p>{{ entry.name }}</p>
                        </h3>
                        <div class="text-xs">
                            <p>Author: {{ entry.author }}</p>
                            <p>Section: {{ entry.section }}</p>
                        </div>
                    </div>
                    <div class="flex-none">
                        <button class="btn btn-md btn-circle btn-ghost hover:bg-primary">
                            <i-material-symbols:arrow-circle-right-outline style="font-size: xx-large;" />
                        </button>
                    </div>
                </div>
            </li>
        </ul>
    </div>
</div>
</template>

Axios default interceptors are not working

Describe the bug

I have a react app using axios package which has two interceptors (one response, one request) like in the snippet below.
After I wrap it around the setupCache wrapper, the access tokens are not added. Can someone help me with what's going wrong?

To Reproduce

const instance = Axios.create({
    baseURL,
});

// Add a request interceptor
instance.interceptors.request.use(async (config: AxiosRequestConfig) => {
    config.headers.Authorization = await getIdToken();
    return config;
});

instance.interceptors.response.use(
    (response) => {
        if (response.headers['x-backend-version']) {
            handleVersion(response.headers['x-backend-version']);
        }
    },
    (error) =>
        Promise.reject(
            (error && error.response && error.response.data) || error
        )
);

const axios = setupCache(instance);

Expected behavior

Have headers being intercepted properly

Additional context

  • Axios: v0.26.1
  • Axios Cache Interceptor: v1.0.0
  • What storage is being used: Default
  • Browser (if applicable): Chrome 108

Debug log

{
    "id": "2124243715",
    "msg": "Sending request, waiting for response",
    "data": {
        "overrideCache": false,
        "state": "empty"
    }
}

Can't import the named export 'deferred' from non EcmaScript module (only default export is available)

Describe the bug

I am trying to use it in AWS Lambda. The tool chain I am using is serverless and serverless-webpack plugin.
Webpack complains about "Can't import ... from non EcmaScript module" in Node 14 environment:

[2022-05-18T10:10:53.414Z] ERROR in ./node_modules/axios-cache-interceptor/dist/index.mjs 1:1278-1288

[2022-05-18T10:10:53.414Z] Can't import the named export 'deferred' from non EcmaScript module (only default export is available)

[2022-05-18T10:10:53.414Z]  @ ./api.ts

[2022-05-18T10:10:53.414Z]  @ ./handler.ts

[2022-05-18T10:10:53.414Z] 

[2022-05-18T10:10:53.414Z] ERROR in ./node_modules/axios-cache-interceptor/dist/index.mjs 1:6483-6489

[2022-05-18T10:10:53.414Z] Can't import the named export 'hash' from non EcmaScript module (only default export is available)

[2022-05-18T10:10:53.414Z]  @ ./api.ts

[2022-05-18T10:10:53.414Z]  @ ./handler.ts

[2022-05-18T10:10:53.414Z] 

[2022-05-18T10:10:53.414Z] ERROR in ./node_modules/axios-cache-interceptor/dist/index.mjs 1:485-492

[2022-05-18T10:10:53.414Z] Can't import the named export 'parse' from non EcmaScript module (only default export is available)

[2022-05-18T10:10:53.414Z]  @ ./api.ts

[2022-05-18T10:10:53.414Z]  @ ./handler.ts

[2022-05-18T10:10:53.414Z]  

[2022-05-18T10:10:53.414Z]  Error ---------------------------------------------------

[2022-05-18T10:10:53.414Z]  

[2022-05-18T10:10:53.414Z]   Error: Webpack compilation error, see stats above

[2022-05-18T10:10:53.414Z]       at /home/ec2-user/workspace/services_feature_cache-term-info/statement/stmt-results/node_modules/serverless-webpack/lib/compile.js:37:15

[2022-05-18T10:10:53.414Z]       at arrayEach (/home/ec2-user/workspace/services_feature_cache-term-info/statement/stmt-results/node_modules/serverless-webpack/node_modules/lodash/lodash.js:530:11)

[2022-05-18T10:10:53.414Z]       at Function.forEach (/home/ec2-user/workspace/services_feature_cache-term-info/statement/stmt-results/node_modules/serverless-webpack/node_modules/lodash/lodash.js:9410:14)

[2022-05-18T10:10:53.414Z]       at /home/ec2-user/workspace/services_feature_cache-term-info/statement/stmt-results/node_modules/serverless-webpack/lib/compile.js:34:7

[2022-05-18T10:10:53.414Z]       at tryCatcher (/home/ec2-user/workspace/services_feature_cache-term-info/statement/stmt-results/node_modules/bluebird/js/release/util.js:16:23)

BTW, in tsconfig.json, "target" and "module" decide the compatibility level of your npm package. If you specify ESNext, that means your package can only be guaranteed to work in the environment that supports all features of ESNext. I usually set that to ES2017 so that my package can work in Node 10+.

Custom BuildStorage example is wrongly typed

Hello !

Thanks for this lib, I wanted to use it with redis to store the cache, and followed that example : https://axios-cache-interceptor.js.org/#/pages/storages?id=creating-your-own-storage

But when I implemented it, I got an error from typescript :
Capture dโ€™eฬcran 2022-03-11 aฬ€ 11 38 06

I think I figured out what's wrong :

  • Redis expects a string to save, so in the set function we Stringify the value.
  • When we get the value from redis in the get function and give it to the buildStorage, we do not parse it. Either the parse is done by the buildStorage and the get function is wrongly typed, or we have to manually parse the value returned by Redis before returning it :

Capture dโ€™eฬcran 2022-03-11 aฬ€ 11 40 49

If I'm correct, maybe adjust the documentation for futur users ;) If I'm wrong, what am I missing ?

Can't import the named export

./node_modules/axios-cache-interceptor/dist/index.mjs
Can't import the named export 'deferred' from non EcmaScript module (only default export is available)

I don't have access to webpack's config file and ejecting it is not ideal. I think this is better solved in axios-cache-interceptor export file.

Unusable in scenarios where no axios reference is available

I would like to try this package, but as implemented, using setupCache necessitates a reference to the axios instance. Unfortunately, in some use cases no such reference exists. For example, some packages wrap axios and pass through configuration to the axios instance, but do not expose the instance itself (e.g. https://www.npmjs.com/package/contentful).

I would suggest making these use cases possible by allowing the cache to passed into the adapter option of axios.

Incorrect URL is being built when using relative paths.

Hi,
In my application I have the backend serve a static page at a specific path /clients/index.html and client api root is /clients/api
Once the /clients/index.html is loaded, I need to get client information using the end point /clients/api/info.

I am using express for the backend and react for the frontend leveraging axios along with the axios-cache-interceptor.

However when using the axios instance (decorated by setupCache) with the baseURL set to : '/clients/api' and the reqeust url set to /info, I am noticing a 404 error in the console.

Page URL: http://localhost:3010/clients/index.html
Clients Information Endpoint: http://localhost:3010/clients/api/info

Working code:

var clientsApi = axios.create({
    baseURL: '/clients/api'
  });

  clientsApi.get('/info').then(a => {
    console.log('Received response: ', a.data);
  }).catch(err => {
    console.log('Error using vanialla axios');
    console.error(err);
  });

**Failing code: **

var clientsApiWithCache = AxiosCacheInterceptor.setupCache(axios.create({
    baseURL: '/clients/api'
  }));

  
  clientsApiWithCache.get('/info').then(a => {
    console.log('Received response using setupCache: ', a.data);
  }).catch(err => {
    console.log('Error using setupCache:');
    console.error(err);
  });

I have debugged the code and see that the issue occurs because of this line:

request.baseURL && (request.baseURL = request.baseURL.replace(SLASHES_REGEX, ''));

Any specific reason for trimming the slashes from the baseURL and url?

The repo @ https://github.com/Chandu/axios-cache-interceptor-relative-base-path-issue can be used to reproduce the issue (I haven't used react in this repo for simpler setup, but the error can be reproduced ).

Screenshot showing the code/error

image

[feature] Status check for cache.update

I noticed cache.update rules will only apply if request resolves but it would also be helpful if rules applied during a bad status.

async function createItem(type, data) {
  var response = await axios.post("/items", data, {
    cache: {
      update: {
        [`item-list-${type}`]: "delete"
      }
    }
  });
  return response.data.id;
}

In the case described above, I'm trying to delete cache for GET request with id item-list-x but there are cases like a status 409 conflict that I would rather it was deleted too.

Something like statusCheck would help perhaps.

bug: Unable to compile on iOS with version 0.10.1 (its working with 0.9.3)

Describe the bug

By running axios and axios-cache-interceptor on iOS device using expo project, the compilation failed with the following error:

iOS Bundling failed 5590ms
While trying to resolve module `axios-cache-interceptor` from file `[...]/Api.tsx`, the package `[...]/node_modules/axios-cache-interceptor/package.json` was successfully found. However, this package itself specifies a `main` module field that could not be resolved (`[...]/node_modules/axios-cache-interceptor/dist/index.cjs`. Indeed, none of these files exist:

  * [...]/node_modules/axios-cache-interceptor/dist/index.cjs(.native|.ios.ts|.native.ts|.ts|.ios.tsx|.native.tsx|.tsx|.ios.js|.native.js|.js|.ios.jsx|.native.jsx|.jsx|.ios.json|.native.json|.json)
  * [...]/node_modules/axios-cache-interceptor/dist/index.cjs/index(.native|.ios.ts|.native.ts|.ts|.ios.tsx|.native.tsx|.tsx|.ios.js|.native.js|.js|.ios.jsx|.native.jsx|.jsx|.ios.json|.native.json|.json)

If I rollback to an older version of the axios-cache-intereceptor (like 0.9.3), the compilation is working as expected.

To Reproduce

  1. Create new expo project (dont know if the issue is present on bare projects)

  2. Install mandatory dependencies

yarn add axios axios-cache-interceptor

{
    "axios": "^0.26.1",
    "axios-cache-interceptor": "^0.10.1",
}
  1. expo start or yarn start
  2. Launch the packager on a real iOS device (probably the issue is present on emulator too)

Expected behavior

The build should succeed

Additional context

  • Axios: 0.26.1
  • Axios Cache Interceptor: 0.10.1
  • Environment : expo app

axios 0.26.0 warning

getting a โžค YN0060: โ”‚ package provides axios (p027d5) with version 0.26.0, which doesn't satisfy what axios-cache-interceptor requests

peer deps of axios-cache-interceptor require ^0.25.0, so not sure why this warning is arising?

the cache not working when use it with axios.create()

Describe the bug

I need to use Axios with rate limit option, the module that I currently using is axios-rate-limit, it require us to use axios.create() when initiating the Axios module

To Reproduce

  1. open https://axios.requestcatcher.com in browser to view the requests
  2. run the code below
const axios = setupCache(Axios);
const axiosRL = axios.create()

// still call 10 times
for (let i = 0; i < 10; i++) {
  axiosRL.get("https://axios.requestcatcher.com/", {});
}

// works fine
for (let i = 0; i < 10; i++) {
  axios.get("https://axios.requestcatcher.com/", {});
}

Expected behavior

only call 1 time when we use the axios.create()

Additional context

  • Axios: E.g: v1.2.2
  • Axios Cache Interceptor: E.g: v1.0.0
  • What storage is being used: Default
  • Node Version: E.g: v16.17.0
  • Browser (if applicable): none

bug: memory storage uses the same instances across requests

Describe the bug

In-memory cache seems to cache objects and arrays as instances.
This may result into issues as one may assign stuff to instances returned by response.data.

To Reproduce

One possible way to see how this could go wrong would be to define properties to response.data instance using Object.defineProperty.
Next time request is performed, Object.defineProperty will be called anew resulting in error as property will already be defined.

Expected behavior

I would expect in-memory cache to store JSON strings instead. Then, when request is performed anew, a JSON.parse will decode string and populate response.data.

Additional context

  • Axios: v0.27.2
  • Axios Cache Interceptor: latest
  • What storage is being used: In-memory Storage
  • Node Version: v18.0.1

CRACO 7 / CRA 5 / Types can't be found

Describe the bug

TS7016: Could not find a declaration file for module 'axios-cache-interceptor'. 'C:/.../packages/app/node_modules/axios-cache-interceptor/dist/index.cjs' implicitly has an 'any' type.
Try npm i --save-dev @types/axios-cache-interceptor if it exists or add a new declaration (.d.ts) file containing declare module 'axios-cache-interceptor';

To Reproduce

CRACO 7 / CRA 5 / React 18

CRACO config:

module.exports = {
  webpack: {
    configure: (webpackConfig) => {
      // Allow importing from external workspaces.
      monorepoWebpackTools.enableWorkspacesResolution(webpackConfig);
      // Ensure nohoisted libraries are resolved from this workspace.
      monorepoWebpackTools.addNohoistAliases(webpackConfig);

      webpackConfig.devtool = 'source-map';

      webpackConfig.module.rules.push({
        test: /\.mjs$/,
        include: /node_modules/,
        type: "javascript/auto"
      });

      webpackConfig.resolve.plugins.find((plugin) => plugin.constructor.name == "ModuleScopePlugin").appSrcs = workspaces;

      webpackConfig.resolve.mainFields = ['browser', 'module', 'main'];

      return webpackConfig;
    },

    plugins: [
      // Inject the "__DEV__" global variable.
      new webpack.DefinePlugin({
        __DEV__: process.env.NODE_ENV !== "production",
      })
    ],
  },
};

Expected behavior

Types would be found

Additional context

  • Axios Cache Interceptor:latest
  • Node Version: 19.2.0

Do you have an idea why craco can't find your types?

RedisStore - TypeError: Cannot read property 'data' of undefined

Using Redis store to get, set,remove. And i see below exception

err: TypeError: Cannot read property 'data' of undefined at t.adapter (/node_modules/axios-cache-interceptor/cjs/index.js:1:3074)

I do not see cjs/index.js in [axios-cache-interceptor](https://github.com/arthurfiorette/axios-cache-interceptor) repo

Etag handling

I've stumbled on this lib from Any plans on ETag support?
but I can't find any reference to If-None-Match in the source.

Is there any plans for this ? (I'll try to provide a PR if I can make it work quickly :) )

bug: axios V1.0.0 support

Describe the bug

A few types are broken when using with axios v1.0.0 due to the being no overlap between axios and axios cache instance.

To Reproduce

Bump axios to v1.0.0 and use a axios instance as a cache interceptor type.

Expected behavior

Be able to compile the ts without any error.

Additional context

  • Axios: 1.0.0
  • Axios Cache Interceptor: latest
  • Error thrown:

Error: src/functions/NitrApi.ts(25,21): error TS2352: Conversion of type 'AxiosInstance' to type 'AxiosCacheInstance' may be a mistake because neither type sufficiently overlaps with the other. If this was intentional, convert the expression to 'unknown' first.
123
  Type 'AxiosInstance' is missing the following properties from type 'AxiosCacheInstance': storage, generateKey, waiting, headerInterpreter, and 3 more.
124
Error: src/functions/NitrApi.ts(35,33): error TS2345: Argument of type 'AxiosCacheInstance' is not assignable to parameter of type 'AxiosInstance'.
125
  Types of property 'defaults' are incompatible.
126
    Type 'AxiosDefaults<any> & { cache: CacheProperties<unknown, unknown>; }' is not assignable to type 'Omit<AxiosDefaults<any>, "headers"> & { headers: HeadersDefaults & { [key: string]: AxiosHeaderValue; }; }'.
127
      Type 'AxiosDefaults<any> & { cache: CacheProperties<unknown, unknown>; }' is not assignable to type '{ headers: HeadersDefaults & { [key: string]: AxiosHeaderValue; }; }'.
128
        Types of property 'headers' are incompatible.
129
          Type 'HeadersDefaults' is not assignable to type 'HeadersDefaults & { [key: string]: AxiosHeaderValue; }'.
130
            Type 'HeadersDefaults' is not assignable to type '{ [key: string]: AxiosHeaderValue; }'.
131
              Index signature for type 'string' is missing in type 'HeadersDefaults'.

[Feature Request] Invalidation callback

Similar to axios-cache-adapter callback called invalidate.

With this callback, we could easily fine-tune the interceptor's behaviour, by inspecting the current request id, method and what not.

As an example, this is what I have right now, along with axios-cache-adapter:

async function invalidate (config, req) {
  if (req.forceRefresh) {
    await invalidateByForcedRefresh(config, req)
  } else if (req.method.toLowerCase() !== 'get') {
    await invalidateByMethod(config, req)
  }
}

It allows me to pass in extra arguments (like forceRefresh in this case) straight from each request, allows me to test for id patterns for clearing cache, etc.

The reason is that the current update[id] method can be a little too simplistic. I may have an user requesting GET /things?filter=alpha and GET /things?filter=beta, and I want both cached. When the user does POST /thing, I want to invalidate both entries with different filters. Currently, I would have to implement that into each request point, making sure I generate suitable IDs and clearing all caches after a success.

The callback would allow me to better defined default invalidation behaviour into a centralised place.

Edit:

Another common case is multiple page loading. GET /things and GET /things?nextPageToken=ABCDE are both parts of the same query, and both need to be invalidated if a new item is added.

Post requests cache is not busted when data values change (swap data for params in defaultKeyGenerator)

In defaultKeyGenerator, the params value is used to generate the key. The problem is that params is undefined on all requests that I've seen, so post requests end up getting cached, even when their bodies have different data. I recommend instead pulling in the data value and including that as part of the key. This guarantees that the cache will be broken if the post request's body changes. The post request body will come in as the data value.
Screen Shot 2022-01-13 at 4 09 33 PM

Update GET cache after POST request.

Originally posted by @diegonogaretti in #304 (comment)

I just started using axios-cache-interceptor today and so far so good!
Unfortunately I have the same problem as @nolde, I'm caching all the GET requests but some have parameters and need to get invalidated/updated after a POST to the same endpoint, here an example:

Request ID generation (url parameters included)

generateKey: buildKeyGenerator(({url, method}) => `${method?.toUpperCase()}/${url}`)

My axios' request's interceptor (I have a global axios instance using react's context api)

client.interceptors.request.use(
        (config) => {
            setBackdrop({...backdrop, open: true, type: config.method === "get" ? loading" : "saving"});
            return config;
        },
        (error) => {
            setBackdrop({...backdrop, open: false});
            return Promise.reject(error);
        }
);

How can I invalidate/update cached GET requests in the interceptor? IDs are generated and not fixed like "list-posts" from your example.
Thanks in advance!

Q: How to cache both failed and successful responses

Odd question as it may be, but I need to cache both failed and successful responses.

My situation is as follows:
I have to check if an email exists, our API returns 200 for positive response and 404 for negative response. Both need to be cached since I don't want to spam the API with the same values over and over again. Regardless of the outcome.

I have been fiddling with the settings but I can't seem to get it to work. Request level cachePredicate on statusCheck doens't seem to get triggered, staleIfError is kinda confusing on how it's used. A global cachePredicate isn't really what I wan't in this situation.

My Axios instance does have validateStatus: status => status >= 200 && status < 400. No idea if that is blocking something, It would be kinde of odd.

Versions used:

Thanks in advance

Data value vanish after first cached value read access

Setup:

const instance = setupCache(axios.create(), { ttl: 2000 });

so using the internal memory storage. didnt test any other storages.
so first excution of the request is fine.
2nd is also good, after this the data value vanishes somehow out of the storage without trigger any function call on the storage itself (did console logs on find, set, remove => not getting called)

So this may be project specific, casue we are working alot with references in our system. Since references are totaly fine, there should be an mechanism to store and get an shallow copy of the data value.

So for now my current workaround for this is make an own memory storage:

const CACHE = new Map();
const STORAGE = buildStorage({
  find: (key) => {
    const found = CACHE.get(key);
    if (found?.data) {
      return { ...found, data: JSON.parse(JSON.stringify(found.data)) };
    }
    return found;
  },
  set: (key, value) => {    
    if (value?.data) {
      CACHE.set(key, {
        ...value,
        data: JSON.parse(JSON.stringify(value.data)),
      });
    } else {
      CACHE.set(key, value);
    }
  },
  remove: (key) => {
    CACHE.delete(key);
  },
});

const INSTANCE = setupCache(axios.create(), {
  ttl: 2000,
  storage: STORAGE,
});

bug: Property cacheTakeover results into CORS policy errors

Describe the bug

It seems that leaving property cacheTakeover to default value (true) results in CORS policy errors due to no-cache headers being set. This block seems to be the culprit: https://github.com/arthurfiorette/axios-cache-interceptor/blob/main/src/interceptors/request.ts#L39

Preflight requests end up with the following:

Request header field expires is not allowed by Access-Control-Allow-Headers in preflight response.
Request header field pragma is not allowed by Access-Control-Allow-Headers in preflight response.

To Reproduce

I'm doing request to a REST API which browser performs cors preflight requests for.

Expected behavior

Should not throw CORS policy errors.

Additional context

  • Axios: 1.2.3
  • Axios Cache Interceptor: 1.0.0

I wonder if this property should be false by default.

bug: don't working vuejs 3

Describe the bug

Does not working vuejs 3 and axios.
Please help me!

Additional context

  • Axios: v1.2.2
  • Axios Cache Interceptor: v1.0.0
  • What storage is being used: Web Storage
  • Node Version: v14.21.1

const axiosClient = setupCache(axios.create({ baseURL: import.meta.env.VITE_API_URL, }));

Run 2x:
apiCall({method: 'get', url: '/example'});

axiosClient.interceptors.response.use(function (response) { console.log(response.cached); return response; });

The console just returns false.

Feature Suggestion: Gimme "Stale cache"

I used to use Fetch and some state management library as you said. And now switch to your great library but only one function is missing from my own use.

For slow networks, I usually show old data and if data not loaded in 1 sec, I inform the user and still load in the background. When finish laoding simply show fresh data. This is a very practical way becasue I don't interrupt user, maybe even he/she doesn't need the new data.

I think it would be great if I could pass a callback and it gives me stale cache data. When fresh data is pulled, it will call my callback and I'll get my new fresh data.

Maybe sounds wierd, but really is cool for slow networks.

How to force update a cached request that has a long TTL?

Hi,

I'm in the following situation: I have some requests that I'd like to cache for as long as possible, so I set a very long TTL, because my users might not be connected to the Internet for a long time. However, once in a while, I update the content, and I want to enable the users to fetch the new content whenever they are connected.

How can I force update a response? I know I can disable the cache with the cache:false option so that the users will be served a fresh version of the response, but from what I understand, the cache will be completely bypassed, i.e. the new response will not be saved locally, is that correct? If so, is there a way to force that behavior?

I thought about deleting the entry from the storage first, but that's a bit dangerous because if the request goes wrong, then the local version will be deleted, and I won't have a fresh version to replace it.

Many thanks for your hard work on this project!

feature request: cache override/force

It'd be useful to have an option on making a request to clear the existing cache for the id. This is because knowing the id of a request to invalidate it can be difficult.

The workaround I might use for now is to use the built in id generator and calculate the expected id from it, but it adds a lot of complexity.

I see this being implemented as:

  1. calculate id using the key generator
  2. calling await axios.storage.remove(id)
  3. running the request

axios custom response data types get stripped (converted to any)

Hi Arthur, sorry to create another issue so quickly. I'm actively this as well. Here are some images to illustrate the problem:

Notice the response type that I pass in on line 221:
Screen Shot 2021-12-27 at 3 26 14 PM

Now, when I use that function, notice that those types are not showing up, since it's been converted to 'any'.
Screen Shot 2021-12-27 at 3 27 06 PM

Here is how it should look, when I use axios alone:
Screen Shot 2021-12-27 at 3 28 15 PM

Thank you!

Basic Authorization

Hello,
Congrats for a excellent job!

I need to pass Authorization Basic in Header, but, when I pass the Headers, cache dont work

const api = setupCache(
  axios.create({
    baseURL: process.env.DEV
      ? "https://URL.com.br/wp-json"
      : "https://URL.com.br/wp-json",
    headers: {
      Authorization: `Basic ${window.btoa("pass")}`,
    },
  }),
  {
    storage: buildWebStorage(localStorage, "axios-cache:"),
    debug: console.log,
  }
);

If I remove the Headers, cache work

I do something wrong?

Thank you

Uncaught (in promise) Error: Use buildStorage() function at j (create.ts:47:1)

Description

This is in a React application written in TypeScript.

We're using buildWebStorage(localStorage). Occasionally the localStorage cache state will stay in loading. The network request is successful with a 200 status code, and the expected response data. To debug this, we're enabling development mode, by importing setupCache from axios-cache-interceptor/dev , however the following error shows:

unnamed

Screen Shot 2022-05-04 at 12 15 25 PM

Our cache setup:

Screen Shot 2022-05-04 at 12 28 15 PM

Any insight on:

  1. What causes cache to stay in a loading state?
  2. The cause of the aforementioned error?

bug: Request doesn't execute after a abortion.

Describe the bug

I've experienced that when i try to cancel a request and resubmit it right after, nothing seems to happen.

To Reproduce

In this CodePen, if i click the 'Request' button as first, everything seems to be fine, but after a reload, if i click first the 'With Quick Abort', all further requests will not be initiated.

Expected behavior

After the page load, when 'With Quick Abort' button is clicked, the first request will be aborted, while the second one will be sent and completed.

Additional context

  • Axios: v0.27.2
  • Axios Cache Interceptor: v0.10.7
  • What storage is being used: MemoryStorage
  • Node Version: v16.14.0
  • Browser (if applicable): Chrome 104.0.5112.81

P.S.: This plugin is very powerful and easy to use, I hope you can help me or tell me if I'm doing something wrong! ๐Ÿ˜Š

bug: Invalidating Cache not working

Describe the bug

When applying the logic to invalidate a cache neither approach is working, using the dev code to debug it looks like the Response not cached but storage is not loading is always being triggered.

It seems the logic cache.state !== 'loading' should be cache.state === 'loading' otherwise every request that is not a get request sees this branch as true.

As I do not know this library inside out I might be wrong, any help is appreciated. Thanks

To Reproduce

Follow the example outlined here to invalidate a cache invalidating-cache

Expected behavior

The cache is invalidated correctly.

Additional context

  • Axios: 0.26.0
  • Axios Cache Interceptor: 0.10.5
  • What storage is being used: Web Storage
  • Node Version: v14.19.0
  • Browser (if applicable): Chrome Version 102.0.5005.115

`staleIfError: true` should use the `stale-if-error` directive if present

Describe the bug

When using staleIfError: true, its time is resolved as forever, but if the cache-control header included a stale-if-error directive, that time should be used instead.

To Reproduce

axios.get('url to a server that returns stale-if-error', {
  cache: { staleIfError: true }
});

// The cache will be stale forever.

Expected behavior

When staleIfError is true and the server returned the stale-if-error directive, it should behave exactly the same as staleIfError: <ms in the stale-if-error directive>

Additional context

  • Axios: v1.3.1
  • Axios Cache Interceptor: v1.0.1

bug: Can't import form non EcmaScript module

Describe the bug

Getting this error while starting the project:

../app/node_modules/axios-cache-interceptor/dist/index.mjs
Can't import the named export 'deferred' from non EcmaScript module (only default export is available)

To Reproduce

Additional context

"axios": "^0.27.2",
"axios-cache-interceptor": "^0.10.7",
node: 14.7.0

Do you think there is a fix for this problem ?

TypeError: (0 , x.hash) is not a function

I have installed axios 0.27.2 and axios-cache-interceptor 0.10.7

Using the code from the readme.md

import Axios from 'axios';
import { setupCache } from 'axios-cache-interceptor';

// same object, but with updated typings.
const axios = setupCache(Axios);

const req1 = axios.get('https://api.example.com/');
const req2 = axios.get('https://api.example.com/');

const [res1, res2] = await Promise.all([req1, req2]);

res1.cached; // false
res2.cached; // true

I get the following output / error

file:///home/mike/axios-test/node_modules/axios-cache-interceptor/dist/index.mjs:1
import*as e from"cache-parser";import*as t from"fast-defer";import*as a from"object-code";var r={d:(e,t)=>{for(var a in t)r.o(t,a)&&!r.o(e,a)&&Object.defineProperty(e,a,{enumerable:!0,get:t[a]})},o:(e,t)=>Object.prototype.hasOwnProperty.call(e,t)},s={};r.d(s,{h4:()=>o,UN:()=>C,uu:()=>S,Kd:()=>I,ZF:()=>O,nv:()=>w,p:()=>l,E7:()=>d,NQ:()=>i,xK:()=>A,G6:()=>h,LN:()=>m,Bw:()=>y,Ad:()=>u,$k:()=>v,v8:()=>E,Jk:()=>g,tI:()=>p,iS:()=>f});const n=(e=>{var t={};return r.d(t,e),t})({parse:()=>e.parse}),o=Object.freeze({IfModifiedSince:"if-modified-since",LastModified:"last-modified",IfNoneMatch:"if-none-match",CacheControl:"cache-control",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=e=>{if(!e)return"not enough headers";const t=e[o.CacheControl];if(t){const{noCache:a,noStore:r,mustRevalidate:s,maxAge:i,immutable:c}=(0,n.parse)(String(t));if(a||r)return"dont cache";if(c)return 31536e6;if(s)return 0;if(void 0!==i){const t=e[o.Age];return t?1e3*(i-Number(t)):1e3*i}}const a=e[o.Expires];if(a){const e=Date.parse(String(a))-Date.now();return e>=0?e:"dont cache"}return"not enough headers"};const c=(e=>{var t={};return r.d(t,e),t})({deferred:()=>t.deferred});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 f(e,t){var a;t.headers||(t.headers={});const{etag:r,modifiedSince:s}=t.cache;if(r){const s=!0===r?null===(a=e.data)||void 0===a?void 0:a.headers[o.ETag]:r;s&&(t.headers[o.IfNoneMatch]=s)}s&&(t.headers[o.IfModifiedSince]=!0===s?e.data.headers[o.LastModified]||new Date(e.createdAt).toUTCString():s.toUTCString())}function l(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 h(e){const t=async t=>{var a;const r=t.id=e.generateKey(t);if(!1===t.cache)return t;if(t.cache=Object.assign(Object.assign({},e.defaults.cache),t.cache),!u(t.method,t.cache.methods))return t;let s=await e.storage.get(r,t);const n=t.cache.override;e:if("empty"===s.state||"stale"===s.state||n){if(e.waiting[r]&&!n&&(s=await e.storage.get(r,t),"empty"!==s.state)){0;break e}return e.waiting[r]=(0,c.deferred)(),null===(a=e.waiting[r])||void 0===a||a.catch((()=>{})),await e.storage.set(r,{state:"loading",previous:n?s.data?"stale":"empty":s.state,data:s.data,createdAt:n&&!s.createdAt?Date.now():s.createdAt},t),"stale"===s.state&&f(s,t),t.validateStatus=d(t.validateStatus),t}let o;if("loading"===s.state){const a=e.waiting[r];if(!a)return await e.storage.remove(r,t),t;0;try{o=await a}catch(e){return t}}else o=s.data;return t.adapter=()=>Promise.resolve({config:t,data:o.data,headers:o.headers,status:o.status,statusText:o.statusText,cached:!0,id:r}),t};return{onFulfilled:t,apply:()=>e.interceptors.request.use(t)}}async function g(e,t){var a;if("function"==typeof t)return t(e);const{statusCheck:r,responseMatch:s,containsHeaders:n}=t;if(r&&!await r(e.status)||s&&!await s(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 p(e,t,a){if("function"==typeof a)return a(t);for(const[r,s]of Object.entries(a)){if("delete"===s){await e.remove(r,t.config);continue}const a=await e.get(r,t.config);if("loading"===a.state)continue;const n=await s(a,t);"delete"!==n?"ignore"!==n&&await e.set(r,n,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,s,n;const i=a.id=null!==(r=(n=a.config).id)&&void 0!==r?r:n.id=e.generateKey(a.config);if(null!==(s=a.cached)&&void 0!==s||(a.cached=!1),a.cached)return a;const c=a.config.cache;if(!c)return Object.assign(Object.assign({},a),{cached:!1});const d=a.config,u=await e.storage.get(i,d);if((null==c?void 0:c.update)&&await p(e.storage,a,c.update),"loading"!==u.state)return a;if(!u.data&&!await g(a,c.cachePredicate))return await t(i,d),a;for(const e of Object.keys(a.headers))e.startsWith("x-axios-cache")&&delete a.headers[e];c.etag&&!0!==c.etag&&(a.headers[o.XAxiosCacheEtag]=c.etag),c.modifiedSince&&(a.headers[o.XAxiosCacheLastModified]=!0===c.modifiedSince?"use-cache-timestamp":c.modifiedSince.toUTCString());let f=c.ttl||-1;if(null==c?void 0:c.interpretHeader){const r=e.headerInterpreter(a.headers);if("dont cache"===r)return await t(i,d),a;f="not enough headers"===r?f:r}const h=l(a,u.data);"function"==typeof f&&(f=await f(a)),c.staleIfError&&(a.headers[o.XAxiosCacheStaleIfError]=String(f));const m={state:"cached",ttl:f,createdAt:Date.now(),data:h},v=e.waiting[i];return v&&(v.resolve(m.data),delete e.waiting[i]),await e.storage.set(i,m,d),a},r=async a=>{var r;const s=a.config;if(!(null==s?void 0:s.cache)||!s.id)throw a;const n=await e.storage.get(s.id,s),o=s.cache;if("loading"!==n.state||"stale"!==n.previous)throw await t(s.id,s),a;if(null==o?void 0:o.staleIfError){const t="function"==typeof o.staleIfError?await o.staleIfError(a.response,n,a):o.staleIfError;if(!0===t||"number"==typeof t&&n.createdAt+t>Date.now())return null===(r=e.waiting[s.id])||void 0===r||r.resolve(n.data),delete e.waiting[s.id],await e.storage.set(s.id,{state:"stale",createdAt:Date.now(),data:n.data},s),{cached:!0,config:s,id:s.id,data:n.data.data,headers:n.data.headers,status:n.data.status,statusText:n.data.statusText}}throw a};return{onFulfilled:a,onRejected:r,apply:()=>e.interceptors.response.use(a,r)}}const v=e=>!!e&&!!e["is-storage"];function w(e){const t=e.data.headers;return o.ETag in t||o.LastModified in t||o.XAxiosCacheEtag in t||o.XAxiosCacheStaleIfError in t||o.XAxiosCacheLastModified in t}function y(e){return e.createdAt+e.ttl<=Date.now()}function I({set:e,find:t,remove:a}){return{"is-storage":1,set:e,remove:a,get:async(r,s)=>{const n=await t(r,s);if(!n)return{state:"empty"};if("cached"!==n.state||!y(n))return n;if(w(n)){const t={state:"stale",createdAt:n.createdAt,data:n.data};return await e(r,t,s),t}return await a(r,s),{state:"empty"}}}}function S(e=!1){const t=I({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}const x=(e=>{var t={};return r.d(t,e),t})({hash:()=>a.hash}),b=/^\/|\/$/g;function C(e){return t=>{if(t.id)return t.id;const a=e(t);return"string"==typeof a||"number"==typeof a?`${a}`:`${(0,x.hash)(a)}`}}const A=C((({baseURL:e="",url:t="",method:a="get",params:r,data:s})=>(e&&(e=e.replace(b,"")),t&&(t=t.replace(b,"")),a&&(a=a.toLowerCase()),{url:e+(e&&t?"/":"")+t,params:r,method:a,data:s})));function E(e,t={}){var a,r,s,n,o;const c=e;if(c.storage=t.storage||S(),!v(c.storage))throw new Error("Use buildStorage() function");return c.waiting=t.waiting||{},c.generateKey=t.generateKey||A,c.headerInterpreter=t.headerInterpreter||i,c.requestInterceptor=t.requestInterceptor||h(c),c.responseInterceptor=t.responseInterceptor||m(c),c.debug=t.debug,c.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!==(s=t.modifiedSince)&&void 0!==s?s:!1===t.etag,interpretHeader:null===(n=t.interpretHeader)||void 0===n||n,staleIfError:null===(o=t.staleIfError)||void 0===o||o,override:!1},c.requestInterceptor.apply(),c.responseInterceptor.apply(),c}function O(e,t=""){return I({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 s=()=>e.setItem(t+a,JSON.stringify(r));try{return s()}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&&y(t[1])&&!w(t[1])&&e.removeItem(t[0]);try{return s()}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 s()}catch(e){}}}e.removeItem(t+a)}}})}var j=s.h4,N=s.UN,T=s.uu,M=s.Kd,L=s.ZF,K=s.nv,X=s.p,k=s.E7,D=s.NQ,J=s.xK,P=s.G6,R=s.LN,U=s.Bw,q=s.Ad,H=s.$k,$=s.v8,F=s.Jk,G=s.tI,W=s.iS;export{j as Header,N as buildKeyGenerator,T as buildMemoryStorage,M as buildStorage,L as buildWebStorage,K as canStale,X as createCacheResponse,k as createValidateStatus,D as defaultHeaderInterpreter,J as defaultKeyGenerator,P as defaultRequestInterceptor,R as defaultResponseInterceptor,U as isExpired,q as isMethodIn,H as isStorage,$ as setupCache,F as testCachePredicate,G as updateCache,W as updateStaleRequest};
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        

TypeError: (0 , x.hash) is not a function
    at Function.generateKey (file:///home/mike/axios-test/node_modules/axios-cache-interceptor/dist/index.mjs:1:6720)
    at t (file:///home/mike/axios-test/node_modules/axios-cache-interceptor/dist/index.mjs:1:2060)
    at async Promise.all (index 0)
    at async file:///home/mike/axios-test/test.mjs:10:22

So I'm sure I'm doing something wrong as this seems fairly fundamental, and I can see no open / closed issues that seem similar.

I did try with version 1.1.3 of axios, then I get a different error:

file:///home/mike/axios-test/node_modules/axios/lib/adapters/http.js:7
import {getProxyForUrl} from 'proxy-from-env';
        ^^^^^^^^^^^^^^
SyntaxError: The requested module 'proxy-from-env' is expected to be of type CommonJS, which does not support named exports. CommonJS modules can be imported by importing the default export.
For example:
import pkg from 'proxy-from-env';
const {getProxyForUrl} = pkg;
    at ModuleJob._instantiate (internal/modules/esm/module_job.js:98:21)
    at async ModuleJob.run (internal/modules/esm/module_job.js:137:5)
    at async Loader.import (internal/modules/esm/loader.js:165:24)
    at async Object.loadESM (internal/process/esm_loader.js:68:5)

which seems to be related to this issue - when I apply this patch that error goes away but TypeError: (0 , x.hash) is not a function then comes back.

Any advice / comments appreciated. Thanks.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.