text: // @flow
  import _ from 'lodash';
  import invariant from 'invariant';
  import stores from 'stores';
  
  type Options = {
    baseUrl?: string,
  };
  
  class ApiClient {
    baseUrl: string;
    userAgent: string;
  
    constructor(options: Options = {}) {
      this.baseUrl = options.baseUrl || '/api';
      this.userAgent = 'OutlineFrontend';
    }
  
    fetch = (
      path: string,
      method: string,
      data: ?Object,
      options: Object = {}
    ) => {
      let body;
      let modifiedPath;
  
      if (method === 'GET') {
        if (data) {
          modifiedPath = `${path}?${data && this.constructQueryString(data)}`;
        } else {
          modifiedPath = path;
        }
      } else if (method === 'POST' || method === 'PUT') {
        body = data ? JSON.stringify(data) : undefined;
      }
  
      // Construct headers
      const headers = new Headers({
        Accept: 'application/json',
        'Content-Type': 'application/json',
      });
      if (stores.auth.authenticated) {
        invariant(stores.auth.token, 'JWT token not set properly');
        headers.set('Authorization', `Bearer ${stores.auth.token}`);
      }
  
      // Construct request
      // $FlowFixMe don't care much about this right now
      const request = fetch(this.baseUrl + (modifiedPath || path), {
        method,
        body,
        headers,
        redirect: 'follow',
        credentials: 'include',
      });
  
      // Handle request promises and return a new promise
      return new Promise((resolve, reject) => {
        request
          .then(response => {
            // Handle successful responses
            if (response.status >= 200 && response.status < 300) {
              return response;
            }
  
            // Handle 401, log out user
            if (response.status === 401) {
              stores.auth.logout();
              return;
            }
  
            // Handle failed responses
            const error = {};
            error.statusCode = response.status;
            error.response = response;
            throw error;
          })
          .then(response => {
            return response && response.json();
          })
          .then(json => {
            resolve(json);
          })
          .catch(error => {
            error.response.json().then(json => {
              error.error = json;
              reject(error);
            });
          });
      });
    };
  
    get = (path: string, data: ?Object, options?: Object) => {
      return this.fetch(path, 'GET', data, options);
    };
  
    post = (path: string, data: ?Object, options?: Object) => {
      return this.fetch(path, 'POST', data, options);
    };
  
    // Helpers
    constructQueryString = (data: Object) => {
      return _.map(data, (v, k) => {
        return `${encodeURIComponent(k)}=${encodeURIComponent(v)}`;
      }).join('&');
    };
  }
  
  export default ApiClient;
  
  // In case you don't want to always initiate, just import with `import { client } ...`
  export const client = new ApiClient();
  