Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 30 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,12 @@ Supports throttling and pagification. (NextToken stuff)
Examples
--------

Installation:
### Installation:
```
npm i mws-api -S
```

Initialization:
### Initialization:

```javascript
const MWSClient = require('mws-api');
Expand All @@ -40,7 +40,7 @@ const mws = new MWSClient({
}
```

Usage:
### Usage:

```javascript

Expand All @@ -55,7 +55,7 @@ mws.Orders.ListOrders({
});
```

Flat files:
### Flat files:

When working with a flat-file response from Amazon, a `parseCSVResult` function is provided as an
option to conviniently post-process the result. Returning a Promise will result in the Promise being resolved.
Expand All @@ -73,3 +73,29 @@ const mws = new MWSClient({
}
});
```

### Fulfillment:

```javascript
mws.FulfillmentOutboundShipment.CreateFulfillmentOrder({
SellerFulfillmentOrderId: 'order-id', // must be unique for each order
DisplayableOrderId: 'order-id',
DisplayableOrderComment: 'order-comment',
DisplayableOrderDateTime: (new Date()).toISOString(),
FulfillmentAction: 'Hold', // or 'Ship'
ShippingSpeedCategory: 'Standard', // or 'Expedited' or 'Priority'
'DestinationAddress.Name': 'Chip Douglas',
'DestinationAddress.Line1': '7662 Beach Blvd',
'DestinationAddress.Line2': '',
'DestinationAddress.Line3': '',
'DestinationAddress.City': 'Buena Park',
'DestinationAddress.StateOrProvinceCode': 'CA',
'DestinationAddress.PostalCode': '90620',
'DestinationAddress.CountryCode': 'US',
LineItems: [{
Quantity: 1,
SellerFulfillmentOrderItemId: 'order-id' + '_0',
SellerSKU: '101'
}]
});
```
8 changes: 2 additions & 6 deletions lib/client.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
const _ = require('lodash');
const crypto = require('crypto');
const Promise = require('bluebird');
const qs = require('querystring');
const qs = require('qs');
const request = require('request');
const tls = require('tls');
const parseString = Promise.promisify(require('xml2js').parseString);
Expand Down Expand Up @@ -223,11 +223,7 @@ class AmazonMwsClient {
}, {});

const stringToSign = ['POST', this.host, path, qs.stringify(sorted)]
.join('\n')
.replace(/'/g, '%27')
.replace(/\*/g, '%2A')
.replace(/\(/g, '%28')
.replace(/\)/g, '%29');
.join('\n');

return _.assign({}, query, {
Signature: crypto.createHmac('sha256', this.secretAccessKey)
Expand Down
55 changes: 0 additions & 55 deletions lib/complexList.js

This file was deleted.

91 changes: 60 additions & 31 deletions lib/request.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,8 @@ function getValueForParam(param, val) {
case Type.BOOLEAN:
return String(!!val);

case Type.COMPLEX:
// return param.construct(members); // TODO: fix
case Type.OBJECT:
return val;

default:
return val;
Expand Down Expand Up @@ -62,13 +62,19 @@ class AmazonMwsRequest {
});
this.action = options.action || 'GetServiceStatus';

options.params = _.mapValues(options.params, function (param, name) {
if (!param.name) {
param.name = name;
}
function deepDefaultNamesToKeys(object) {
object = _.mapValues(object, (param, key) => {
if (!param.name) {
param.name = key;
}
if (param.params) {
deepDefaultNamesToKeys(param.params);
}
return param;
});
}

return param;
});
deepDefaultNamesToKeys(options.params);

this.params = _.reduce(options.params, function (params, param, name) {
const realName = param.name;
Expand Down Expand Up @@ -137,6 +143,13 @@ class AmazonMwsRequest {
return this;
}

const allowedParamNames = _.union(_.keys(this.params), _.keys(this.paramsMap));
if (!_.includes(allowedParamNames, paramName)) {
throw new Error(`Unknown parameter \`${paramName}\`; valid params: ` + _.join(_.map(allowedParamNames, (name) => {
return '`' + name + '`';
}), ', '));
}

if (this.paramsMap[paramName]) {
paramName = this.paramsMap[paramName];
}
Expand All @@ -145,26 +158,32 @@ class AmazonMwsRequest {

const getValue = _.partial(getValueForParam, param);

function toCollection(value) {
return (_.isString(value) || _.isNumber(value)) ? [value] : value;
}

// Lists need to be sequentially numbered and we take care of that here
if (param.list) {
const values = _.map(toCollection(value), getValue);
const values = _.isArray(value) ? value : [value];

_.forEach(values, (value, i) => {
this.values[`${param.name}.${i + 1}`] = value;
const indexedName = `${param.name}.${i + 1}`;
this.assign(indexedName, getValue(value));
});
}
else {
this.values[param.name] = getValue(value);
} else {
this.assign(param.name, getValue(value));
}
}

return this;
}

assign(name, value) {
if (_.isObject(value)) {
_.assign(this.values, _.mapKeys(value, (_, key) => {
return name + '.' + key;
}));
} else {
this.values[name] = value;
}
}

setMultiple(conf) {
_.each(conf, (value, key) => {
this.set(key, value);
Expand All @@ -180,22 +199,32 @@ class AmazonMwsRequest {
*/
query() {
return Promise.try(() => {
const missing = _.filter(this.params, (param) => {
const isList = param.list;
const isRequired = param.required;

if (!isRequired) {
return false;
}

const value = isList ? this.values[`${param.name}.1`] : this.values[param.name];

// intentional `==`
return value == null;
});
const missing = checkParams(this.values, this.params, '');

// Iterate through params and return list of any required and missing
// Recurse on object-lists
// prefix must be `''` or end with a `.`
function checkParams(values, params, prefix) {
return _.reduce(params, (missingParams, param) => {
const isList = param.list;
const isObject = param.type === Type.OBJECT;
const paramName = prefix + param.name + (isList ? '.1' : '');

if (isList && isObject) {
// recurse
return _.concat(missingParams, checkParams(values, param.params, paramName + '.'));
}

// check param
if (param.required && _.isNil(values[paramName])) {
return _.concat(missingParams, paramName);
}
return missingParams;
}, []);
}

if (missing.length > 0) {
throw new Error(`ERROR: Missing required parameter${missing.length > 1 ? 's' : ''}: ${_.map(missing, 'name').join(', ')}!`);
throw new Error(`Missing required parameter${missing.length > 1 ? 's' : ''}: ${_.join(missing,', ')}!`);
}

return this.values;
Expand Down
Loading