Comparing version 0.15.0 to 0.16.0
@@ -19,2 +19,4 @@ /** | ||
var constants = require('./constants'); | ||
var errors = require('./errors'); | ||
var meta = require('../package.json'); | ||
var utils = require('./utils'); | ||
@@ -40,16 +42,21 @@ | ||
if (!opts.baseUrl) { | ||
throw new Error('baseUrl required'); | ||
throw errors.Validation('baseUrl required'); | ||
} | ||
if (typeof opts.baseUrl !== 'string') { | ||
throw new Error('baseUrl must be a string: ' + opts.baseUrl); | ||
if (!(opts.baseUrl instanceof url.Url)) { | ||
if (typeof opts.baseUrl !== 'string') { | ||
throw errors.Validation('baseUrl must be a string: ' + opts.baseUrl); | ||
} | ||
opts.baseUrl = url.parse(opts.baseUrl); | ||
} | ||
opts.baseUrl = url.parse(opts.baseUrl); | ||
opts.baseUrl.path = opts.baseUrl.pathname; | ||
opts.baseUrl = utils.pick(opts.baseUrl, | ||
'auth', 'hostname', 'path', 'port', 'protocol'); | ||
if (opts.baseUrl.path === '/') { | ||
opts.baseUrl.path = ''; | ||
opts.baseUrl.pathname = ''; | ||
} else if (opts.baseUrl.path[opts.baseUrl.path.length - 1] === '/') { | ||
throw new Error('baseUrl must not end with a forward slash'); | ||
throw errors.Validation('baseUrl must not end with a forward slash'); | ||
} | ||
@@ -99,7 +106,7 @@ | ||
if (!eventName || typeof eventName !== 'string') { | ||
throw this._err('extension eventName required'); | ||
throw this._err(errors.Validation('extension eventName required')); | ||
} | ||
if (typeof callback !== 'function') { | ||
throw this._err('extension callback required'); | ||
throw this._err(errors.Validation('extension callback required')); | ||
} | ||
@@ -118,7 +125,7 @@ | ||
if (!plugin) { | ||
throw this._err('plugin required'); | ||
throw this._err(errors.Validation('plugin required')); | ||
} | ||
if (typeof plugin.register !== 'function') { | ||
throw this._err('plugin must have register function'); | ||
throw this._err(errors.Validation('plugin must have register function')); | ||
} | ||
@@ -129,11 +136,11 @@ | ||
if (!attributes) { | ||
throw this._err('plugin attributes required'); | ||
throw this._err(errors.Validation('plugin attributes required')); | ||
} | ||
if (!attributes.name) { | ||
throw this._err('plugin attributes name required'); | ||
throw this._err(errors.Validation('plugin attributes name required')); | ||
} | ||
if (!attributes.version) { | ||
throw this._err('plugin attributes version required'); | ||
throw this._err(errors.Validation('plugin attributes version required')); | ||
} | ||
@@ -158,3 +165,3 @@ | ||
if (!this._opts.encoders[mime]) { | ||
throw new Error('unknown encoder: ' + mime); | ||
throw errors.Codec('unknown encoder: ' + mime); | ||
} | ||
@@ -166,3 +173,3 @@ | ||
err.message = 'encode (' + mime + ') failed: ' + err.message; | ||
throw err; | ||
throw errors.Codec(err); | ||
} | ||
@@ -177,3 +184,3 @@ }; | ||
if (!this._opts.decoders[mime]) { | ||
throw new Error('unknown decoder: ' + mime); | ||
throw errors.Codec('unknown decoder: ' + mime); | ||
} | ||
@@ -185,3 +192,3 @@ | ||
err.message = 'decode (' + mime + ') failed: ' + err.message; | ||
throw err; | ||
throw errors.Codec(err); | ||
} | ||
@@ -234,3 +241,4 @@ }; | ||
} else { | ||
return self.emit('error', self._err('callback required', opts)); | ||
return self.emit('error', self._err( | ||
errors.Validation('callback required'), opts)); | ||
} | ||
@@ -251,3 +259,3 @@ | ||
if (ctx._retryable === false) { | ||
throw new Error('request is not retryable'); | ||
throw errors.Validation('request is not retryable'); | ||
} | ||
@@ -310,3 +318,3 @@ | ||
if (typeof path !== 'string') { | ||
return next(new Error('path required')); | ||
return next(errors.Validation('path required')); | ||
} | ||
@@ -320,3 +328,3 @@ | ||
if (!opts.params.hasOwnProperty(dst)) { | ||
throw new Error('missing param: ' + dst); | ||
throw errors.Validation('missing param: ' + dst); | ||
} | ||
@@ -366,3 +374,3 @@ | ||
if (!isBuffer && !isStream && !mime) { | ||
return next(new Error('type required')); | ||
return next(errors.Validation('type required')); | ||
} | ||
@@ -378,3 +386,3 @@ | ||
} else { | ||
return next(new Error('type is unknown: ' + mime)); | ||
return next(errors.Codec('type is unknown: ' + mime)); | ||
} | ||
@@ -413,3 +421,3 @@ } | ||
if (!(ctx.pipe instanceof stream.Writable)) { | ||
return next(new Error('pipe must be a writable stream')); | ||
return next(errors.Validation('pipe must be a writable stream')); | ||
} | ||
@@ -461,2 +469,6 @@ } | ||
if (request.getHeader('user-agent') === undefined) { | ||
request.setHeader('user-agent', 'papi/' + meta.version); | ||
} | ||
request.on('error', function(err) { | ||
@@ -487,3 +499,3 @@ self._log(['papi', 'request', 'error'].concat(opts.tags), err); | ||
self._log(['papi', 'request', 'error', 'timeout'].concat(opts.tags)); | ||
if (!err) err = new Error('request timed out (' + timeout + 'ms)'); | ||
if (!err) err = errors.Timeout('request timed out (' + timeout + 'ms)'); | ||
request.emit('error', err); | ||
@@ -544,3 +556,3 @@ }); | ||
if (Math.floor(res.statusCode / 100) !== 2) { | ||
var err = new Error(); | ||
var err = errors.Response(); | ||
@@ -547,0 +559,0 @@ if (res.body && mime === 'text/plain' && res.body.length < 80) { |
@@ -7,3 +7,6 @@ 'use strict'; | ||
var url = require('url'); | ||
var Client = require('./client').Client; | ||
var errors = require('./errors'); | ||
@@ -14,5 +17,5 @@ /** | ||
function request(opts, callback) { | ||
function request(opts) { | ||
if (typeof opts === 'string') { | ||
opts = { method: 'get', url: opts }; | ||
arguments[0] = opts = { method: 'get', url: opts }; | ||
} else { | ||
@@ -24,16 +27,27 @@ opts = opts || {}; | ||
if (!opts.url) { | ||
throw new Error('url required'); | ||
throw errors.Validation('url required'); | ||
} | ||
if (typeof opts.url !== 'string') { | ||
throw new Error('url must be a string'); | ||
throw errors.Validation('url must be a string'); | ||
} | ||
var client = new Client({ baseUrl: opts.url }); | ||
var baseUrl = url.parse(opts.url); | ||
opts.path = ''; | ||
opts.path = baseUrl.pathname.replace('%7B', '{').replace('%7D', '}'); | ||
baseUrl.pathname = ''; | ||
var client = new Client({ baseUrl: baseUrl }); | ||
delete opts.url; | ||
client._request(opts, callback); | ||
client._request.apply(client, arguments); | ||
} catch (err) { | ||
var callback = arguments[arguments.length - 1]; | ||
if (typeof callback !== 'function') { | ||
err.message = 'no callback: ' + err.message; | ||
throw err; | ||
} | ||
callback(err); | ||
@@ -48,5 +62,5 @@ } | ||
function method(name) { | ||
return function(opts, callback) { | ||
return function(opts) { | ||
if (typeof opts === 'string') { | ||
opts = { url: opts }; | ||
arguments[0] = opts = { url: opts }; | ||
} else { | ||
@@ -58,3 +72,3 @@ opts = opts || {}; | ||
request(opts, callback); | ||
request.apply(null, arguments); | ||
}; | ||
@@ -61,0 +75,0 @@ } |
{ | ||
"name": "papi", | ||
"version": "0.15.0", | ||
"version": "0.16.0", | ||
"description": "Build HTTP API clients", | ||
@@ -8,10 +8,10 @@ "main": "lib", | ||
"async": "^0.9.0", | ||
"debug": "^1.0.3", | ||
"istanbul": "^0.3.0", | ||
"jscs": "^1.5.9", | ||
"jshint": "^2.5.3", | ||
"lodash": "^2.4.1", | ||
"mocha": "^1.21.4", | ||
"nock": "^0.45.0", | ||
"request": "^2.40.0", | ||
"debug": "^2.0.0", | ||
"istanbul": "^0.3.2", | ||
"jscs": "^1.6.2", | ||
"jshint": "^2.5.5", | ||
"lodash": "^3.1.0", | ||
"mocha": "^2.1.0", | ||
"nock": "^0.59.1", | ||
"request": "^2.44.0", | ||
"should": "^4.0.4", | ||
@@ -21,4 +21,5 @@ "sinon": "^1.10.3" | ||
"scripts": { | ||
"cover": "./node_modules/.bin/istanbul cover ./node_modules/.bin/_mocha -- --recursive && open coverage/lcov-report/index.html", | ||
"test": "./node_modules/.bin/jshint lib test && ./node_modules/.bin/jscs lib test && ./node_modules/.bin/istanbul cover ./node_modules/.bin/_mocha -- --recursive --check-leaks" | ||
"cover": "istanbul cover _mocha -- --recursive && open coverage/lcov-report/index.html", | ||
"bench": "BENCHMARK=true mocha test/benchmark.js", | ||
"test": "jshint lib test && jscs lib test && istanbul cover _mocha -- --recursive --check-leaks && istanbul check-coverage --statements 98 --functions 100 --branches 97 --lines 99" | ||
}, | ||
@@ -25,0 +26,0 @@ "repository": { |
@@ -11,2 +11,6 @@ # Papi [![Build Status](https://travis-ci.org/silas/node-papi.png?branch=master)](https://travis-ci.org/silas/node-papi) | ||
* [Client](#client) | ||
* [Shortcuts](#shortcuts) | ||
<a name="client"/> | ||
### papi.Client([options]) | ||
@@ -16,2 +20,5 @@ | ||
Your client should inherit the prototype methods from this constructor and call | ||
it in your client's constructor. | ||
Options | ||
@@ -31,10 +38,17 @@ | ||
var papi = require('papi'); | ||
var util = require('util'); | ||
var client = new papi.Client({ | ||
baseUrl: 'https://api.github.com', | ||
headers: { 'user-agent': 'PapiGitHub/0.1.0' }, | ||
timeout: 5 * 1000, | ||
}); | ||
function GitHub(opts) { | ||
opts = opts || {}; | ||
opts.baseUrl = 'https://api.github.com'; | ||
opts.header = { accept: 'application/vnd.github.v3+json' }; | ||
opts.timeout = 15 * 1000; | ||
papi.Client.call(this, opts); | ||
} | ||
util.inherits(GitHub, papi.Client); | ||
``` | ||
<a name="client-request"/> | ||
### client.\_request(request, [callback...], callback) | ||
@@ -44,2 +58,5 @@ | ||
Your client should use this or the shortcut methods listed below to execute | ||
HTTP requests in your client methods. | ||
Arguments | ||
@@ -63,4 +80,4 @@ | ||
There are also `_get`, `_head`, `_post`, `_put`, `_delete`, `_patch`, and | ||
`_options` shortcuts with the same method signature as `_request`. | ||
There are also `_get`, `_head`, `_post`, `_put`, `_delete` (`_del`), `_patch`, | ||
and `_options` shortcuts with the same method signature as `_request`. | ||
@@ -70,17 +87,14 @@ Usage | ||
``` javascript | ||
var opts = { | ||
path: '/users/{username}/gists', | ||
params: { username: 'silas' }, | ||
}; | ||
GitHub.prototype.gists = function(username, callback) { | ||
var opts = { | ||
path: '/users/{username}/gists', | ||
params: { username: username }, | ||
}; | ||
client._get(opts, function(err, res) { | ||
if (err) { | ||
console.log('error', err.message); | ||
} | ||
this._get(opts, function(err, res) { | ||
if (err) return callback(err); | ||
if (res) { | ||
console.log('statusCode', res.statusCode); | ||
console.log('body', res.body); | ||
} | ||
}); | ||
callback(null, res.body); | ||
}); | ||
}; | ||
``` | ||
@@ -176,2 +190,32 @@ | ||
<a name="shortcuts"/> | ||
### papi.request(request, [callback...], callback) | ||
Shortcuts for making one-off requests. | ||
See [client request](#client-request) for full options list, with the exception | ||
that `path` is replaced with `url`. | ||
Request | ||
* url (String): request url (ex: `http://example.org/`) | ||
There are also `get`, `head`, `post`, `put`, `delete` (`del`), `patch`, and | ||
`options` shortcuts with the same method signature as `request`. | ||
Usage | ||
``` javascript | ||
var papi = require('papi'); | ||
papi.get('https://api.github.com/users/silas/gists', function(err, res) { | ||
if (err) throw err; | ||
res.body.forEach(function(gist) { | ||
console.log(gist.url); | ||
}); | ||
}); | ||
``` | ||
## Example | ||
@@ -178,0 +222,0 @@ |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
28311
11
743
306