Comparing version 2.2.0 to 2.3.0
@@ -0,1 +1,5 @@ | ||
## 2.3.0 (2020-02-14) | ||
- Change emitted error format—errors now have `headers`, `status`, `body`, and `cause` keys. | ||
- Always emit errors when `maxRetries` is exhausted during streaming. | ||
## 2.2.0 (2020-01-29) | ||
@@ -2,0 +6,0 @@ - Add `maxRetries` and `retryInterval` configuration options. |
@@ -20,6 +20,4 @@ // Initialize with your Best Buy developer API key - if it is present as a | ||
console.log('Here is what an error looks like:'); | ||
console.log('HTTP Status Code: ' + err.statusCode); | ||
console.log(err.message); | ||
console.log('There are %d examples of how to do it right', | ||
err.error.error.examples.length); | ||
console.log('HTTP Status Code: ' + err.status); | ||
console.log('Response body: ' + JSON.stringify(err.body)); | ||
console.log(''); | ||
@@ -26,0 +24,0 @@ }); |
@@ -28,3 +28,3 @@ module.exports = apiServiceFactory; | ||
if (attempts > opts.maxRetries) { | ||
return finishWithError(error, callback); | ||
return finishWithError(error, request.params.format, callback); | ||
} | ||
@@ -40,12 +40,53 @@ | ||
return finishWithError(error, callback); | ||
return finishWithError(error, request.params.format, callback); | ||
}); | ||
} | ||
function finishWithError (error, callback) { | ||
if (callback) callback(error.response); | ||
if (error.response) return Promise.reject(error.response); | ||
return Promise.reject(error); | ||
function finishWithError (error, requestFormat, callback) { | ||
const wrappingError = new Error('Exceeded max retries'); | ||
const response = error.response; | ||
if (response) { | ||
wrappingError.headers = response.headers; | ||
wrappingError.status = response.status; | ||
if (response.data.constructor.name === 'IncomingMessage') { | ||
return getBodyFromStream(response.data) | ||
.then(body => { | ||
wrappingError.body = requestFormat === 'json' ? JSON.parse(body) : body; | ||
return wrappingError; | ||
}) | ||
.catch(error => { | ||
wrappingError.errorHandlingError = error; | ||
return wrappingError; | ||
}) | ||
.then(wrappingError => { | ||
if (callback) callback(wrappingError); | ||
throw wrappingError; | ||
}); | ||
} else { | ||
wrappingError.body = response.data; | ||
} | ||
} | ||
if (callback) { | ||
callback(wrappingError); | ||
} else { | ||
return Promise.reject(wrappingError); | ||
} | ||
} | ||
function getBodyFromStream (s) { | ||
return new Promise((resolve, reject) => { | ||
let body = ''; | ||
s.on('readable', () => { | ||
const read = s.read(); | ||
if (read) body += read; | ||
}); | ||
s.on('error', error => { | ||
reject(error); | ||
}); | ||
s.on('end', () => { | ||
resolve(body); | ||
}); | ||
}); | ||
} | ||
function waitABit (ms) { | ||
@@ -52,0 +93,0 @@ return new Promise(resolve => { |
@@ -74,11 +74,4 @@ module.exports = apiStreamJsonServiceFactory; | ||
.catch(error => { | ||
var errorStream = JSONStream.parse('*.message'); | ||
errorStream.on('data', msg => { | ||
stream.emit('error', new Error(msg)); | ||
}); | ||
pump(error.data, errorStream, (err) => { | ||
if (err) console.error(err); | ||
stream.end(); | ||
}); | ||
stream.emit('error', error); | ||
stream.end(); | ||
}); | ||
@@ -85,0 +78,0 @@ } |
@@ -82,11 +82,4 @@ module.exports = apiStreamXmlServiceFactory; | ||
.catch(error => { | ||
var errorStream = xmlNodes('error'); | ||
errorStream.on('data', msg => { | ||
stream.emit('error', new Error(msg)); | ||
}); | ||
pump(error.data, errorStream, (err) => { | ||
if (err) console.error(err); | ||
stream.end(); | ||
}); | ||
stream.emit('error', error); | ||
stream.end(); | ||
}); | ||
@@ -93,0 +86,0 @@ } |
@@ -11,4 +11,4 @@ module.exports = availabilityEndpoint; | ||
} | ||
if (typeof callback === 'undefined') callback = function noop () {}; | ||
if (typeof callback !== 'function') { | ||
if (typeof callback !== 'function' && typeof callback !== 'undefined') { | ||
var argsErr = new Error('Unrecognized parameter length when calling "availability" method'); | ||
@@ -22,3 +22,5 @@ return Promise.reject(argsErr); | ||
} catch (err) { | ||
callback(err); | ||
if (callback) { | ||
callback(err); | ||
} | ||
return Promise.reject(err); | ||
@@ -25,0 +27,0 @@ } |
@@ -11,3 +11,2 @@ module.exports = categoriesEndpoint; | ||
} | ||
if (typeof callback === 'undefined') callback = function noop () {}; | ||
@@ -14,0 +13,0 @@ return opts.apiService(prepareRequest(search, params), callback); |
@@ -11,3 +11,2 @@ module.exports = openBoxEndpoint; | ||
} | ||
if (typeof callback === 'undefined') callback = function noop () {}; | ||
@@ -14,0 +13,0 @@ return opts.apiService(prepareRequest(search, params), callback); |
@@ -12,4 +12,2 @@ module.exports = productsEndpoint; | ||
if (typeof callback === 'undefined') callback = function noop () {}; | ||
if (typeof params === 'function') { | ||
@@ -16,0 +14,0 @@ var queryObjFuncErr = new Error('Unhandled parameter type'); |
@@ -7,7 +7,7 @@ module.exports = realTimeAvailabilityEndpoint; | ||
function realTimeAvailability (sku, params, callback) { | ||
if (typeof callback === 'undefined') callback = function noop () {}; | ||
if (!(params.storeId || params.postalCode)) { | ||
var argsErr = new Error('Must provide either storeId or postalCode'); | ||
callback(argsErr); | ||
if (callback) { | ||
callback(argsErr); | ||
} | ||
return Promise.reject(argsErr); | ||
@@ -20,3 +20,5 @@ } | ||
} catch (err) { | ||
callback(err); | ||
if (callback) { | ||
callback(err); | ||
} | ||
return Promise.reject(err); | ||
@@ -23,0 +25,0 @@ } |
@@ -9,3 +9,2 @@ module.exports = recommendationsEndpoint; | ||
} | ||
if (typeof callback === 'undefined') callback = function noop () {}; | ||
@@ -17,3 +16,5 @@ var url; | ||
var criteriaErr = new Error('Recommendations endpoint requires 2nd parameter to be a SKU for the "' + path + '" method'); | ||
callback(criteriaErr); | ||
if (callback) { | ||
callback(criteriaErr); | ||
} | ||
return Promise.reject(criteriaErr); | ||
@@ -25,3 +26,5 @@ } | ||
var criteriaFuncErr = new Error('Unhandled parameter type'); | ||
callback(criteriaFuncErr); | ||
if (callback) { | ||
callback(criteriaFuncErr); | ||
} | ||
return Promise.reject(criteriaFuncErr); | ||
@@ -32,3 +35,5 @@ } | ||
var pathErr = new Error(`Unrecognized path "${path}"`); | ||
callback(pathErr); | ||
if (callback) { | ||
callback(pathErr); | ||
} | ||
return Promise.reject(pathErr); | ||
@@ -35,0 +40,0 @@ } |
@@ -12,4 +12,2 @@ module.exports = storesEndpoint; | ||
if (typeof callback === 'undefined') callback = function noop () {}; | ||
return opts.apiService(prepareRequest(search, params), callback); | ||
@@ -16,0 +14,0 @@ } |
@@ -7,7 +7,6 @@ module.exports = versionEndpoint; | ||
return function version (callback) { | ||
if (typeof callback === 'undefined') callback = function noop () {}; | ||
var url = `${opts.url}/version.txt`; | ||
const jsonifiedCallback = callback ? jsonify(callback) : undefined; | ||
return opts.apiService({url}, jsonify(callback)) | ||
return opts.apiService({url}, jsonifiedCallback) | ||
.then(version => { | ||
@@ -14,0 +13,0 @@ return createVersionObject(version); |
@@ -5,4 +5,2 @@ module.exports = warrantiesEndpoint; | ||
return function warranties (sku, callback) { | ||
if (typeof callback === 'undefined') callback = function noop () {}; | ||
var url = `${opts.url}/v1/products/${sku}/warranties.json`; | ||
@@ -9,0 +7,0 @@ |
{ | ||
"name": "bestbuy", | ||
"version": "2.2.0", | ||
"version": "2.3.0", | ||
"description": "High level node.js client for the Best Buy API.", | ||
@@ -5,0 +5,0 @@ "main": "index.js", |
@@ -70,2 +70,3 @@ # Best Buy API | ||
- a `data` event will be emitted for each item in the result (one per product/store/etc). | ||
- an `error` event will be emitted once `maxRetries` is exceeded. | ||
@@ -103,3 +104,8 @@ ### availability | ||
}); | ||
stream.on('error', function (error) { | ||
console.error(`Error status: ${error.status}`); | ||
console.error(`Error headers: ${error.headers}`); | ||
console.error(`Error body: ${error.body}`); | ||
console.error(`Error cause: ${error.cause}`); | ||
}) | ||
``` | ||
@@ -106,0 +112,0 @@ |
@@ -80,2 +80,3 @@ var test = require('./lib/tape-nock-setup'); | ||
t.equals(error.status, 400, 'error code 400 returned'); | ||
t.ok(error.body.error, 'error element present'); | ||
t.end(); | ||
@@ -88,4 +89,5 @@ }); | ||
bby.products('gurgleflats') | ||
.catch(function (data) { | ||
t.equals(data.status, 400, 'status 400 returned'); | ||
.catch(function (error) { | ||
t.equals(error.status, 400, 'status 400 returned'); | ||
t.ok(error.body.error, 'error element present'); | ||
t.end(); | ||
@@ -99,2 +101,3 @@ }); | ||
t.equals(err.status, 400, 'status 400 returned'); | ||
t.ok(err.body.error, 'error element present'); | ||
t.end(); | ||
@@ -211,10 +214,18 @@ }); | ||
test('Is a garbage search as xml stream', test.opts, function (t) { | ||
// Do a search which emits an error | ||
var stream = bby.productsAsStream('gurgleflats', {format: 'xml'}); | ||
test('Handles garbage search with xml stream', test.opts, function (t) { | ||
const stream = bby.productsAsStream('gurgleflats', {format: 'xml'}); | ||
stream.on('error', err => { | ||
t.equals(err.status, 400, 'returns response status'); | ||
t.ok(err.body.indexOf('<error') > -1, 'error element present'); | ||
t.end(); | ||
}); | ||
}); | ||
test('Handles garbage search with json stream', test.opts, function (t) { | ||
const stream = bby.productsAsStream('gurgleflats', {format: 'json'}); | ||
stream.on('error', err => { | ||
t.ok(err.toString().indexOf('<error') > -1, 'error element present'); | ||
t.equals(err.status, 400, 'returns response status'); | ||
t.ok(err.body.error, 'error element present'); | ||
t.end(); | ||
}); | ||
}); |
@@ -132,5 +132,5 @@ var test = require('./lib/tape-nock-setup'); | ||
stream.on('error', (err) => { | ||
t.ok(err.message.startsWith("Couldn't understand"), 'error returned'); | ||
t.ok(err.body.error.message.startsWith("Couldn't understand"), 'error returned'); | ||
t.end(); | ||
}); | ||
}); |
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
1724477
125
32799
481