diff --git a/index.js b/index.js index 0776514..966a5e5 100644 --- a/index.js +++ b/index.js @@ -2,6 +2,7 @@ function defaults (target, obj) { for (var prop in obj) target[prop] = target[prop] || obj[prop] + return target } function getQuery (queryParams) { @@ -11,10 +12,30 @@ return '?' + arr.join('&') } + function identity(arg) { return arg } + + var responseHandlers = { + 'json': function(response) { return response.json() }, + 'text': function(response) { return response.text() }, + 'response': true + } + + var encodeHandlers = { + 'json': JSON.stringify, + 'noop': identity, + true: identity, + false: identity, + } + function _fetch (method, url, opts, data, queryParams) { + // Use a shallow copy of opts parameter and opts.header subfield + opts = defaults({}, opts) opts.method = method - opts.headers = opts.headers || {} - opts.responseAs = (opts.responseAs && ['json', 'text', 'response'].indexOf(opts.responseAs) >= 0) ? opts.responseAs : 'json' + opts.headers = defaults({}, opts.headers || {}) + + if (opts.responseAs !== true && typeof opts.responseAs !== 'function') { + opts.responseAs = responseHandlers[opts.responseAs] || responseHandlers.json + } defaults(opts.headers, { 'Accept': 'application/json', @@ -26,23 +47,28 @@ } if (data) { - opts.body = JSON.stringify(data); - } else { - delete opts.body; + if (typeof opts.encodeAs !== 'function') { + opts.encodeAs = encodeHandlers[opts.encodeAs] || encodeHandlers.json + } + opts.body = opts.encodeAs(data) } return fetchival.fetch(url, opts) .then(function (response) { if (response.status >= 200 && response.status < 300) { - if(opts.responseAs=="response") + if(opts.responseAs===true) return response if (response.status == 204) return null; - return response[opts.responseAs](); + return opts.responseAs(response); + } + if(typeof opts.errorAs !== 'function') { + var err = new Error(response.statusText) + err.response = response + throw err + } else { + throw opts.errorAs(response) } - var err = new Error(response.statusText) - err.response = response - throw err }) } @@ -61,20 +87,20 @@ return _fetch('GET', url, opts, null, queryParams) } - _.post = function (data) { - return _fetch('POST', url, opts, data) + _.post = function (data, queryParams) { + return _fetch('POST', url, opts, data, queryParams) } - _.put = function (data) { - return _fetch('PUT', url, opts, data) + _.put = function (data, queryParams) { + return _fetch('PUT', url, opts, data, queryParams) } - _.patch = function (data) { - return _fetch('PATCH', url, opts, data) + _.patch = function (data, queryParams) { + return _fetch('PATCH', url, opts, data, queryParams) } - _.delete = function () { - return _fetch('DELETE', url, opts) + _.delete = function (queryParams) { + return _fetch('DELETE', url, opts, null, queryParams) } return _ @@ -83,6 +109,8 @@ // Expose fetch so that other polyfills can be used // Bind fetch to window to avoid TypeError: Illegal invocation fetchival.fetch = typeof fetch !== 'undefined' ? fetch.bind(window) : null + fetchival.responseHandlers = responseHandlers + fetchival.encodeHandlers = encodeHandlers // Support CommonJS, AMD & browser if (typeof exports === 'object') diff --git a/test/tests.js b/test/tests.js index dbbb6e7..482a8ac 100644 --- a/test/tests.js +++ b/test/tests.js @@ -17,6 +17,30 @@ var requestText = fetchival('http://jsonplaceholder.typicode.com', { responseAs: 'text' }) +fetchival.responseHandlers['registered-example'] = function(response) { + return response.json() + .then(function (json) { + return {kind: 'registered-example', json: json, response: response} + }) +} + +var requestRegisteredExample = fetchival('http://jsonplaceholder.typicode.com', { + mode: 'cors', + headers: { 'X-TEST': 'test' }, + responseAs: 'registered-example' +}) + +var requestCustomExample = fetchival('http://jsonplaceholder.typicode.com', { + mode: 'cors', + headers: { 'X-TEST': 'test' }, + responseAs: function(response) { + return response.json() + .then(function (json) { + return {kind: 'custom', json: json, response: response} + }) + } +}) + describe('fetchival', function () { this.timeout(5000) this.slow(5000) @@ -135,4 +159,37 @@ describe('fetchival', function () { }) }) }) + + describe('requestCustomExample(posts/1/comments)', function () { + var posts = requestCustomExample('posts') + var comments = posts(1 + '/comments') + + it('should #get()', function (done) { + comments + .get() + .then(function (extendedReponseObj) { + assert.equal('custom', extendedReponseObj.kind) + assert(extendedReponseObj.response.ok) + assert(extendedReponseObj.json.length) + done() + }) + }) + }) + + describe('requestRegisteredExample(posts/1/comments)', function () { + var posts = requestRegisteredExample('posts') + var comments = posts(1 + '/comments') + + it('should #get()', function (done) { + comments + .get() + .then(function (extendedReponseObj) { + assert.equal('registered-example', extendedReponseObj.kind) + assert(extendedReponseObj.response.ok) + assert(extendedReponseObj.json.length) + done() + }) + }) + }) + })