Socket
Socket
Sign inDemoInstall

ebay-api

Package Overview
Dependencies
6
Maintainers
1
Versions
73
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 1.3.0 to 1.4.0

lib/key-lists.js

228

lib/json-parser.js

@@ -15,5 +15,7 @@ /**

EbayRequestError = _errors.EbayRequestError,
EbayClientError = _errors.EbayClientError;
EbayClientError = _errors.EbayClientError,
knownArrayKeysByApiEndpoint = require('./key-lists').knownArrayKeysByApiEndpoint;
/*

@@ -49,5 +51,17 @@ helper: find an array containing only special key-value pairs

*/
function _canFlattenKey(key) {
if (/Array$/.test(key)) return false;
if (key === 'Item') return false;
function _canFlattenKey(key, requestContext) {
//debug('_canFlattenKey?', key, requestContext);
// assume that '*Array' and '*List' elements are arrays.
if (/Array$/.test(key) || /List$/.test(key)) return false;
// per-endpoint blacklist of known array keys.
if (requestContext != null && requestContext.serviceName && requestContext.opType &&
knownArrayKeysByApiEndpoint[requestContext.serviceName] != null &&
knownArrayKeysByApiEndpoint[requestContext.serviceName][requestContext.opType] != null &&
_.contains(knownArrayKeysByApiEndpoint[requestContext.serviceName][requestContext.opType], key)) {
return false;
}
// otherwise assume it can be flattened if there's a single value.
return true;

@@ -59,90 +73,134 @@ }

convert `OrderArray: [ Order: [...] ]` structure to `Orders: []`.
@param obj: the obj *containing* the key to be restructured.
@param parentObj: the obj *containing* the key to be restructured.
@param key: the key within the object to fix.
modifies byref - no return.
*/
function _flattenSillyArray(obj, key) {
function _flattenSillyArray(parentObj, key, requestContext) {
//debug('_flattenSillyArray', key, parentObj[key]);
var subKey = key.replace(/Array$/, ''); // e.g. 'Order' from 'OrderArray'
var newKey = subKey + 's'; // e.g. 'Orders'
obj[newKey] = obj[key][0][subKey];
delete obj[key];
parentObj[newKey] = parentObj[key][0][subKey];
delete parentObj[key];
obj[newKey] = obj[newKey].map(function(subObj) {
return exports.flatten(subObj);
// might have already been flattened...
if (!_.isArray(parentObj[newKey])) parentObj[newKey] = [ parentObj[newKey] ];
parentObj[newKey] = parentObj[newKey].map(function(subObj) {
return exports.flatten(subObj, -1, requestContext);
});
return obj;
}
function _convertAmountStructure(obj) {
if (obj.hasOwnProperty('_')) {
obj.amount = obj._;
delete obj._;
function _convertAmountStructure(el, requestContext) {
if (_.isArray(el)) {
return el.map(function(subEl) {
return _convertAmountStructure(subEl);
});
}
if (obj.hasOwnProperty('$')) {
_.extend(obj, obj['$']);
delete obj['$'];
if (el.hasOwnProperty('_') && el.hasOwnProperty('$')) {
el.amount = +el._;
delete el._;
_.extend(el, el['$']); // {currencyID}
delete el['$'];
}
return obj;
return el;
}
function _castTypes(el) {
if (_.isString(el)) {
if (!isNaN(el)) el = +el; // numeric string to number
else if (el === 'true') el = true;
else if (el === 'false') el = false;
}
return el;
}
/*
helper: RECURSIVELY turn 1-element arrays/objects into flat vars
(different from _.flatten() which returns an array)
*/
exports.flatten = function flatten(el, maxDepth, _depth) {
recursively turn 1-element arrays/objects into flat values/objects.
intended to handle flaw of XML->JSON conversion, that everything becomes an array.
NOTE this is risky/complicated, because it has to make assumptions
about what *should* remain an array,
so some items might be structured differently depending on number of values.
helpers like `canFlattenKey()` try to mitigate this risk.
also transforms numbers and booleans from strings to types.
*/
exports.flatten = function flatten(el, maxDepth, requestContext, _depth) {
if (_.isUndefined(_depth)) _depth = 0;
if (_.isUndefined(maxDepth)) maxDepth = 10;
if (_.isUndefined(maxDepth) || maxDepth < 1) maxDepth = 10;
if (_depth === 0) debug('flattening', el, {maxDepth: maxDepth});
if (_depth === 0) debug('flattening', el, {maxDepth: maxDepth, requestContext: requestContext});
if (_depth > maxDepth) return el;
if (_depth <= maxDepth) {
// flatten 1-item arrays
if (_.isArray(el) && el.length === 1) {
el = _.first(el);
}
// flatten 1-item arrays.
// note: this is dangerous, means responses w/ single value can look different from multiple values.
// trying to mitigate with `canFlattenKey()` check below.
if (_.isArray(el) && el.length === 1) {
el = _.first(el);
}
// special value-pair structure in the ebay API: turn { @key:KEY, __value__:VALUE } into { KEY: VALUE }
if (_isValuePair(el)) {
var values = _.values(el);
debug('found special element', el);
el = {};
el[ values[0] ] = values[1];
debug('converted element:', el);
}
// weird value-pair structure:
// turn `{ @key:KEY, __value__:VALUE }` into `{ KEY: VALUE }`
if (_isValuePair(el)) {
var values = _.values(el);
debug('converting key-value pair', el);
el = {};
el[ values[0] ] = values[1];
}
// previous fix just creates an array of these. we want a clean key:val obj.
// so, is this an array of special value-pairs?
if (_isArrayOfValuePairs(el)) {
var fixEl = {};
_(el).each(function(pair) {
_.extend(fixEl, flatten(pair, maxDepth, _depth+1)); // fix each, combine
});
el = fixEl;
}
//// previous fix just creates an array of these. we want a clean key:val obj.
//// so, is this an array of special value-pairs?
//// TODO - disabled this b/c old and inefficient - understand where it was needed, and try to optimize.
//if (_isArrayOfValuePairs(el)) {
// var fixEl = {};
// _(el).each(function(pair) {
// _.extend(fixEl, flatten(pair, maxDepth, requestContext, _depth + 1)); // fix each, combine
// });
// el = fixEl;
//}
// flatten sub-elements
if (_.isArray(el)) {
_.each(el, function(subEl, subInd) {
el[subInd] = flatten(el[subInd], maxDepth, _depth+1);
});
}
else if (_.isObject(el)) {
_.each(el, function(subEl, subKey) {
// special cases
if (/Array$/.test(subKey)) {
el = _flattenSillyArray(el, subKey);
}
else if (/Amount/.test(subKey)) {
el[subKey] = _convertAmountStructure(el[subKey]);
}
else if (_canFlattenKey(subKey)) {
el[subKey] = flatten(el[subKey], maxDepth, _depth + 1);
}
});
}
// flatten sub-elements
if (_.isObject(el) && !_.isArray(el)) {
debug('--is an object', el);
_.forOwn(el, function(childEl, childKey) {
debug('--child', childKey, childEl);
// special cases
if (/Array$/.test(childKey)) {
_flattenSillyArray(el, childKey, requestContext); // on parent, byref
}
else if (/(Amount|Cost|Price)/.test(childKey)) {
el[childKey] = _convertAmountStructure(childEl, requestContext);
}
if (_canFlattenKey(childKey, requestContext)) {
el[childKey] = flatten(childEl, maxDepth, requestContext, _depth + 1);
}
// can't flatten [presumed] array itself, but can still flatten its children.
// @REVIEW: this causes weird skipping behavior, where grandchildren are flattened before higher levels,
// so can't assume that lower levels haven't been flattened yet!
else if (_.isArray(childEl)) {
debug('---grandchildren', childKey, childEl, el[childKey]===childEl, typeof childEl.map);
el[childKey] = childEl.map(function(grandChildEl) {
return flatten(grandChildEl, maxDepth, requestContext, _depth + 1);
});
}
});
}
if (_.isArray(el)) {
el = el.map(function(childEl) {
return flatten(childEl, maxDepth, requestContext, _depth + 1);
});
}
} //depth
el = _castTypes(el);
debug('flattened to', el);
return el;

@@ -155,3 +213,3 @@ };

@param data: response, converted to (or originally in) JSON.
@param options: context on the request.
@param requestContext: context on the request.
@param callback: gets `null, data` in success case, and `error, data` on error case.

@@ -161,19 +219,23 @@ - error can be from response or parsing failure. (see error types.)

*/
exports.parseResponseJson = function(data, options, callback) {
debug('parsing items', data);
exports.parseResponseJson = function(data, requestContext, callback) {
debug('parsing response json', data, requestContext);
var flatten = exports.flatten;
data = flatten(data, 1); // top level first
debug('flattened', data);
// flattening can be slow with big responses;
// don't necessarily want to flatten all the way up front.
// (maybe better to let app pick the keys it wants and flatten only them.)
// depth here is arbitrary.
data = flatten(data, 5, requestContext);
// find the response key.
// (is probably `{options.opType}Response`)
// (is probably `{requestContext.opType}Response`)
var responseKey = _(data).keys().find(function(key) {
return /[a-zA-Z]+Response$/.test(key);
}) || options.opType + 'Response';
}) || requestContext.opType + 'Response';
debug('looking for response key', responseKey);
data = flatten(data[responseKey], 1); // drill down 1 more level
data = data[responseKey];
if (_.isUndefined(data)) {

@@ -199,3 +261,3 @@ // assume this is a failure of the client to parse the response properly.

if (!_.isUndefined(data.Ack)) {
data.Ack = flatten(data.Ack);
data.Ack = flatten(data.Ack, -1, requestContext);
}

@@ -221,3 +283,3 @@

errorMessage = errors.map(function(errorObj) {
errorObj = flatten(errorObj);
errorObj = flatten(errorObj, -1, requestContext);
if (errorObj.ErrorClassification === 'SystemError') {

@@ -233,3 +295,3 @@ errorClassification = 'SystemError'; // trumps RequestError

else if (!_.isUndefined(data.errorMessage)) {
errorMessage = flatten(data.errorMessage);
errorMessage = flatten(data.errorMessage, -1, requestContext);
if (_.isObject(errorMessage)) errorMessage = util.inspect(errorMessage, true, 3);

@@ -251,10 +313,2 @@ // TODO error code and classification in this format?

// flatten a little more.
// see `_canFlattenKey()` for exceptions.
data = flatten(data, 1);
if (data.paginationOutput) {
data.paginationOutput = flatten(data.paginationOutput);
}
//

@@ -261,0 +315,0 @@ // PER-OP PARSING

{
"name": "ebay-api",
"description": "eBay API Client",
"version": "1.3.0",
"version": "1.4.0",
"homepage": "https://github.com/newleafdigital/nodejs-ebay-api",

@@ -6,0 +6,0 @@ "author": "Ben Buckman <ben@newleafdigital.com> (http://newleafdigital.com)",

@@ -30,5 +30,5 @@ #! /usr/bin/env node

},
function(data, next) {
parseResponseJson(data, {}, next);
}
//function(data, next) {
// parseResponseJson(data, {}, next);
//}
],

@@ -35,0 +35,0 @@ function(error, parsedJson) {

@@ -1,6 +0,3 @@

var
chai = require('chai'),
expect = chai.expect;
require('./helpers');
describe('`deepToArray`', function() {

@@ -7,0 +4,0 @@ var deepToArray = require('../lib/deep-to-array').deepToArray;

@@ -0,3 +1,5 @@

require('./helpers');
describe('`paginatedRequest`', function() {
it('#TODO')
});

@@ -1,8 +0,3 @@

var
chai = require('chai'),
expect = chai.expect,
sinon = require('sinon');
require('./helpers');
chai.use(require("sinon-chai"));
var

@@ -14,10 +9,2 @@ request = require('request'),

describe('XML requests', function() {
beforeEach('sandbox', function() {
this.sinon = sinon.sandbox.create();
});
afterEach('unstub', function() {
this.sinon.restore();
});
describe('building requests', function() {

@@ -390,6 +377,1 @@ beforeEach('stub request', function () {

});
// @TODO try to hit an actual sandbox endpoint ...?
// (can a sandbox key be hard-coded in this module?)
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap

Packages

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc