softonic / axios-retry

Axios plugin that intercepts failed requests and retries them whenever possible
Other
1.9k stars 167 forks source link

TypeError: axiosRetry is not a function in v4.0.0 #259

Closed nodegin closed 4 months ago

nodegin commented 11 months ago

With latest 4.0.0 I got TypeError: axiosRetry is not a function for import axiosRetry from 'axios-retry'; imports, if I change to import * as axiosRetry from 'axios-retry'; it seem can be imported but the typing will be broken:

This expression is not callable.
  Type 'typeof import("/Users/user/Desktop/project/node_modules/axios-retry/dist/cjs/index")' has no call signatures.
DominicRoyStang commented 11 months ago

I'm getting this error as well in unit tests in an ESM Typescript codebase using jest, ts-jest (and NODE_OPTIONS=--experimental-vm-modules set).

mindhells commented 11 months ago

can't reproduce this in a simple ESM (type="module") project see https://stackblitz.com/edit/stackblitz-starters-dzcrb9?file=index.js please provide an minimum example to reproduce the issue Have in mind that, since 4.0, you need to use this method to import from CJS:

// CommonJS
const axiosRetry = require('axios-retry').default;
yutak23 commented 11 months ago

I could not reproduce this on my end, at least with the following settings.

// tsconfig.json
{
    "compilerOptions": {
        "lib": [
            "es2023"
        ],
        "module": "node16",
        "target": "es2022",
        "strict": true,
        "esModuleInterop": true,
        "skipLibCheck": true,
        "forceConsistentCasingInFileNames": true,
        "moduleResolution": "node16",
        "allowUnusedLabels": false,
        "allowUnreachableCode": false,
        "exactOptionalPropertyTypes": true,
        "noFallthroughCasesInSwitch": true,
        "noImplicitOverride": true,
        "noImplicitReturns": true,
        "noPropertyAccessFromIndexSignature": true,
        "noUncheckedIndexedAccess": true,
        "noUnusedLocals": true,
        "noUnusedParameters": true,
        "checkJs": true,
        "outDir": "./build",
        "declaration": true,
        "sourceMap": true
    },
    "files": [
        "./srv/app.ts"
    ],
    "include": [
        "srv/**/*.ts"
    ],
    "exclude": [
        "node_modules",
        "build"
    ]
}
// package.json
{
    ...
    "type": "commonjs",
    "devDependencies": {
        "typescript": "~5.3.2"
    },
    "dependencies": {
        "axios": "^1.6.2",
        "axios-retry": "^4.0.0"
    }
}
import axios from 'axios';
import axiosRetry from 'axios-retry';

axiosRetry(axios);
axiosRetry(axios, { retries: 3, retryDelay: axiosRetry.exponentialDelay });

image

nodegin commented 11 months ago

I created a minimal reproduction repo https://github.com/nodegin/axios-retry-v4-bug

You can try npm install && npm run build and you will see the bug I am using Vite SSR feature in my project

so it seem for CJS it expect default module export should be exported by just module.exports but in v4 case, the export is under default which breaks normal CJS imports

nodegin commented 11 months ago

Comparing the CJS version of axios and axios-retry it seem the index should export both version for default and non-default:

axios:

import axios from './lib/axios.js';

// This module is intended to unwrap Axios default export as named.
// Keep top-level export same with static properties
// so that it can keep same with es module or cjs
const {
  Axios,
  AxiosError,
  CanceledError,
  isCancel,
  CancelToken,
  VERSION,
  all,
  Cancel,
  isAxiosError,
  spread,
  toFormData,
  AxiosHeaders,
  HttpStatusCode,
  formToJSON,
  getAdapter,
  mergeConfig
} = axios;

export {
  axios as default,
  Axios,
  AxiosError,
  CanceledError,
  isCancel,
  CancelToken,
  VERSION,
  all,
  Cancel,
  isAxiosError,
  spread,
  toFormData,
  AxiosHeaders,
  HttpStatusCode,
  formToJSON,
  getAdapter,
  mergeConfig
}

axios-retry:

const axiosRetry = ...
axiosRetry.isNetworkError = isNetworkError;
axiosRetry.isSafeRequestError = isSafeRequestError;
axiosRetry.isIdempotentRequestError = isIdempotentRequestError;
axiosRetry.isNetworkOrIdempotentRequestError = isNetworkOrIdempotentRequestError;
axiosRetry.exponentialDelay = exponentialDelay;
axiosRetry.isRetryableError = isRetryableError;
exports.default = axiosRetry;

Therefore in axios, you can both import const axios = require("axios") or const axios = require("axios").default

vivmagarwal commented 10 months ago

const axios = require("axios").default works for CJS

fredsensibill commented 9 months ago

I'm getting this error as well in unit tests in an ESM Typescript codebase using jest, ts-jest (and NODE_OPTIONS=--experimental-vm-modules set).

This is exactly my case. Type check succeeds if I run tsc --noEmit but my jest tests fail with This expression is not callable

jeremysimmons commented 9 months ago

This threw me off too. I would much prefer that the axios-retry CJS module behave similarly to axios. I do not want to have to know about adding .default to the end of require('axios-retry').

ibqn commented 7 months ago

I created a minimal reproduction repo https://github.com/nodegin/axios-retry-v4-bug

You can try npm install && npm run build and you will see the bug I am using Vite SSR feature in my project

so it seem for CJS it expect default module export should be exported by just module.exports but in v4 case, the export is under default which breaks normal CJS imports

so how this minimal example should be fixed? I am still confused 🫤

edsonboldrini commented 5 months ago

I'm converting a project to esmodules and started importing async-retry like this and worked for me, but it's still very ugly:

import axiosRetry from '../../../node_modules/axios-retry/dist/esm/index.js';

Also had to add it in my jest.config.ts to prevent errors import outside a module:

{
  ...
  transformIgnorePatterns: ['node_modules/(?!(p-queue|p-timeout|axios-retry)/)'],
  ...
}
nodegin commented 4 months ago

Just an update to this issue, I switched to gaxios which provide retry functionality out of the box