Source: client/index.js

const axios = require('axios');
const debug = require('debug')('reflect-node');
const Errors = require('../errors');

const Reporting = require('./reporting');
const Projects = require('./projects');

const DEFAULT_HOST = 'https://api.reflect.io';

const nodeVersion = process.version;
const pkgVersion = require('../../package.json').version;

const methods = {
  GET: 'get',
  PUT: 'put',
  POST: 'post',
  DELETE: 'delete',
};

const logDebug = (method, url, status, headers) => debug(
  'method=%s url=%s: status=%s reflect-request-identifier=%s',
  method,
  url,
  status,
  headers['reflect-request-identifier']
);

/**
 * Client provides a simple interface for using the Reflect API from Node.
 *
 * Provides a way to authenticate, make requests, and robustly handle errors.
 *
 * @constructor
 * @param {string} token The API token to authenticate with. You can find this at https://app.reflect.io.
 *                       Can be either read-only or read-write, depending on the usage.
 * @param {string} [host=https://api.reflect.io] Host to use when querying
 */
function Client(token, host) {
  this._token = token;
  this._host = host || DEFAULT_HOST;

  this.reporting = new Reporting(this);
  this.projects = new Projects(this);
}

/**
 * Given a method, path, and some options, makes a request to the Reflect API using the configured
 * host.
 *
 * @param {string} method The HTTP method to use
 * @param {string} path The path to query
 * @param {Object} [opts={}] Options
 * @param {Object} opts.params Params to send in the request
 * @return {Promise} Promise that represents the HTTP request
 */
Client.prototype.request = function request(method, path, opts = {}) {
  const url = `${this._host}/${path}`;
  const headers = {
    'User-Agent': `reflect-node v${pkgVersion} (node ${nodeVersion})`, // TODO: Add version
  };

  const config = Object.assign(opts, {
    url,
    method,
    headers,
    auth: { password: this._token },
  });

  return axios(config)
    .then((res) => {
      logDebug(
        method,
        url,
        res.status,
        res.headers
      );

      return res.data;
    })
    .catch((error) => {
      if (error.response) {
        logDebug(
          method,
          url,
          error.response.status,
          error.response.headers
        );
      }

      throw Errors.fromResponse(error);
    });
};

/**
 * Makes a GET request to the Reflect API.
 *
 * @param  {string} path The path to query
 * @param {Object} opts Options to make the request with
 * @return {Promise} Promise that represents the HTTP request
 */
Client.prototype.get = function get(path, opts) {
  return this.request(methods.GET, path, opts);
};

/**
 * Makes a POST request to the Reflect API.
 *
 * @param  {string} path The path to query
 * @param {Object} opts Options to make the request with
 * @return {Promise} Promise that represents the HTTP request
 */
Client.prototype.post = function post(path, opts) {
  return this.request(methods.POST, path, opts);
};

/**
 * Makes a PUT request to the Reflect API.
 *
 * @param  {string} path The path to query
 * @param {Object} opts Options to make the request with
 * @return {Promise} Promise that represents the HTTP request
 */
Client.prototype.put = function put(path, opts) {
  return this.request(methods.PUT, path, opts);
};

/**
 * Makes a DELETE request to the Reflect API.
 *
 * @param  {string} path The path to query
 * @param {Object} opts Options to make the request with
 * @return {Promise} Promise that represents the HTTP request
 */
Client.prototype.delete = function (path, opts) { // eslint-ignore-line func-names
  return this.request(methods.DELETE, path, opts);
};

exports.Client = Client;