Skip to content

Commit

Permalink
1.0.0
Browse files Browse the repository at this point in the history
  • Loading branch information
bartve committed Oct 27, 2016
1 parent 541f6f0 commit 2a8853c
Show file tree
Hide file tree
Showing 11 changed files with 212 additions and 227 deletions.
5 changes: 5 additions & 0 deletions HISTORY.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
1.0.0 / 2016-10-27
==================
* When no callback is provided, all API functions now return a native JS `Promise`
* Removed the non get/set method calls like `database.release(...)` deprecated in release `0.8.0`

0.9.1 / 2016-10-24
==================
* Upgraded OAuth library to `oauth-1.0a` v2.0.0
Expand Down
18 changes: 17 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@

* Covers all API endpoints
* Supports [pagination](http://www.discogs.com/developers/#page:home,header:home-pagination), [rate limiting](http://www.discogs.com/developers/#page:home,header:home-rate-limiting), etc.
* All database, marketplace and user functions implement a standard `function(err, data, rateLimit)` format for the callback
* All database, marketplace and user functions implement a standard `function(err, data, rateLimit)` format for the callback or return a
native JS [Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) when no callback is provided
* Easy access to protected endpoints with `Discogs Auth`
* Includes OAuth 1.0a tools. Just plug in your consumer key and secret and do the OAuth dance
* API functions grouped in their own namespace for easy access and isolation
Expand Down Expand Up @@ -67,6 +68,20 @@ col.getReleases('USER_NAME', 0, {page: 2, per_page: 75}, function(err, data){
});
```

### Promises
When no callback is provided, the API functions return a native JS [Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) for easy chaining.

```javascript
var db = new Discogs().database();
db.getRelease(1)
.then(function(release){
return db.getArtist(release.artists[0].id);
})
.then(function(artist){
console.log(artist.name);
});
```

### Output format
User, artist and label profiles can be formatted in different ways: `plaintext`, `html` and `discogs`. `disconnect` defaults to `discogs`, but the output format can be set for each client instance.
```javascript
Expand Down Expand Up @@ -111,6 +126,7 @@ app.get('/authorize', function(req, res){
);
});
```

#### 2. Authorize
After redirection to the Discogs authorize URL in step 1, authorize the application.

Expand Down
135 changes: 74 additions & 61 deletions lib/client.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,7 @@ var https = require('https'),
url = require('url'),
pkg = require('../package.json'),
error = require('./error.js'),
util = require('./util.js'),
deprecate = require('depd')('disconnect');
util = require('./util.js');

module.exports = DiscogsClient;

Expand Down Expand Up @@ -38,7 +37,7 @@ var queue = require('./queue.js')({
* Object constructor
* @param {string} [userAgent] - The name of the user agent to use to make API calls
* @param {object} [auth] - Optional authorization data object
* @returns {DiscogsClient}
* @return {DiscogsClient}
*/

function DiscogsClient(userAgent, auth){
Expand Down Expand Up @@ -73,7 +72,7 @@ function DiscogsClient(userAgent, auth){
/**
* Override the default configuration
* @param {object} customConfig - Custom configuration object for Browserify/CORS/Proxy use cases
* @returns {DiscogsClient}
* @return {DiscogsClient}
*/
DiscogsClient.prototype.setConfig = function(customConfig){
util.merge(this.config, customConfig);
Expand All @@ -87,7 +86,7 @@ DiscogsClient.prototype.setConfig = function(customConfig){
/**
* Return whether the client is authenticated for the optionally given access level
* @param {number} [level] - Optional authentication level
* @returns {boolean}
* @return {boolean}
*/

DiscogsClient.prototype.authenticated = function(level){
Expand All @@ -98,33 +97,35 @@ DiscogsClient.prototype.authenticated = function(level){
/**
* Test authentication by getting the identity resource for the authenticated user
* @param {function} callback - Callback function receiving the data
* @return {DiscogsClient|Promise}
*/

DiscogsClient.prototype.getIdentity = function(callback){
this.get({url: '/oauth/identity', authLevel: 2}, callback);
return this.get({url: '/oauth/identity', authLevel: 2}, callback);
};

DiscogsClient.prototype.identity = deprecate.function(DiscogsClient.prototype.getIdentity,
'client.identity: Use client.getIdentity instead');

/**
* Get info about the Discogs API and this client
* @param {function} callback - Callback function receiving the data
*/

DiscogsClient.prototype.about = function(callback){
var self = this;
this.get('', function(err, data){
if(data){
data.disconnect = {
version: pkg.version,
userAgent: self.config.userAgent,
authMethod: (self.auth ? self.auth.method : 'none'),
authLevel: (self.auth ? self.auth.level : 0)
};
}
callback(err, data);
});
var clientInfo = {
version: pkg.version,
userAgent: this.config.userAgent,
authMethod: (this.auth ? this.auth.method : 'none'),
authLevel: (this.auth ? this.auth.level : 0)
};
if(typeof callback === 'function'){
return this.get('', function(err, data){
data && (data.disconnect = clientInfo);
callback(err, data);
});
}
return this.get('').then(function(data){
data && (data.disconnect = clientInfo);
return data;
});
};

/**
Expand All @@ -135,8 +136,8 @@ DiscogsClient.prototype.about = function(callback){
* method: '', // Defaults to GET
* data: {} // POST/PUT data as an object
* }
* @param {function} [callback] - Callback function receiving the data
* @returns {DiscogsClient}
* @param {function} callback - Callback function receiving the data
* @return {DiscogsClient}
*/

DiscogsClient.prototype._rawRequest = function(options, callback){
Expand Down Expand Up @@ -180,7 +181,7 @@ DiscogsClient.prototype._rawRequest = function(options, callback){
}

// Set the HTTPS request options
var options = {
var requestOptions = {
host: urlParts.host||this.config.host,
port: urlParts.port||this.config.port,
path: urlParts.path,
Expand All @@ -189,19 +190,17 @@ DiscogsClient.prototype._rawRequest = function(options, callback){
};

// Build the HTTPS request
var req = https.request(options, function(res){
var req = https.request(requestOptions, function(res){
var data = '', rateLimit = null, add = function(chunk){ data += chunk.toString(); };

// Pass the data to the callback and pass an error on unsuccessful HTTP status
var passData = function(){
if(typeof callback === 'function'){
var err = null, status = parseInt(res.statusCode, 10);
if(status > 399){ // Unsuccessful HTTP status? Then pass an error to the callback
var match = data.match(/^\{"message": "(.+)"\}/i);
err = new error.DiscogsError(status, ((match&&match[1]) ? match[1] : null));
}
callback(err, data, rateLimit);
var err = null, status = parseInt(res.statusCode, 10);
if(status > 399){ // Unsuccessful HTTP status? Then pass an error to the callback
var match = data.match(/^\{"message": "(.+)"\}/i);
err = new error.DiscogsError(status, ((match&&match[1]) ? match[1] : null));
}
callback(err, data, rateLimit);
};

// Find and add rate limiting when present
Expand Down Expand Up @@ -230,7 +229,7 @@ DiscogsClient.prototype._rawRequest = function(options, callback){
res.on('data', add).on('end', passData);
}
}).on('error', function(err){
if(typeof callback === 'function'){ callback(err); }
callback(err);
});

// When present, write the data to the request
Expand All @@ -249,19 +248,38 @@ DiscogsClient.prototype._rawRequest = function(options, callback){
* data: {} // POST/PUT data as an object
* }
* @param {function} [callback] - Callback function receiving the data
* @returns {DiscogsClient}
* @return {DiscogsClient|Promise}
*/

DiscogsClient.prototype._request = function(options, callback){
var self = this, hasCb = (typeof callback === 'function'),
var client = this,
doRequest = function(){
self._rawRequest(options, function(err, data, rateLimit){
client._rawRequest(options, function(err, data, rateLimit){
if(data && options.json && (data.indexOf('<!') !== 0)){
data = JSON.parse(data);
}
if(hasCb){ callback(err, data, rateLimit); }
callback(err, data, rateLimit);
});
},
prepareRequest = function(){
// Check whether authentication is required
if(!options.authLevel || client.authenticated(options.authLevel)){
if(options.queue){ // Add API request to the execution queue
queue.add(function(err){
if(!err){
doRequest(callback);
}else{ // Can't add to the queue because it's full
callback(err);
}
});
}else{ // Don't queue, just do the request
doRequest(callback);
}
}else{
callback(new error.AuthError());
}
};

// By default, queue requests
if(!options.hasOwnProperty('queue')){
options.queue = true;
Expand All @@ -270,30 +288,25 @@ DiscogsClient.prototype._request = function(options, callback){
if(!options.hasOwnProperty('json')){
options.json = true;
}
// Check whether authentication is required
if(!options.authLevel || this.authenticated(options.authLevel)){
if(options.queue){ // Add API request to the execution queue
queue.add(function(err){
if(!err){
doRequest();
}else{ // Can't add to the queue because it's full
if(hasCb){ callback(err); }
}
});
}else{ // Don't queue, just do the request
doRequest();
}
}else{
if(hasCb){ callback(new error.AuthError()); }

if(typeof callback === 'function'){
prepareRequest();
return this;
}
return this;
// No callback provided? Return a Promise
return new Promise(function(resolve, reject){
callback = function(err, data){
(err && reject(err)) || resolve(data);
};
prepareRequest();
});
};

/**
* Perform a GET request against the Discogs API
* @param {(object|string)} options - Request options object or an url
* @param {function} [callback] - Callback function receiving the data
* @returns {DiscogsClient}
* @return {DiscogsClient|Promise}
*/

DiscogsClient.prototype.get = function(options, callback){
Expand All @@ -306,7 +319,7 @@ DiscogsClient.prototype.get = function(options, callback){
* @param {(object|string)} options - Request options object or an url
* @param {object} data - POST data
* @param {function} [callback] - Callback function receiving the data
* @returns {DiscogsClient}
* @return {DiscogsClient|Promise}
*/

DiscogsClient.prototype.post = function(options, data, callback){
Expand All @@ -319,7 +332,7 @@ DiscogsClient.prototype.post = function(options, data, callback){
* @param {(object|string)} options - Request options object or an url
* @param {object} data - PUT data
* @param {function} [callback] - Callback function receiving the data
* @returns {DiscogsClient}
* @return {DiscogsClient|Promise}
*/

DiscogsClient.prototype.put = function(options, data, callback){
Expand All @@ -331,7 +344,7 @@ DiscogsClient.prototype.put = function(options, data, callback){
* Perform a DELETE request against the Discogs API
* @param {(object|string)} options - Request options object or an url
* @param {function} [callback] - Callback function receiving the data
* @returns {DiscogsClient}
* @return {DiscogsClient|Promise}
*/

DiscogsClient.prototype.delete = function(options, callback){
Expand All @@ -341,7 +354,7 @@ DiscogsClient.prototype.delete = function(options, callback){

/**
* Get an instance of the Discogs OAuth class
* @returns {DiscogsOAuth}
* @return {DiscogsOAuth}
*/

DiscogsClient.prototype.oauth = function(){
Expand All @@ -351,7 +364,7 @@ DiscogsClient.prototype.oauth = function(){

/**
* Expose the database functions and pass the current instance
* @returns {object}
* @return {object}
*/

DiscogsClient.prototype.database = function(){
Expand All @@ -360,7 +373,7 @@ DiscogsClient.prototype.database = function(){

/**
* Expose the marketplace functions and pass the current instance
* @returns {object}
* @return {object}
*/

DiscogsClient.prototype.marketplace = function(){
Expand All @@ -369,7 +382,7 @@ DiscogsClient.prototype.marketplace = function(){

/**
* Expose the user functions and pass the current instance
* @returns {object}
* @return {object}
*/

DiscogsClient.prototype.user = function(){
Expand Down
Loading

0 comments on commit 2a8853c

Please sign in to comment.