Show:
                        var fs = require('fs');
                        var util = require('util');
                        
                        var winston = require('winston');
                        var lodash = require('lodash');
                        var request = require('request');
                        var Promise = require('promise');
                        
                        var DSN = require('./dsn').DSN;
                        var Projects = require('./projects');
                        var Organizations = require('./organizations');
                        var Releases = require('./releases');
                        var Teams = require('./teams');
                        var Events = require('./events');
                        
                        /**
                         * Client for the Sentry API.
                         *
                         * @example
                         *   var Client = require('sentry-api').Client;
                         *
                         *   var sentry = new Client('https://abc123:@app.getsentry.com/1234', {
                         *     logging: true
                         *   });
                         *
                         *   sentry.projects.get('my-organization-slug', 'my-project-slug').then(function(error, project) {
                         *     console.log(project.name);
                         *   });
                         *
                         * @class Client
                         * @constructor
                         * @param {String}  dsn    Sentry DSN.
                         * @param {Options} config Config
                         * @param {Number}  config.version Sentry API version number.
                         */
                        var Client = function(dsn, config) {
                          this.dsn = new DSN(dsn);
                        
                          this.config = lodash.defaults(config || {}, {
                            version: 0,
                            logging: false,
                          });
                        
                          this.logger = new(winston.Logger)({
                            transports: this.config.logging ? [
                              new (winston.transports.Console)({
                                colorize: true,
                                label: 'SentryAPI'
                              })
                            ] : []
                          });
                        
                          this.projects = new Projects(this);
                          this.organizations = new Organizations(this);
                          this.releases = new Releases(this);
                          this.teams = new Teams(this);
                          this.events = new Events(this);
                        };
                        
                        /**
                         * Contains methods related to Sentry Projects.
                         *
                         * @property {Projects} projects
                         */
                        Client.prototype.projects = null;
                        
                        /**
                         * Contains methods related to Sentry Organizations.
                         *
                         * @property {Organizations} organizations
                         */
                        Client.prototype.organizations = null;
                        
                        /**
                         * Contains methods related to Sentry Releases.
                         *
                         * @property {Releases} releases
                         */
                        Client.prototype.releases = null;
                        
                        /**
                         * Contains methods related to Sentry Teams.
                         *
                         * @property {Teams} teams
                         */
                        Client.prototype.teams = null;
                        
                        /**
                         * Contains methods related to Sentry Events.
                         *
                         * @property {Events} events
                         */
                        Client.prototype.events = null;
                        
                        /**
                         * Make a request to the Sentry API.
                         *
                         * @method request
                         * @param  {String}   path     The request path.
                         * @param  {Object}   options  Request options. These are the same as the request module's options.
                         * @param  {Function} callback Function to execute when the request completes.
                         * @return {Promise}
                         */
                        Client.prototype.request = function(path, options, callback) {
                          var uri = util.format('%s/api/%d/%s', this.dsn.uri, this.config.version, path);
                        
                          this.logger.info(options.method, uri);
                        
                          if (lodash.isUndefined(callback)) {
                            callback = function() {};
                          }
                        
                          return new Promise(function (resolve, reject) {
                            request(lodash.extend({
                              uri: uri,
                              json: true,
                              auth: {
                                user: this.dsn.publicKey,
                              },
                            }, options), function(error, response, body) {
                              if (error) {
                                this.logger.error(error);
                                callback(error, null);
                                reject(error);
                              }
                              else if (response.statusCode >= 200 && response.statusCode < 300) {
                                this.logger.info(response.statusCode, response.statusMessage);
                                callback(null, body);
                                resolve(body);
                              }
                              else {
                                this.logger.warn(response.statusCode, response.statusMessage);
                                if (body && body.detail) {
                                  error = new Error(body.detail);
                                }
                                else if (response.statusMessage) {
                                  error = new Error(util.format('%d: %s', response.statusCode, response.statusMessage));
                                }
                                else {
                                  error = new Error(response.statusCode);
                                }
                                callback(error);
                                reject(error)
                              }
                            }.bind(this));
                          }.bind(this));
                        };
                        
                        /**
                         * Convenience method for making GET requests.
                         *
                         * @method get
                         * @param  {String}   path     Request path.
                         * @param  {Object}   params   Request query string parameters.
                         * @param  {Function} callback Request callback.
                         * @return {Promise}
                         */
                        Client.prototype.get = function(path, params, callback) {
                          return this.request(path, {method: 'GET', qs: params}, callback);
                        };
                        
                        /**
                         * Convenience method for making POST requests.
                         *
                         * @method post
                         * @param  {String}   path     Request path.
                         * @param  {Object}   body     Request body.
                         * @param  {Function} callback Request callback.
                         * @return {Promise}
                         */
                        Client.prototype.post = function(path, body, callback) {
                          return this.request(path, {method: 'POST', body: body}, callback);
                        };
                        
                        /**
                         * Convenience method for making DELETE requests.
                         *
                         * @method delete
                         * @param  {String}   path     Request path.
                         * @param  {Function} callback Request callback.
                         * @return {Promise}
                         */
                        Client.prototype.delete = function(path, callback) {
                          return this.request(path, {method: 'DELETE'}, callback);
                        };
                        
                        /**
                         * Convenience method for making PUT requests.
                         *
                         * @method put
                         * @param  {String}   path     Request path.
                         * @param  {Object}   body     Request body.
                         * @param  {Function} callback Request callback.
                         * @return {Promise}
                         */
                        Client.prototype.put = function(path, body, callback) {
                          return this.request(path, {method: 'PUT', body: body}, callback);
                        };
                        
                        exports.Client = Client;