Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for axios 1.6.0 with impors from "./unsafe/*" #31

Open
bardisg opened this issue Nov 7, 2023 · 6 comments
Open

Support for axios 1.6.0 with impors from "./unsafe/*" #31

bardisg opened this issue Nov 7, 2023 · 6 comments

Comments

@bardisg
Copy link

bardisg commented Nov 7, 2023

Hi! 👋

Firstly, thanks for your work on this project! 🙂

Today I used patch-package to patch @vespaiach/axios-fetch-adapter@0.3.1 for the project I'm working on.

I needed to support axios version 1.6.0

Here is the diff that solved my problem:

diff --git a/node_modules/@vespaiach/axios-fetch-adapter/index.js b/node_modules/@vespaiach/axios-fetch-adapter/index.js
index 527e282..649926f 100644
--- a/node_modules/@vespaiach/axios-fetch-adapter/index.js
+++ b/node_modules/@vespaiach/axios-fetch-adapter/index.js
@@ -1,8 +1,9 @@
 import axios from 'axios';
-import settle from 'axios/lib/core/settle';
-import buildURL from 'axios/lib/helpers/buildURL';
-import buildFullPath from 'axios/lib/core/buildFullPath';
-import { isUndefined, isStandardBrowserEnv, isFormData } from 'axios/lib/utils';
+import settle from 'axios/unsafe/core/settle';
+import buildURL from 'axios/unsafe/helpers/buildURL';
+import buildFullPath from 'axios/unsafe/core/buildFullPath';
+import * as browserUtils from 'axios/unsafe/platform/browser';
+import * as utils from 'axios/unsafe/utils';
 
 /**
  * - Create a request object
@@ -106,7 +107,7 @@ function createRequest(config) {
 
         // In these cases the browser will automatically set the correct Content-Type,
         // but only if that header hasn't been set yet. So that's why we're deleting it.
-        if (isFormData(options.body) && isStandardBrowserEnv()) {
+        if (utils.default.isFormData(options.body) && browserUtils.default.isStandardBrowserEnv()) {
             headers.delete('Content-Type');
         }
     }
@@ -127,7 +128,7 @@ function createRequest(config) {
     }
     // This config is similar to XHR’s withCredentials flag, but with three available values instead of two.
     // So if withCredentials is not set, default value 'same-origin' will be used
-    if (!isUndefined(config.withCredentials)) {
+    if (!utils.default.isUndefined(config.withCredentials)) {
         options.credentials = config.withCredentials ? 'include' : 'omit';
     }
 

This issue body was partially generated by patch-package.

@gbyesiltas
Copy link

Would be great to have this merged in to support axios v1 🥹

@pablovinc
Copy link

Hello, do we have any updates on this? I'm trying to update the axios version to 1.6.5 but I'm getting this error when trying to build my extension

@PedroS11
Copy link

PedroS11 commented Feb 6, 2024

I have the same issue @pablovinc
I think @vespaiach might no longer update this repo

@gbyesiltas
Copy link

By the way as a workaround you can just // @ts-ignore these imports

@PedroS11
Copy link

PedroS11 commented Feb 9, 2024

By the way as a workaround you can just // @ts-ignore these imports

If the implementation needs to be changed, wouldn't that just remove the error message but still breaking the code?

@iwgyyyy
Copy link

iwgyyyy commented Mar 19, 2024

Actually, you can copy this code, and then import it directly. It worked for me.

axios: 1.6.7

// adapter.js

import axios from 'axios';
import settle from 'axios/unsafe/core/settle.js';
import buildURL from 'axios/unsafe/helpers/buildURL.js';
import buildFullPath from 'axios/unsafe/core/buildFullPath.js';
import * as utils from 'axios/unsafe/utils.js';

/**
 * 
 * Note:
 * 
 *   This function is for backward compatible.
 * 
 *  
 * Update an Error with the specified config, error code, and response.
 *
 * @param {Error} error The error to update.
 * @param {Object} config The config.
 * @param {string} [code] The error code (for example, 'ECONNABORTED').
 * @param {Object} [request] The request.
 * @param {Object} [response] The response.
 * @returns {Error} The error.
 */
function enhanceError(error, config, code, request, response) {
  error.config = config;
  if (code) {
    error.code = code;
  }

  error.request = request;
  error.response = response;
  error.isAxiosError = true;

  error.toJSON = function toJSON() {
    return {
      // Standard
      message: this.message,
      name: this.name,
      // Microsoft
      description: this.description,
      number: this.number,
      // Mozilla
      fileName: this.fileName,
      lineNumber: this.lineNumber,
      columnNumber: this.columnNumber,
      stack: this.stack,
      // Axios
      config: this.config,
      code: this.code,
      status: this.response && this.response.status ? this.response.status : null
    };
  };
  return error;
}

/**
 * Note:
 * 
 *   From version >= 0.27.0, createError function is replaced by AxiosError class.
 *   So I copy the old createError function here for backward compatible.
 * 
 * 
 * 
 * Create an Error with the specified message, config, error code, request and response.
 *
 * @param {string} message The error message.
 * @param {Object} config The config.
 * @param {string} [code] The error code (for example, 'ECONNABORTED').
 * @param {Object} [request] The request.
 * @param {Object} [response] The response.
 * @returns {Error} The created error.
 */
function createError(message, config, code, request, response) {
  if (axios.AxiosError && typeof axios.AxiosError === 'function') {
    return new axios.AxiosError(message, axios.AxiosError[code], config, request, response);
  }

  const error = new Error(message);
  return enhanceError(error, config, code, request, response);
}

function isStandardBrowserEnv() {
  if (typeof navigator !== 'undefined' && (navigator.product === 'ReactNative'
                                           || navigator.product === 'NativeScript'
                                           || navigator.product === 'NS')) {
    return false;
  }
  return (
    typeof window !== 'undefined'
    && typeof document !== 'undefined'
  );
}

/**
 * Fetch API stage two is to get response body. This funtion tries to retrieve
 * response body based on response's type
 */
async function getResponse(request, config) {
  let stageOne;
  try {
    stageOne = await fetch(request);
  } catch (e) {
    return createError('Network Error', config, 'ERR_NETWORK', request);
  }

  const response = {
    ok: stageOne.ok,
    status: stageOne.status,
    statusText: stageOne.statusText,
    headers: new Headers(stageOne.headers), // Make a copy of headers
    config,
    request,
  };

  if (stageOne.status >= 200 && stageOne.status !== 204) {
    switch (config.responseType) {
      case 'arraybuffer':
        response.data = await stageOne.arrayBuffer();
        break;
      case 'blob':
        response.data = await stageOne.blob();
        break;
      case 'json':
        response.data = await stageOne.json();
        break;
      case 'formData':
        response.data = await stageOne.formData();
        break;
      default:
        response.data = await stageOne.text();
        break;
    }
  }

  return response;
}

/**
 * This function will create a Request object based on configuration's axios
 */
function createRequest(config) {
  const headers = new Headers(config.headers);

  // HTTP basic authentication
  if (config.auth) {
    const username = config.auth.username || '';
    const password = config.auth.password ? decodeURI(encodeURIComponent(config.auth.password)) : '';
    headers.set('Authorization', `Basic ${btoa(`${username}:${password}`)}`);
  }

  const method = config.method.toUpperCase();
  const options = {
    headers,
    method,
  };
  if (method !== 'GET' && method !== 'HEAD') {
    options.body = config.data;

    // In these cases the browser will automatically set the correct Content-Type,
    // but only if that header hasn't been set yet. So that's why we're deleting it.
    if (utils.default.isFormData(options.body) && isStandardBrowserEnv()) {
      headers.delete('Content-Type');
    }
  }
  if (config.mode) {
    options.mode = config.mode;
  }
  if (config.cache) {
    options.cache = config.cache;
  }
  if (config.integrity) {
    options.integrity = config.integrity;
  }
  if (config.redirect) {
    options.redirect = config.redirect;
  }
  if (config.referrer) {
    options.referrer = config.referrer;
  }
  // This config is similar to XHR’s withCredentials flag, but with three available values instead of two.
  // So if withCredentials is not set, default value 'same-origin' will be used
  if (!utils.default.isUndefined(config.withCredentials)) {
    options.credentials = config.withCredentials ? 'include' : 'omit';
  }

  const fullPath = buildFullPath(config.baseURL, config.url);
  const url = buildURL(fullPath, config.params, config.paramsSerializer);

  // Expected browser to throw error if there is any wrong configuration value
  return new Request(url, options);
}

/**
 * - Create a request object
 * - Get response body
 * - Check if timeout
 */
export default async function fetchAdapter(config) {
  const request = createRequest(config);
  const promiseChain = [getResponse(request, config)];

  if (config.timeout && config.timeout > 0) {
    promiseChain.push(
      new Promise((res) => {
        setTimeout(() => {
          const message = config.timeoutErrorMessage
            ? config.timeoutErrorMessage
            : `timeout of ${config.timeout}ms exceeded`;
          res(createError(message, config, 'ECONNABORTED', request));
        }, config.timeout);
      })
    );
  }

  const data = await Promise.race(promiseChain);
  return new Promise((resolve, reject) => {
    if (data instanceof Error) {
      reject(data);
    } else {
      Object.prototype.toString.call(config.settle) === '[object Function]'
        ? config.settle(resolve, reject, data)
        : settle(resolve, reject, data);
    }
  });
}
// your axios.js

import axios, { isAxiosError } from 'axios';
import fetchAdapter from './adapter';

const instance = axios.create({
  baseURL: '',
  timeout: 300000,
  adapter: fetchAdapter,
});

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants