Source: flyApi.js

const axios = require('axios')

class Fly {
  /**
   * Create a Fly API Client
   * @param {string} apiKey Fly.io access token
   * @param {string} [resourceType=apps]    Site type (`apps` or `sites`)
   */
  constructor (apiKey, resourceType = 'apps') {
    this.apiKey = apiKey
    this.resourceType = resourceType

    this.apiVersion = 'v1'
    this.apiUrl = `https://fly.io/api/${this.apiVersion}/${this.resourceType}`

    this.axios = axios.create({
      baseURL: this.apiUrl,
      headers: { Authorization: `Bearer ${this.apiKey}` }
    })
  }

  /**
   * Creates a new Error
   * @private
   * @param {Error} err Error object
   */
  createError (err) {
    const error = new Error(err)
    if (err.response) {
      if (err.response.status) {
        error.status = err.response.status
      }

      if (err.response.data && err.response.data.errors) {
        error.message = err.response.data.errors[0].title
      }
    }

    throw error
  }

  /**
   * List a site's hostnames
   * @param {string} name Name of the site
   *
   * @returns {Promise} Promise object represents the API response
   */
  async getHostnames (name) {
    try {
      const res = await this.axios.get(`/${name}/hostnames`)
      return res.data.data
    } catch (err) {
      return this.createError(err)
    }
  }

  /**
   * Create a new site hostname
   * @param {string} name Name of the site
   * @param {string} hostname The new hostname
   *
   * @returns {Promise} Promise object represents the API response
   */
  async postHostname (name, hostname) {
    try {
      const data = {
        data: {
          attributes: {
            hostname: hostname
          }
        }
      }
      const res = await this.axios.post(`/${name}/hostnames`, data)
      return res.data.data
    } catch (err) {
      return this.createError(err)
    }
  }

  /**
   * Get a hostname of a site
   * @param {string} name Name of the site
   * @param {string} hostname The requested hostname
   *
   * @returns {Promise} Promise object represents the API response
   */
  async getHostname (name, hostname) {
    try {
      const res = await this.axios.get(`/${name}/hostnames/${hostname}`)
      return res.data.data
    } catch (err) {
      return this.createError(err)
    }
  }

  /**
   * Delete a site hostname
   * @param {string} name Name of the site
   * @param {string} hostname Hostname to delete
   *
   * @returns {Promise} Promise object represents the API response
   */
  async deleteHostname (name, hostname) {
    try {
      const res = await this.axios.delete(`/${name}/hostnames/${hostname}`)
      return res.data.data
    } catch (err) {
      return this.createError(err)
    }
  }

  async getApps () {
    try {
      const res = await this.axios.get('/')
      return res.data.data
    } catch (err) {
      return this.createError(err)
    }
  }

  async getApp (name) {
    if (this.resourceType === 'sites') {
      throw new Error('Getting a single site is not supported')
    }
    try {
      const res = await this.axios.get(`/${name}`)
      return res.data.data
    } catch (err) {
      return this.createError(err)
    }
  }
}

module.exports = Fly