'use strict';

var ebec = require('ebec');
var axios = require('axios');
var axiosRetry = require('axios-retry');

/*
 * Copyright (c) 2021-2021.
 * Author Peter Placzek (tada5hi)
 * For the full copyright and license information,
 * view the LICENSE file that was distributed with this source code.
 */

var configMap = {};
function setConfig(value, key) {
  key = key || 'default';
  value = buildConfig(value);
  configMap[key] = value;
  return value;
}
function useConfig(key) {
  key = key || 'default';
  if (typeof configMap[key] === 'undefined') {
    return buildConfig();
  }
  return configMap[key];
}
function buildConfig(config) {
  config = config || {};
  config.extra = config.extra || {};
  return config;
}

/*
 * Copyright (c) 2022.
 * Author Peter Placzek (tada5hi)
 * For the full copyright and license information,
 * view the LICENSE file that was distributed with this source code.
 */

exports.ErrorCode = void 0;
(function (ErrorCode) {
  ErrorCode["AUTHORIZATION_HEADER_INVALID"] = "auth_header_invalid";
  ErrorCode["AUTHORIZATION_HEADER_PARSE"] = "auth_header_parse";
  ErrorCode["AUTHORIZATION_HEADER_TYPE_PARSE"] = "auth_header_type_parse";
})(exports.ErrorCode || (exports.ErrorCode = {}));

function _typeof(obj) {
  "@babel/helpers - typeof";

  return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (obj) {
    return typeof obj;
  } : function (obj) {
    return obj && "function" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
  }, _typeof(obj);
}
function _classCallCheck(instance, Constructor) {
  if (!(instance instanceof Constructor)) {
    throw new TypeError("Cannot call a class as a function");
  }
}
function _defineProperties(target, props) {
  for (var i = 0; i < props.length; i++) {
    var descriptor = props[i];
    descriptor.enumerable = descriptor.enumerable || false;
    descriptor.configurable = true;
    if ("value" in descriptor) descriptor.writable = true;
    Object.defineProperty(target, descriptor.key, descriptor);
  }
}
function _createClass(Constructor, protoProps, staticProps) {
  if (protoProps) _defineProperties(Constructor.prototype, protoProps);
  if (staticProps) _defineProperties(Constructor, staticProps);
  Object.defineProperty(Constructor, "prototype", {
    writable: false
  });
  return Constructor;
}
function _inherits(subClass, superClass) {
  if (typeof superClass !== "function" && superClass !== null) {
    throw new TypeError("Super expression must either be null or a function");
  }
  subClass.prototype = Object.create(superClass && superClass.prototype, {
    constructor: {
      value: subClass,
      writable: true,
      configurable: true
    }
  });
  Object.defineProperty(subClass, "prototype", {
    writable: false
  });
  if (superClass) _setPrototypeOf(subClass, superClass);
}
function _getPrototypeOf(o) {
  _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function _getPrototypeOf(o) {
    return o.__proto__ || Object.getPrototypeOf(o);
  };
  return _getPrototypeOf(o);
}
function _setPrototypeOf(o, p) {
  _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function _setPrototypeOf(o, p) {
    o.__proto__ = p;
    return o;
  };
  return _setPrototypeOf(o, p);
}
function _isNativeReflectConstruct() {
  if (typeof Reflect === "undefined" || !Reflect.construct) return false;
  if (Reflect.construct.sham) return false;
  if (typeof Proxy === "function") return true;
  try {
    Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {}));
    return true;
  } catch (e) {
    return false;
  }
}
function _assertThisInitialized(self) {
  if (self === void 0) {
    throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
  }
  return self;
}
function _possibleConstructorReturn(self, call) {
  if (call && (typeof call === "object" || typeof call === "function")) {
    return call;
  } else if (call !== void 0) {
    throw new TypeError("Derived constructors may only return object or undefined");
  }
  return _assertThisInitialized(self);
}
function _createSuper(Derived) {
  var hasNativeReflectConstruct = _isNativeReflectConstruct();
  return function _createSuperInternal() {
    var Super = _getPrototypeOf(Derived),
      result;
    if (hasNativeReflectConstruct) {
      var NewTarget = _getPrototypeOf(this).constructor;
      result = Reflect.construct(Super, arguments, NewTarget);
    } else {
      result = Super.apply(this, arguments);
    }
    return _possibleConstructorReturn(this, result);
  };
}

var AuthorizationHeaderError = /*#__PURE__*/function (_BaseError) {
  _inherits(AuthorizationHeaderError, _BaseError);
  var _super = _createSuper(AuthorizationHeaderError);
  function AuthorizationHeaderError(options) {
    _classCallCheck(this, AuthorizationHeaderError);
    return _super.call(this, ebec.mergeOptions(options || {}), {
      code: exports.ErrorCode.AUTHORIZATION_HEADER_INVALID,
      message: 'The authorization header is not valid.'
    });
  }

  /* istanbul ignore next */
  _createClass(AuthorizationHeaderError, null, [{
    key: "parse",
    value: function parse() {
      throw new AuthorizationHeaderError({
        code: exports.ErrorCode.AUTHORIZATION_HEADER_PARSE,
        message: 'The authorization header value could not be parsed.'
      });
    }

    /* istanbul ignore next */
  }, {
    key: "parseType",
    value: function parseType() {
      throw new AuthorizationHeaderError({
        code: exports.ErrorCode.AUTHORIZATION_HEADER_TYPE_PARSE,
        message: 'The authorization header value type must either be \'Bearer\' or \'Basic\''
      });
    }
  }]);
  return AuthorizationHeaderError;
}(ebec.BaseError);

/*
 * Copyright (c) 2022.
 * Author Peter Placzek (tada5hi)
 * For the full copyright and license information,
 * view the LICENSE file that was distributed with this source code.
 */

exports.AuthorizationHeaderType = void 0;
(function (AuthorizationHeaderType) {
  AuthorizationHeaderType["BEARER"] = "Bearer";
  AuthorizationHeaderType["BASIC"] = "Basic";
  AuthorizationHeaderType["X_API_KEY"] = "X-API-Key";
  AuthorizationHeaderType["API_KEY"] = "API-Key";
})(exports.AuthorizationHeaderType || (exports.AuthorizationHeaderType = {}));

/*
 * Copyright (c) 2021.
 * Author Peter Placzek (tada5hi)
 * For the full copyright and license information,
 * view the LICENSE file that was distributed with this source code.
 */
function parseAuthorizationHeader(value) {
  var parts = value.split(' ');
  if (parts.length < 2) {
    throw AuthorizationHeaderError.parseType();
  }
  var type = parts[0].toLowerCase();
  var id = parts[1];
  switch (type) {
    case 'basic':
      {
        var base64Decoded = Buffer.from(id, 'base64').toString('utf-8');
        var base64Parts = base64Decoded.split(':');
        if (base64Parts.length !== 2) {
          throw AuthorizationHeaderError.parse();
        }
        return {
          type: exports.AuthorizationHeaderType.BASIC,
          username: base64Parts[0],
          password: base64Parts[1]
        };
      }
    case 'bearer':
      return {
        type: exports.AuthorizationHeaderType.BEARER,
        token: id
      };
    case 'api-key':
    case 'x-api-key':
      return {
        type: type === 'api-key' ? exports.AuthorizationHeaderType.API_KEY : exports.AuthorizationHeaderType.X_API_KEY,
        key: id
      };
    default:
      throw AuthorizationHeaderError.parseType();
  }
}
function stringifyAuthorizationHeader(header) {
  switch (header.type) {
    case exports.AuthorizationHeaderType.BASIC:
      {
        var basicStr = Buffer.from("".concat(header.username, ":").concat(header.password)).toString('base64');
        return "Basic ".concat(basicStr);
      }
    case exports.AuthorizationHeaderType.BEARER:
      return "Bearer ".concat(header.token);
    case exports.AuthorizationHeaderType.X_API_KEY:
    case exports.AuthorizationHeaderType.API_KEY:
      return "".concat(header.type, " ").concat(header.key);
  }
  return '';
}

var Client = /*#__PURE__*/function () {
  // ---------------------------------------------------------------------------------

  function Client(config) {
    _classCallCheck(this, Client);
    config = config || {};
    var client = axios.create(config.driver);
    if (config.retry) {
      var retryConfig = {};
      if (typeof config.retry !== 'boolean') {
        retryConfig = config.retry;
      }
      axiosRetry(client, retryConfig);
    }
    this.driver = client;
  }

  // ---------------------------------------------------------------------------------
  _createClass(Client, [{
    key: "setDriver",
    value: function setDriver(client) {
      this.driver = client;
    }

    /**
     * Return driver config.
     *
     * @return AxiosDefaults<any>
     */
  }, {
    key: "config",
    get: function get() {
      return this.driver.defaults;
    }

    /**
     * Return base url
     *
     * @param config
     *
     * @return string
     */
  }, {
    key: "getUri",
    value: function getUri(config) {
      return this.driver.getUri(config);
    }

    // ---------------------------------------------------------------------------------

    /**
     * Set a header for all upcoming requests.
     *
     * @param key
     * @param value
     */
  }, {
    key: "setHeader",
    value: function setHeader(key, value) {
      this.driver.defaults.headers.common[key] = value;
      return this;
    }

    /**
     * Unset a specific for all upcoming requests.
     *
     * @param key
     */
  }, {
    key: "unsetHeader",
    value: function unsetHeader(key) {
      if (key in this.driver.defaults.headers.common) {
        delete this.driver.defaults.headers.common[key];
      }
      return this;
    }

    /**
     * Unset all defined headers for the upcoming requests.
     */
  }, {
    key: "resetHeader",
    value: function resetHeader() {
      this.driver.defaults.headers.common = {};
      return this;
    }

    // ---------------------------------------------------------------------------------

    /**
     * Set an authorization header (basic, api-key, bearer).
     *
     * @param options
     */
  }, {
    key: "setAuthorizationHeader",
    value: function setAuthorizationHeader(options) {
      this.setHeader('Authorization', stringifyAuthorizationHeader(options));
      return this;
    }

    /**
     * Unset an authorization header.
     */
  }, {
    key: "unsetAuthorizationHeader",
    value: function unsetAuthorizationHeader() {
      this.unsetHeader('Authorization');
      return this;
    }

    // ---------------------------------------------------------------------------------

    /**
     * Make a custom request.
     *
     * @param config
     */
  }, {
    key: "request",
    value: function request(config) {
      return this.driver.request(config);
    }

    // ---------------------------------------------------------------------------------

    /**
     * Request a resource with the GET method.
     *
     * @param url
     * @param config
     */
  }, {
    key: "get",
    value: function get(url, config) {
      return this.driver.get(url, config);
    }

    // ---------------------------------------------------------------------------------

    /**
     * Delete a resource with the DELETE method.
     *
     * @param url
     * @param config
     */
  }, {
    key: "delete",
    value: function _delete(url, config) {
      return this.driver["delete"](url, config);
    }

    // ---------------------------------------------------------------------------------

    /**
     * Make a verification resource with the HEAD method.
     *
     * @param url
     * @param config
     */
  }, {
    key: "head",
    value: function head(url, config) {
      return this.driver.head(url, config);
    }

    // ---------------------------------------------------------------------------------

    /**
     * Create a resource with the POST method.
     *
     * @param url
     * @param data
     * @param config
     */
  }, {
    key: "post",
    value: function post(url, data, config) {
      return this.driver.post(url, data, config);
    }

    /**
     * Create a resource with the POST method and FormData formatted payload.
     *
     * @param url
     * @param data
     * @param config
     */
  }, {
    key: "postForm",
    value: function postForm(url, data, config) {
      return this.driver.postForm(url, data, config);
    }

    // ---------------------------------------------------------------------------------

    /**
     * Update a resource with the PUT method.
     *
     * @param url
     * @param data
     * @param config
     */
  }, {
    key: "put",
    value: function put(url, data, config) {
      return this.driver.put(url, data, config);
    }

    /**
     * Update a resource with the PUT method and FormData formatted payload.
     *
     * @param url
     * @param data
     * @param config
     */
  }, {
    key: "putForm",
    value: function putForm(url, data, config) {
      return this.driver.putForm(url, data, config);
    }

    // ---------------------------------------------------------------------------------

    /**
     * Update a resource with the PATCH method.
     *
     * @param url
     * @param data
     * @param config
     */
  }, {
    key: "patch",
    value: function patch(url, data, config) {
      return this.driver.patch(url, data, config);
    }

    /**
     * Update a resource with the PATCH method and FormData formatted payload.
     *
     * @param url
     * @param data
     * @param config
     */
  }, {
    key: "patchForm",
    value: function patchForm(url, data, config) {
      return this.driver.patchForm(url, data, config);
    }

    //---------------------------------------------------------------------------------

    /**
     * Mount a response interceptor.
     *
     * @param onFulfilled
     * @param onRejected
     */
  }, {
    key: "mountResponseInterceptor",
    value: function mountResponseInterceptor(onFulfilled, onRejected) {
      return this.driver.interceptors.response.use(onFulfilled, onRejected);
    }

    /**
     * Unmount a response interceptor.
     *
     * @param id
     */
  }, {
    key: "unmountResponseInterceptor",
    value: function unmountResponseInterceptor(id) {
      this.driver.interceptors.response.eject(id);
      return this;
    }

    //---------------------------------------------------------------------------------

    /**
     * Mount a request interceptor.
     *
     * @param onFulfilled
     * @param onRejected
     */
  }, {
    key: "mountRequestInterceptor",
    value: function mountRequestInterceptor(onFulfilled, onRejected) {
      return this.driver.interceptors.request.use(onFulfilled, onRejected);
    }

    /**
     * Unmount a request interceptor.
     *
     * @param id
     */
  }, {
    key: "unmountRequestInterceptor",
    value: function unmountRequestInterceptor(id) {
      this.driver.interceptors.request.eject(id);
      return this;
    }
  }]);
  return Client;
}();

function isClientError(error) {
  if (_typeof(error) !== 'object') {
    return false;
  }
  if (Object.prototype.hasOwnProperty.call(error, 'config') && Object.prototype.hasOwnProperty.call(error, 'isAxiosError') && typeof error.isAxiosError === 'boolean') {
    return !!error.isAxiosError;
  }
  return axios.isAxiosError(error);
}

/*
 * Copyright (c) 2021.
 * Author Peter Placzek (tada5hi)
 * For the full copyright and license information,
 * view the LICENSE file that was distributed with this source code.
 */

// eslint-disable-next-line @typescript-eslint/ban-types
function hasOwnProperty(obj, prop) {
  return Object.prototype.hasOwnProperty.call(obj, prop);
}

/*
 * Copyright (c) 2022.
 * Author Peter Placzek (tada5hi)
 * For the full copyright and license information,
 * view the LICENSE file that was distributed with this source code.
 */
var instanceMap = {};
function setClient(client, key) {
  key = key || 'default';
  instanceMap[key] = client;
  return client;
}
function useClient(key) {
  key = key || 'default';
  var config = useConfig(key);
  if (Object.prototype.hasOwnProperty.call(instanceMap, key)) {
    return instanceMap[key];
  }
  var instance = createClient(config);
  instanceMap[key] = instance;
  return instance;
}
function createClient(config) {
  config = buildConfig(config);
  var instance;
  if (config.clazz) {
    var _config = config,
      Clazz = _config.clazz;
    instance = new Clazz(config);
  } else {
    instance = new Client(config);
  }
  return instance;
}

exports.AuthorizationHeaderError = AuthorizationHeaderError;
exports.Client = Client;
exports.buildConfig = buildConfig;
exports.createClient = createClient;
exports.hasOwnProperty = hasOwnProperty;
exports.isClientError = isClientError;
exports.parseAuthorizationHeader = parseAuthorizationHeader;
exports.setClient = setClient;
exports.setConfig = setConfig;
exports.stringifyAuthorizationHeader = stringifyAuthorizationHeader;
exports.useClient = useClient;
exports.useConfig = useConfig;
//# sourceMappingURL=index.cjs.js.map
