repo_description: Promise based HTTP client for the browser and node.js
repo_topics: hacktoberfest http-client javascript nodejs promise
code: import utils from '../utils.js';
  import httpAdapter from './http.js';
  import xhrAdapter from './xhr.js';
  import * as fetchAdapter from './fetch.js';
  import AxiosError from '../core/AxiosError.js';
  
  /**
   * Known adapters mapping.
   * Provides environment-specific adapters for Axios:
   * - `http` for Node.js
   * - `xhr` for browsers
   * - `fetch` for fetch API-based requests
   *
   * @type {Object<string, Function|Object>}
   */
  const knownAdapters = {
    http: httpAdapter,
    xhr: xhrAdapter,
    fetch: {
      get: fetchAdapter.getFetch,
    },
  };
  
  // Assign adapter names for easier debugging and identification
  utils.forEach(knownAdapters, (fn, value) => {
    if (fn) {
      try {
        Object.defineProperty(fn, 'name', { value });
      } catch (e) {
        // eslint-disable-next-line no-empty
      }
      Object.defineProperty(fn, 'adapterName', { value });
    }
  });
  
  /**
   * Render a rejection reason string for unknown or unsupported adapters
   *
   * @param {string} reason
   * @returns {string}
   */
  const renderReason = (reason) => `- ${reason}`;
  
  /**
   * Check if the adapter is resolved (function, null, or false)
   *
   * @param {Function|null|false} adapter
   * @returns {boolean}
   */
  const isResolvedHandle = (adapter) =>
    utils.isFunction(adapter) || adapter === null || adapter === false;
  
  /**
   * Get the first suitable adapter from the provided list.
   * Tries each adapter in order until a supported one is found.
   * Throws an AxiosError if no adapter is suitable.
   *
   * @param {Array<string|Function>|string|Function} adapters - Adapter(s) by name or function.
   * @param {Object} config - Axios request configuration
   * @throws {AxiosError} If no suitable adapter is available
   * @returns {Function} The resolved adapter function
   */
  function getAdapter(adapters, config) {
    adapters = utils.isArray(adapters) ? adapters : [adapters];
  
    const { length } = adapters;
    let nameOrAdapter;
    let adapter;
  
    const rejectedReasons = {};
  
    for (let i = 0; i < length; i++) {
      nameOrAdapter = adapters[i];
      let id;
  
      adapter = nameOrAdapter;
  
      if (!isResolvedHandle(nameOrAdapter)) {
        adapter = knownAdapters[(id = String(nameOrAdapter)).toLowerCase()];
  
        if (adapter === undefined) {
          throw new AxiosError(`Unknown adapter '${id}'`);
        }
      }
  
      if (adapter && (utils.isFunction(adapter) || (adapter = adapter.get(config)))) {
        break;
      }
  
      rejectedReasons[id || '#' + i] = adapter;
    }
  
    if (!adapter) {
      const reasons = Object.entries(rejectedReasons).map(
        ([id, state]) =>
          `adapter ${id} ` +
          (state === false ? 'is not supported by the environment' : 'is not available in the build')
      );
  
      let s = length
        ? reasons.length > 1
          ? 'since :\n' + reasons.map(renderReason).join('\n')
          : ' ' + renderReason(reasons[0])
        : 'as no adapter specified';
  
      throw new AxiosError(
        `There is no suitable adapter to dispatch the request ` + s,
        'ERR_NOT_SUPPORT'
      );
    }
  
    return adapter;
  }
  
  /**
   * Exports Axios adapters and utility to resolve an adapter
   */
  export default {
    /**
     * Resolve an adapter from a list of adapter names or functions.
     * @type {Function}
     */
    getAdapter,
  
    /**
     * Exposes all known adapters
     * @type {Object<string, Function|Object>}
     */
    adapters: knownAdapters,
  };
  