diff --git a/README b/README deleted file mode 100644 index e69de29..0000000 diff --git a/README.md b/README.md index d1c38fd..2412566 100644 --- a/README.md +++ b/README.md @@ -1,36 +1,54 @@ mws-js ====== -I find Node.js an absolute pleasure to work with and made this rough -Marketplace web services client as one of my first projects. I still find it -beats the snot out of PHP, Java, or C# packages Amazon publishes. -I use it for real-time integration and/or dashboards for e-commerce clients. -Note: there may be tons of bugs since I updated the formatting to be a lot -more user-friendly, but almost all of the documented functions and objects -should work fine and dandy like cotton candy. +Complete Amazon marketplace web services client for Node.js. This project is still a work in progress, not all interfaces are fully tested and working. Usage ===== -Super simple example --------------------- +config +------ +```javascript +loginInfo = { + locale: 'US', + merchantId: 'XXXXXXX', + marketplaceId: 'XXXXXXX', + accessKeyId: 'XXXXXXX', + secretAccessKey: 'XXXXX' +} -I will be creating some sample projects illustrating how to take advantage -of complex/enum params and other more useful features of this library, but -the most basic usage I could come up with goes something like: +``` +.js Example +------------- +Fetching a product info: ```javascript -var mws = require('mws'), - client = new AmazonMwsClient('accessKeyId', 'secretAccessKey', 'merchantId', {}); - -// Get the service status of Sellers API endpoint and print it -client.invoke(new mws.sellers.requests.GetServiceStatus(), console.log); - -var listOrders = new mws.orders.requests.ListOrders(); -listOrders.set('MarketplaceId', 'marketplaceId') - .set('CreatedAfter', new Date(2,14,2012)); -client.invoke(listOrders, function(result) { - console.log(result); - // Do something fun with the results... +var mws = require('mws-js'); +var client = new mws.products.Client(loginInfo); + +client.getMatchingProductForId('ASIN', 'B005ISQ7JC', function(res){ + if (res.error) { + console.error(res.error); + } else if (res.result) { + console.log(res.result); + } }); -``` \ No newline at end of file + +``` + +Coffee Script example +-------------- +Fetching a product info: +``` +mws = require equire 'mws-js' +client = new mws.products.Client(loginInfo) + +client.getMatchingProductForId 'ASIN', ASIN_ID , (res) => + if res.error + console.error res.error + else if res.result + console.log util.inspect(res.result,false,10) + +``` + +You can have a look at test directory for more examples. diff --git a/index.js b/index.js new file mode 100644 index 0000000..c42b664 --- /dev/null +++ b/index.js @@ -0,0 +1,15 @@ +// Pull in our core mws-js module +var mws = require('./lib/core'); + +// Pull in each of the the individual API modules +mws.fba = require('./lib/fba'); +mws.feeds = require('./lib/feeds'); +mws.orders = require('./lib/orders'); +mws.products = require('./lib/products'); +mws.reports = require('./lib/reports'); +mws.sellers = require('./lib/sellers'); + +module.exports = mws + +// var util = require('util'); +// console.log(util.inspect(mws)); \ No newline at end of file diff --git a/lib/core.js b/lib/core.js new file mode 100644 index 0000000..fe2bd41 --- /dev/null +++ b/lib/core.js @@ -0,0 +1,978 @@ +// Generated by CoffeeScript 1.6.3 +(function() { + var EventEmitter, MWSBool, MWSClient, MWSComplexList, MWSComplexParam, MWSEnum, MWSEnumList, MWSParam, MWSParamList, MWSRequest, MWSResponse, MWSService, MWSTimestamp, MWS_LOCALES, MWS_MARKETPLACES, MWS_SIGNATURE_METHOD, MWS_SIGNATURE_VERSION, crypto, https, qs, types, xml2js, _ref, _ref1, + __hasProp = {}.hasOwnProperty, + __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }, + __slice = [].slice, + __indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; }; + + EventEmitter = require("events").EventEmitter; + + https = require("https"); + + qs = require("querystring"); + + crypto = require("crypto"); + + xml2js = require('xml2js'); + + MWS_SIGNATURE_METHOD = 'HmacSHA256'; + + MWS_SIGNATURE_VERSION = 2; + + MWS_MARKETPLACES = { + ATVPDKIKX0DER: 'US', + A1F83G8C2ARO7P: 'UK', + A13V1IB3VIYZZH: 'FR', + A1PA6795UKMFR9: 'DE', + APJ6JRA9NG5V4: 'IT', + A1RKKUPIHCS9HS: 'ES', + US: 'ATVPDKIKX0DER', + UK: 'A1F83G8C2ARO7P', + FR: 'A13V1IB3VIYZZH', + DE: 'A1PA6795UKMFR9', + IT: 'APJ6JRA9NG5V4', + ES: 'A1RKKUPIHCS9HS', + CA: null, + CN: null, + JP: null + }; + + MWS_LOCALES = { + US: { + host: "mws.amazonservices.com", + country: 'UnitedStates', + domain: 'www.amazon.com', + marketplaceId: MWS_MARKETPLACES.US + }, + UK: { + host: "mws.amazonservices.co", + country: 'UnitedKingdom', + domain: 'www.amazon.co.uk', + marketplaceId: MWS_MARKETPLACES.UK + }, + FR: { + host: "mws.amazonservices.fr", + country: 'France', + domain: 'www.amazon.fr', + marketplaceId: MWS_MARKETPLACES.FR + }, + DE: { + host: "mws.amazonservices.de", + country: 'Germany', + domain: 'www.amazon.de', + marketplaceId: MWS_MARKETPLACES.DE + }, + IT: { + host: "mws.amazonservices.it", + country: 'Italy', + domain: 'www.amazon.it', + marketplaceId: MWS_MARKETPLACES.IT + }, + ES: { + host: "mws.amazonservices.es", + country: 'Spain', + domain: 'www.amazon.es', + marketplaceId: MWS_MARKETPLACES.ES + }, + CA: { + host: "mws.amazonservices.ca", + country: 'Canada', + domain: 'www.amazon.ca', + marketplaceId: MWS_MARKETPLACES.CA + }, + CN: { + host: "mws.amazonservices.cn", + country: 'China', + domain: 'www.amazon.cn', + marketplaceId: MWS_MARKETPLACES.CN + }, + JP: { + host: "mws.amazonservices.jp", + country: 'Japan', + domain: 'www.amazon.jp', + marketplaceId: MWS_MARKETPLACES.JP + } + }; + + types = { + ServiceStatus: { + GREEN: "The service is operating normally.", + GREEN_I: "The service is operating normally + additional info provided", + YELLOW: "The service is experiencing higher than normal error rates or degraded performance.", + RED: "The service is unabailable or experiencing extremely high error rates." + } + }; + + MWSClient = (function(_super) { + __extends(MWSClient, _super); + + function MWSClient() { + var e, extras, k, options, v, _i, _len, _ref, _ref1, _ref10, _ref11, _ref12, _ref13, _ref14, _ref2, _ref3, _ref4, _ref5, _ref6, _ref7, _ref8, _ref9; + options = arguments[0], extras = 2 <= arguments.length ? __slice.call(arguments, 1) : []; + if (options == null) { + options = {}; + } + for (_i = 0, _len = extras.length; _i < _len; _i++) { + e = extras[_i]; + if (typeof e === 'object') { + for (k in e) { + v = e[k]; + options[k] = v; + } + } + } + if (options.locale != null) { + if (typeof options.locale !== 'object') { + options.locale = (_ref = MWS_LOCALES[options.locale]) != null ? _ref : null; + } + this.host = (_ref1 = options.host) != null ? _ref1 : (_ref2 = options.locale.host) != null ? _ref2 : "mws.amazonservices.com"; + this.marketplaceId = options.locale.marketplaceId; + this.country = (_ref3 = options.locale.country) != null ? _ref3 : void 0; + this.domain = (_ref4 = options.locale.domain) != null ? _ref4 : void 0; + } + this.host = (_ref5 = this.host) != null ? _ref5 : (_ref6 = options.host) != null ? _ref6 : "mws.amazonservices.com"; + this.port = (_ref7 = options.port) != null ? _ref7 : 443; + this.merchantId = (_ref8 = options.merchantId) != null ? _ref8 : null; + this.accessKeyId = (_ref9 = options.accessKeyId) != null ? _ref9 : null; + this.secretAccessKey = (_ref10 = options.secretAccessKey) != null ? _ref10 : null; + if (this.marketplaceId == null) { + this.marketplaceId = (_ref11 = this.marketplaceId) != null ? _ref11 : (_ref12 = options.marketplaceId) != null ? _ref12 : null; + } + this.appName = options.appName || 'mws-js'; + this.appVersion = options.appVersion || "0.2.0"; + this.appLanguage = options.appLanguage || "JavaScript"; + this.appHost = (_ref13 = options.appHost) != null ? _ref13 : void 0; + this.appPlatform = (_ref14 = options.appPlatform) != null ? _ref14 : void 0; + options; + } + + MWSClient.prototype.sign = function(service, q) { + var hash, k, keys, path, sorted, stringToSign, v, _i, _len, _ref; + if (q == null) { + q = {}; + } + path = (_ref = service.path) != null ? _ref : '/'; + hash = crypto.createHmac("sha256", this.secretAccessKey); + if (service.legacy) { + q['Merchant'] = this.merchantId; + } else { + q['SellerId'] = this.merchantId; + } + if (q['AWSAccessKeyId'] == null) { + q['AWSAccessKeyId'] = this.accessKeyId; + } + q['SignatureMethod'] = MWS_SIGNATURE_METHOD; + q['SignatureVersion'] = MWS_SIGNATURE_VERSION; + sorted = {}; + keys = ((function() { + var _results; + _results = []; + for (k in q) { + v = q[k]; + _results.push(k); + } + return _results; + })()).sort(); + for (_i = 0, _len = keys.length; _i < _len; _i++) { + k = keys[_i]; + sorted[k] = q[k]; + } + stringToSign = "POST\n" + this.host + "\n" + path + "\n" + (qs.stringify(sorted)); + stringToSign = stringToSign.replace(/'/g, '%27'); + stringToSign = stringToSign.replace(/\*/g, '%2A'); + stringToSign = stringToSign.replace(/\(/g, '%28'); + stringToSign = stringToSign.replace(/\)/g, '%29'); + q['Signature'] = hash.update(stringToSign).digest('base64'); + return q; + }; + + MWSClient.prototype.invoke = function(request, options, cb) { + var agentParams, h, q, req, v, _ref, _ref1, _ref2, _ref3, _ref4, _ref5, + _this = this; + if (request != null ? request.body : void 0) { + request.md5Calc(); + } + if (options != null ? options.body : void 0) { + request.attach(options.body, 'text'); + } + if (options.path == null) { + options.path = (_ref = (_ref1 = request.service) != null ? _ref1.path : void 0) != null ? _ref : '/'; + } + q = this.sign((_ref2 = (_ref3 = options.service) != null ? _ref3 : request.service) != null ? _ref2 : null, request.query((_ref4 = options.query) != null ? _ref4 : {})); + if (options.headers == null) { + options.headers = {}; + } + _ref5 = request.headers; + for (h in _ref5) { + v = _ref5[h]; + options.headers[h] = v; + } + if (request.body || options.body) { + if (options.body == null) { + options.body = request.body; + } + options.path = "" + options.path + "?" + (qs.stringify(q)); + } else { + options.body = qs.stringify(q); + options.headers['content-type'] = 'application/x-www-form-urlencoded; charset=utf-8'; + } + options.headers['host'] = this.host; + agentParams = ["Language=" + this.appLanguage]; + if (this.appHost) { + agentParams.push("Host=" + this.appHost); + } + if (this.appPlatform) { + agentParams.push("Platform=" + this.appPlatform); + } + options.headers['user-agent'] = "" + this.appName + "/" + this.appVersion + " (" + (agentParams.join('; ')) + ")"; + options.headers['content-length'] = options.body.length; + if (options.host == null) { + options.host = this.host; + } + if (options.port == null) { + options.port = this.port; + } + if (options.method == null) { + options.method = 'POST'; + } + req = https.request(options, function(res) { + var data; + data = []; + res.on('data', function(chunk) { + return data.push(chunk); + }); + res.on('end', function() { + var mwsres; + data = Buffer.concat(data); + mwsres = new MWSResponse(res, data, options); + mwsres.parseHeaders(); + return mwsres.parseBody(function(err, parsed) { + var invokeOpts, nextRequest, _ref6, _ref7, _ref8; + if ((options.nextTokenCall != null) && (((_ref6 = mwsres.result) != null ? (_ref7 = _ref6.NextToken) != null ? _ref7.length : void 0 : void 0) > 0)) { + invokeOpts = { + nextTokenCall: options.nextTokenCall + }; + if (options.nextTokenCallUseHasNext) { + invokeOpts.nextTokenCallUseHasNext = options.nextTokenCallUseHasNext; + if (((_ref8 = mwsres.result) != null ? _ref8.HasNext : void 0) === 'true') { + mwsres.nextToken = mwsres.result.NextToken; + } + } else { + mwsres.nextToken = mwsres.result.NextToken; + } + nextRequest = new options.nextTokenCall({ + NextToken: mwsres.nextToken + }); + mwsres.getNext = function() { + var k, opts; + opts = {}; + for (k in invokeOpts) { + v = invokeOpts[k]; + opts[k] = v; + } + return _this.invoke(nextRequest, opts, cb); + }; + } + _this.emit('response', mwsres, parsed); + return cb(mwsres); + }); + }); + return res.on('error', function(err) { + _this.emit('error', err); + return cb(err, null, Buffer.concat(data).toString()); + }); + }); + this.emit('request', req, options); + req.write(options.body); + return req.end(); + }; + + return MWSClient; + + })(EventEmitter); + + MWSService = (function() { + function MWSService(options) { + var k, v; + for (k in options) { + v = options[k]; + this[k] = v; + } + if (this.name == null) { + this.name = null; + } + if (this.path == null) { + this.path = '/'; + } + if (this.version == null) { + this.version = '2009-01-01'; + } + if (this.legacy == null) { + this.legacy = false; + } + } + + return MWSService; + + })(); + + MWSRequest = (function() { + function MWSRequest(service, action, params, headers, body, init) { + var i, p, pid, _ref, _ref1, _ref2; + this.service = service; + this.action = action; + this.params = params != null ? params : []; + this.headers = headers != null ? headers : {}; + this.body = body != null ? body : null; + if (init == null) { + init = {}; + } + if (this.service == null) { + this.service = new MWSService; + } + _ref = this.params; + for (i in _ref) { + p = _ref[i]; + pid = (_ref1 = p.name) != null ? _ref1 : i; + if (init[pid] != null) { + p.set(init[pid]); + } + this[pid] = (_ref2 = this.params[i]) != null ? _ref2 : null; + } + } + + MWSRequest.prototype.query = function(q) { + var i, p, val, _ref, _ref1, _ref2, _ref3, _ref4, _ref5, _ref6; + if (q == null) { + q = {}; + } + _ref = this.params; + for (i in _ref) { + p = _ref[i]; + val = (_ref1 = (_ref2 = this[(_ref3 = p.name) != null ? _ref3 : i]) != null ? _ref2 : p) != null ? _ref1 : {}; + if (val.render != null) { + val.render(q); + } else { + q[(_ref4 = val.name) != null ? _ref4 : i] = (_ref5 = val.value) != null ? _ref5 : p; + } + } + q['Action'] = this.action; + q['Version'] = (_ref6 = this.service.version) != null ? _ref6 : '2009-01-01'; + q['Timestamp'] = (new Date()).toISOString(); + return q; + }; + + MWSRequest.prototype.set = function(param, value) { + var k, v, _ref, _results; + if (typeof param === 'object' && value === void 0) { + _results = []; + for (k in param) { + v = param[k]; + _results.push(this.set(k, v)); + } + return _results; + } else { + if (((_ref = this[param]) != null ? _ref.set : void 0) != null) { + return this[param].set(value != null ? value : null); + } else { + throw "" + param + " is not a valid parameter for this request type"; + } + } + }; + + MWSRequest.prototype.attach = function(body, format) { + this.body = body; + this.headers['content-type'] = format != null ? format : 'text'; + return this.md5Calc(); + }; + + MWSRequest.prototype.md5Calc = function() { + return this.headers['content-md5'] = crypto.createHash('md5').update(this.body).digest("base64"); + }; + + return MWSRequest; + + })(); + + MWSResponse = (function() { + function MWSResponse(response, body, options) { + var _ref; + if (options == null) { + options = {}; + } + this.statusCode = response.statusCode; + this.headers = response.headers; + this.body = body != null ? body : null; + this.meta = {}; + this.options = options; + this.allowedContentTypes = (_ref = options != null ? options.allowedContentTypes : void 0) != null ? _ref : []; + } + + MWSResponse.prototype.parseHeaders = function() { + var header, id, ns, value, xreg, _base, _ref, _results; + _ref = this.headers; + _results = []; + for (header in _ref) { + value = _ref[header]; + xreg = /x-(\w+)-(.*)/gi.exec(header); + if (xreg) { + ns = xreg[1]; + id = xreg[2].replace(/(\-[a-z])/g, function($1) { + return $1.toUpperCase().replace('-', ''); + }); + if ((_base = this.meta)[ns] == null) { + _base[ns] = {}; + } + _results.push(this.meta[ns][id] = value); + } else { + _results.push(void 0); + } + } + return _results; + }; + + MWSResponse.prototype.parseBody = function(cb) { + var isXml, md5, parser, _ref, _ref1, + _this = this; + isXml = false; + if (this.headers['content-type'].indexOf('text/xml') === 0) { + this.body = this.body.toString(); + isXml = true; + } else if (this.headers['content-type'].indexOf('text/plain') === 0) { + this.body = this.body.toString().trim(); + isXml = this.body.indexOf('= 0) { + md5 = crypto.createHash('md5').update(this.body).digest("base64"); + if (this.headers['content-md5'] === md5) { + this.response = this.body; + return cb(null, this.body); + } else { + this.responseType = 'Error'; + this.error = { + Type: {}, + Code: 'Client_WrongMD5', + Message: "Invalid MD5 on received content: amazon=" + this.headers['content-md5'] + " , calculated=" + md5 + }; + this.response = null; + this.responseWithInvalidMD5 = this.body; + return cb(this.error, null); + } + } else { + this.responseType = 'Error'; + this.error = { + Type: {}, + Code: 'Client_UknownContent', + Message: "Unrecognized content format: " + ((_ref1 = this.headers['content-type']) != null ? _ref1 : 'undefined') + }; + this.response = null; + return cb(this.error, null); + } + }; + + return MWSResponse; + + })(); + + MWSParam = (function() { + function MWSParam(name, required, value) { + this.name = name; + this.required = required != null ? required : false; + if (value != null) { + this.set(value); + } + } + + MWSParam.prototype.render = function(obj) { + var val; + if (obj == null) { + obj = {}; + } + val = this.get(); + if (val != null) { + obj[this.name] = this.get(); + return obj; + } else if (this.required) { + throw "Required parameter " + this.name + " must be defined!"; + } + }; + + MWSParam.prototype.get = function() { + return this.value; + }; + + MWSParam.prototype.set = function(val) { + this.value = val; + return this; + }; + + return MWSParam; + + })(); + + MWSBool = (function(_super) { + __extends(MWSBool, _super); + + function MWSBool() { + _ref = MWSBool.__super__.constructor.apply(this, arguments); + return _ref; + } + + MWSBool.prototype.get = function() { + if (this.value) { + return "true"; + } else if (this.value != null) { + return "false"; + } else { + return void 0; + } + }; + + return MWSBool; + + })(MWSParam); + + MWSTimestamp = (function(_super) { + __extends(MWSTimestamp, _super); + + function MWSTimestamp() { + _ref1 = MWSTimestamp.__super__.constructor.apply(this, arguments); + return _ref1; + } + + MWSTimestamp.prototype.get = function() { + var _ref2; + if (((_ref2 = this.value) != null ? _ref2.constructor : void 0) === Date) { + return this.value.toISOString(); + } else { + return this.value; + } + }; + + MWSTimestamp.prototype.set = function(val) { + var e; + if (val == null) { + val = new Date(); + } + if (val.constructor !== Date) { + try { + this.value = new Date(val); + } catch (_error) { + e = _error; + this.value = val; + } + } else { + this.value = val; + } + return this; + }; + + return MWSTimestamp; + + })(MWSParam); + + MWSParamList = (function(_super) { + __extends(MWSParamList, _super); + + function MWSParamList(name, type, required, value) { + this.name = name; + this.type = type; + this.required = required; + MWSParamList.__super__.constructor.call(this, this.name, this.required, value != null ? value : []); + this.list = true; + } + + MWSParamList.prototype.render = function(obj) { + var k, v, _ref2; + if (obj == null) { + obj = {}; + } + if (this.value.length < 1 && this.required) { + throw "Required parameter list, " + this.name + " is empty!"; + } + _ref2 = this.get(); + for (k in _ref2) { + v = _ref2[k]; + obj[k] = v; + } + return obj; + }; + + MWSParamList.prototype.clear = function() { + return this.value = []; + }; + + MWSParamList.prototype.add = function() { + var vals; + vals = 1 <= arguments.length ? __slice.call(arguments, 0) : []; + return this.value = this.value.concat(vals); + }; + + MWSParamList.prototype.get = function() { + var count, i, index, list, v, _i, _j, _len, _len1, _ref2; + index = 1 <= arguments.length ? __slice.call(arguments, 0) : []; + list = {}; + count = 0; + if (index.length < 1) { + _ref2 = this.value; + for (_i = 0, _len = _ref2.length; _i < _len; _i++) { + v = _ref2[_i]; + list["" + this.name + "." + this.type + "." + (++count)] = v; + } + } else { + for (_j = 0, _len1 = index.length; _j < _len1; _j++) { + i = index[_j]; + if (this.value[i] == null) { + throw "ERROR: INVALID INDEX " + i; + } + list["" + this.name + "." + this.type + "." + (++count)] = this.value[i]; + } + } + return list; + }; + + MWSParamList.prototype.set = function(val) { + if (Array.isArray(val)) { + return this.value = val; + } else { + return this.value = [val]; + } + }; + + return MWSParamList; + + })(MWSParam); + + MWSEnum = (function(_super) { + __extends(MWSEnum, _super); + + function MWSEnum(name, members, required, value) { + this.name = name; + this.members = members != null ? members : []; + this.required = required != null ? required : false; + this.value = null; + if (value != null) { + this.set(value); + } + } + + MWSEnum.prototype.set = function(val) { + if (__indexOf.call(this.members, val) >= 0) { + return this.value = val; + } else if (this.members[val] != null) { + return this.value = this.members[val]; + } else { + throw "Invalid enumeration value, '" + val + "', must be a member or index of " + this.members; + } + }; + + return MWSEnum; + + })(MWSParam); + + MWSEnumList = (function(_super) { + __extends(MWSEnumList, _super); + + function MWSEnumList(name, type, members, required, initValue) { + var m, _i, _len, _ref2; + this.name = name; + this.type = type; + this.members = members; + this.required = required != null ? required : false; + this.list = true; + this.value = {}; + _ref2 = this.members; + for (_i = 0, _len = _ref2.length; _i < _len; _i++) { + m = _ref2[_i]; + this.value[m] = initValue != null ? initValue : false; + } + } + + MWSEnumList.prototype.render = function(obj) { + var k, onset, v; + if (obj == null) { + obj = {}; + } + onset = this.get(); + if (onset.length < 1 && this.required) { + throw "Required paremeter list (enum), " + this.name + " is empty!"; + } + for (k in onset) { + v = onset[k]; + obj[k] = v; + } + return obj; + }; + + MWSEnumList.prototype.enable = function() { + var v, values, _results; + values = 1 <= arguments.length ? __slice.call(arguments, 0) : []; + _results = []; + for (v in values) { + if (__indexOf.call(this.members, v) >= 0) { + _results.push(this.value[v] = true); + } + } + return _results; + }; + + MWSEnumList.prototype.disable = function() { + var v, values, _results; + values = 1 <= arguments.length ? __slice.call(arguments, 0) : []; + _results = []; + for (v in values) { + if (__indexOf.call(this.members, v) >= 0) { + _results.push(this.value[v] = false); + } + } + return _results; + }; + + MWSEnumList.prototype.toggle = function() { + var v, values, _results; + values = 1 <= arguments.length ? __slice.call(arguments, 0) : []; + _results = []; + for (v in values) { + if (__indexOf.call(this.members, v) >= 0) { + _results.push(this.value[v] = this.value[v] ? false : true); + } + } + return _results; + }; + + MWSEnumList.prototype.clear = function() { + return this.disable(this.members); + }; + + MWSEnumList.prototype.all = function() { + return this.enable(this.members); + }; + + MWSEnumList.prototype.invert = function() { + return this.toggle(this.members); + }; + + MWSEnumList.prototype.add = function(value, enabled) { + if (enabled == null) { + enabled = true; + } + this.members[value] = enabled; + this.value[value] = enabled; + return this; + }; + + MWSEnumList.prototype.get = function() { + var count, i, k, list, v, _ref2; + list = {}; + count = 0; + for (i in this.value) { + _ref2 = this.value[i]; + for (k in _ref2) { + v = _ref2[k]; + if (v === true) { + list["" + this.name + "." + this.type + "." + (++count)] = k; + } + } + } + return list; + }; + + return MWSEnumList; + + })(MWSParamList); + + MWSComplexParam = (function(_super) { + __extends(MWSComplexParam, _super); + + function MWSComplexParam(name, params, required, value) { + this.name = name; + this.params = params; + this.required = required; + if (this.params == null) { + this.params = {}; + } + } + + MWSComplexParam.prototype.render = function(obj) { + var fields, k, v; + if (obj == null) { + obj = {}; + } + fields = this.get(); + for (k in fields) { + v = fields[k]; + if (v === null) { + throw "Missing required parameter " + k; + } else { + obj[k] = v; + } + } + return obj; + }; + + MWSComplexParam.prototype.render = function(obj) { + var k, n, p, v, _ref2, _ref3, _ref4; + if (obj == null) { + obj = {}; + } + _ref2 = this.params; + for (k in _ref2) { + p = _ref2[k]; + n = (_ref3 = p.name) != null ? _ref3 : k; + v = (_ref4 = typeof p.get === "function" ? p.get() : void 0) != null ? _ref4 : p.value; + if (v != null) { + obj["" + this.name + "." + n] = v; + } else if (p.required) { + throw "Missing required parameter " + this.name + "." + n; + } + } + return obj; + }; + + MWSComplexParam.prototype.get = function(field) { + var k, obj, p, _ref2, _ref3, _results; + if ((field != null) && (this.params[field] != null)) { + return this.params[field].get(); + } else if (field == null) { + obj = {}; + _ref2 = this.params; + _results = []; + for (k in _ref2) { + p = _ref2[k]; + _results.push(obj[k] = p); + } + return _results; + } else { + _ref3 = this.params; + for (k in _ref3) { + p = _ref3[k]; + if (p.name === field) { + return p; + } + } + throw "There is no field, " + field + ", in " + this.name; + } + }; + + MWSComplexParam.prototype.set = function(field, value) { + var k, v, _ref2, _results, _results1; + if (arguments.length === 1 && typeof field === 'object') { + _results = []; + for (k in field) { + v = field[k]; + _results.push(this.set(k, v)); + } + return _results; + } else if (this.params[field] != null) { + if (this.params[field].set != null) { + return this.params[field].set(value); + } else { + return this.params[field].value = value; + } + } else { + _ref2 = this.params; + _results1 = []; + for (k in _ref2) { + v = _ref2[k]; + if (v.name.toLowerCase() === field.toLowerCase()) { + _results1.push(this.set(k, value)); + } else { + _results1.push(void 0); + } + } + return _results1; + } + }; + + return MWSComplexParam; + + })(MWSParam); + + MWSComplexList = (function(_super) { + __extends(MWSComplexList, _super); + + function MWSComplexList(name, type, required, value) { + this.name = name; + this.type = type; + this.required = required; + MWSComplexList.__super__.constructor.call(this, this.name, this.required, value != null ? value : []); + this.list = true; + } + + MWSComplexList.prototype.render = function(obj) { + var k, v, _ref2; + if (obj == null) { + obj = {}; + } + if (this.value.length < 1 && this.required) { + throw "Required (complex) parameter list, " + this.name + " is empty!"; + } + _ref2 = this.get(); + for (k in _ref2) { + v = _ref2[k]; + v.name = k; + v.render(obj); + } + return obj; + }; + + return MWSComplexList; + + })(MWSParamList); + + module.exports = { + MARKETPLACES: MWS_MARKETPLACES, + LOCALES: MWS_LOCALES, + types: types, + Client: MWSClient, + Request: MWSRequest, + Response: MWSResponse, + Service: MWSService, + Param: MWSParam, + Bool: MWSBool, + Timestamp: MWSTimestamp, + ParamList: MWSParamList, + Enum: MWSEnum, + EnumList: MWSEnumList, + ComplexParam: MWSComplexParam, + ComplexList: MWSComplexList + }; + +}).call(this); diff --git a/lib/fba.js b/lib/fba.js index e8704b1..713459e 100644 --- a/lib/fba.js +++ b/lib/fba.js @@ -1,331 +1,671 @@ - /** - * Fulfillment API requests and definitions for Amazon's MWS web services. - * Currently untested, for the most part because I don't have an account - * with Fulfillment By Amazon services. - * - * @author Robert Saunders - */ -var mws = require('./mws'); - -/** - * Construct a mws fulfillment api request for mws.Client.invoke() - * @param {String} group Group name (category) of request - * @param {String} path Path of associated group - * @param {String} action Action request will be calling - * @param {Object} params Schema of possible request parameters - */ -function FulfillmentRequest(group, path, action, params) { - var opts = { - name: 'Fulfillment', - group: group, - path: path, - version: '2010-10-01', - legacy: false, - action: action, - params: params - }; - return new mws.Request(opts); -} - -function FbaInboundRequest(action, params) { - return FulfillmentRequest('Inbound Shipments', '/FulfillmentInboundShipment/2010-10-01', action, params); -} - -function FbaInventoryRequest(action, params) { - return FulfillmentRequest('Inventory', '/FulfillmentInventory/2010-10-01', action, params); -} - -function FbaOutboundRequest(action, params) { - return FulfillmentRequest('Outbound Shipments', '/FulfillmentOutboundShipment/2010-10-01', action, params); -} - -/** - * Initialize and create an add function for ComplexList parameters. You can create your - * own custom complex parameters by making an object with an appendTo function that takes - * an object as input and directly sets all of the associated values manually. - * - * @type {Object} - */ -var complex = exports.complex = { - - /** - * Complex List used for CreateInboundShipment & UpdateInboundShipment requests - */ - InboundShipmentItems: function() { - var obj = new mws.ComplexList('InboundShipmentItems.member'); - obj.add = function(quantityShipped, sellerSku) { - obj.members.push({'QuantityShipped': quantityShipped, 'SellerSKU': sellerSku}); - return obj; - }; - return obj; - }, - - /** - * Complex List used for CreateInboundShipmentPlan request - */ - InboundShipmentPlanRequestItems: function() { - var obj = new mws.ComplexList('InboundShipmentPlanRequestItems.member'); - obj.add = function(sellerSku, asin, quantity, condition) { - obj.members.push({'SellerSKU': sellerSku, 'ASIN': asin, 'Quantity': quantity, 'Condition': condition}); - return obj; - }; - return obj; - }, - - /** - * The mac-daddy of ComplexListTypes... Used for CreateFulfillmentOrder request - */ - CreateLineItems: function() { - var obj = new mws.ComplexList('Items.member'); - obj.add = function(comment, giftMessage, decUnitValue, decValueCurrency, quantity, orderItemId, sellerSku) { - obj.members.push({ - 'DisplayableComment': comment, - 'GiftMessage': giftMessage, - 'PerUnitDeclaredValue.Value': decUnitValue, - 'PerUnitDeclaredValue.CurrencyCode': decValueCurrency, - 'Quantity': quantity, - 'SellerFulfillmentOrderItemId': orderItemId, - 'SellerSKU': sellerSku - }); - return obj; - }; - return obj; - }, - - /** - * The step child of above, used for GetFulfillmentPreview - */ - PreviewLineItems: function() { - var obj = new mws.ComplexList('Items.member'); - obj.add = function(quantity, orderItemId, sellerSku, estShipWeight, weightCalcMethod) { - obj.members.push({ - 'Quantity': quantity, - 'SellerFulfillmentOrderItemId': orderItemId, - 'SellerSKU': sellerSku, - 'EstimatedShippingWeight': estShipWeight, - 'ShippingWeightCalculationMethod': weightCalcMethod - }); - return obj; - }; - return obj; - } - -}; - -/** - * Ojects to represent enum collections used by some request(s) - * @type {Object} - */ -var enums = exports.enums = { - - ResponseGroups: function() { - return new mws.Enum(['Basic', 'Detailed']); - }, - - ShippingSpeedCategories: function() { - return new mws.Enum(['Standard', 'Expedited', 'Priority']); - }, - - FulfillmentPolicies: function() { - return new mws.Enum(['FillOrKill', 'FillAll', 'FillAllAvailable']); - } - -}; - -/** - * A collection of currently supported request constructors. Once created and - * configured, the returned requests can be passed to an mws client `invoke` call - * @type {Object} - */ -var calls = exports.requests = { - - // Inbound Shipments - inbound: { - - GetServiceStatus: function() { - return new FbaInboundRequest('GetServiceStatus', {}); - }, - - CreateInboundShipment: function() { - return new FbaInboundRequest('CreateInboundShipment', { - ShipmentId: { name: 'ShipmentId', required: true}, - Shipmentname: { name: 'InboundShipmentHeader.ShipmentName', required: true }, - ShipFromName: { name: 'InboundShipmentHeader.ShipFromAddress.Name', required: true }, - ShipFromAddressLine1: { name: 'InboundShipmentHeader.ShipFromAddress.AddressLine1', required: true }, - ShipFromAddressLine2: { name: 'InboundShipmentHeader.ShipFromAddress.AddressLine2', required: false }, - ShipFromAddressCity: { name: 'InboundShipmentHeader.ShipFromAddress.City', required: true }, - ShipFromDistrictOrCounty: { name: 'InboundShipmentHeader.ShipFromAddress.DistrictOrCounty', required: false }, - ShipFromStateOrProvince: { name: 'InboundShipmentHeader.ShipFromAddress.StateOrProvinceCode', required: true }, - ShipFromPostalCode: { name: 'InboundShipmentHeader.ShipFromAddress.PostalCode', required: true }, - ShipFromCountryCode: { name: 'InboundShipmentHeader.ShipFromAddress.CountryCode', required: true }, - DestinationFulfillmentCenterId: { name: 'InboundShipmentHeader.DestinationFulfillmentCenterId', required: true }, - ShipmentStatus: { name: 'InboundShipmentHeader.ShipmentStatus' }, - LabelPrepPreference: { name: 'InboundShipmentHeader.LabelPrepPreference' }, - InboundShipmentItems: { name: 'InboundShipmentItems', type: 'Complex', required: true, construct: complex.InboundShipmentItems } - }); - }, - - CreateInboundShipmentPlan: function() { - return new FbaInboundRequest('CreateInboundShipmentPlan', { - LabelPrepPreference: { name: 'LabelPrepPreference', required: true }, - ShipFromName: { name: 'ShipFromAddress.Name' }, - ShipFromAddressLine1: { name: 'ShipFromAddress.AddressLine1' }, - ShipFromCity: { name: 'ShipFromAddress.City' }, - ShipFromStateOrProvince: { name: 'ShipFromAddress.StateOrProvinceCode' }, - ShipFromPostalCode: { name: 'ShipFromAddress.PostalCode' }, - ShipFromCountryCode: { name: 'ShipFromAddress.CountryCode' }, - ShipFromAddressLine2: { name: 'ShipFromAddress.AddressLine2' }, - ShipFromDistrictOrCounty: { name: 'ShipFromAddress.DistrictOrCounty' }, - InboundShipmentPlanRequestItems: { name: 'InboundShipmentPlanRequestItems', type: 'Complex', required: true, construct: complex.InboundShipmentPlanRequestItems } - }); - }, - - ListInboundShipmentItems: function() { - return new FbaInboundRequest('ListInboundShipmentItems', { - ShipmentId: { name: 'ShipmentId', required: true }, - LastUpdatedAfter: { name: 'LastUpdatedAfter', type: 'Timestamp' }, - LastUpdatedAfter: { name: 'LastUpdatedBefore', type: 'Timestamp' } - }); - }, - - ListInboundShipmentItemsByNextToken: function() { - return new FbaInboundRequest('ListInboundShipmentItemsByNextToken', { - NextToken: { name: 'NextToken', required: true } - }); - }, - - ListInboundShipments: function() { - return new FbaInboundRequest('ListInboundShipments', { - ShipmentStatuses: { name: 'ShipmentStatusList.member', list: true, required: false }, - ShipmentIds: { name: 'ShipmentIdList.member', list: true, required: false }, - LastUpdatedAfter: { name: 'LastUpdatedAfter', type: 'Timestamp' }, - LastUpdatedBefore: { name: 'LastUpdatedBefore', type: 'Timestamp' } - }); - }, - - ListInboundShipmentsByNextToken: function() { - return new FbaInboundRequest('ListInboundShipmentsByNextToken', { - NextToken: { name: 'NextToken', required: true } - }); - }, - - UpdateInboundShipment: function() { - return new FbaInboundRequest('UpdateInboundShipment', { - ShipmentId: { name: 'ShipmentId', required: true }, - ShipmentName: { name: 'InboundShipmentHeader.ShipmentName', required: true }, - ShipFromName: { name: 'InboundShipmentHeader.ShipFromAddress.Name', required: true }, - ShipFromAddressLine1: { name: 'InboundShipmentHeader.ShipFromAddress.AddressLine1', required: true }, - ShipFromAddressLine2: { name: 'InboundShipmentHeader.ShipFromAddress.AddressLine2', required: false }, - ShipFromAddressCity: { name: 'InboundShipmentHeader.ShipFromAddress.City', required: true }, - ShipFromDistrictOrCounty: { name: 'InboundShipmentHeader.ShipFromAddress.DistrictOrCounty', required: false }, - ShipFromStateOrProvince: { name: 'InboundShipmentHeader.ShipFromAddress.StateOrProvinceCode', required: true }, - ShipFromPostalCode: { name: 'InboundShipmentHeader.ShipFromAddress.PostalCode', required: true }, - ShipFromCountryCode: { name: 'InboundShipmentHeader.ShipFromAddress.CountryCode', required: true }, - DestinationFulfillmentCenterId: { name: 'InboundShipmentHeader.DestinationFulfillmentCenterId', required: true }, - ShipmentStatus: { name: 'InboundShipmentHeader.ShipmentStatus' }, - LabelPrepPreference: { name: 'InboundShipmentHeader.LabelPrepPreference' }, - InboundShipmentItems: { name: 'InboundShipmentItems', type: 'Complex', required: true, construct: complex.InboundShipmentItems } - }); - } - - }, - - // Inventory - inventory: { - - GetServiceStatus: function() { - return new FbaInventoryRequest('GetServiceStatus', {}); - }, - - ListInventorySupply: function() { - return new FbaInventoryRequest('ListInventorySupply', { - SellerSkus: { name: 'SellerSkus.member', list: true }, - QueryStartDateTime: { name: 'QueryStartDateTime', type: 'Timestamp' }, - ResponseGroup: { name: 'ResponseGroup' } - }); - }, - - ListInventorySupplyByNextToken: function() { - return new FbaInventoryRequest('ListInventorySupplyByNextToken', { - NextToken: { name: 'NextToken', required: true } - }); - } - - }, - - // Outbound Shipments - outbound: { - - GetServiceStatus: function() { - return new FbaOutboundRequest('GetServiceStatus', {}); - }, - - CancelFulfillmentOrder: function() { - return new FbaOutboundRequest('CancelFulfillmentOrder', { - SellerFulfillmentOrderId: { name: 'SellerFulfillmentOrderId', required: true } - }); - }, - - CreateFulfillmentOrder: function() { - return new FbaOutboundRequest('CreateFulfillmentOrder', { - SellerFulfillmentOrderId: { name: 'SellerFulfillmentOrderId', required: true }, - ShippingSpeedCategory: { name: 'ShippingSpeedCategory', required: true, type: 'fba.ShippingSpeedCategory' }, - DisplayableOrderId: { name: 'DisplayableOrder.DisplayableOrderId', required: true }, - DisplayableOrderDateTime: { name: 'DisplayableOrder.DisplayableOrderDateTime', type: 'Timestamp' }, - DisplayableOrderComment: { name: 'DisplayableOrder.DisplayableOrderComment' }, - FulfillmentPolicy: { name: 'FulfillmentPolicy', required: false, type: 'fba.FulfillmentPolicy' }, - FulfillmentMethod: { name: 'FulfillmentMethod', required: false }, - NotificationEmails: { name: 'NotificationEmailList.member', required: false, list: true }, - DestName: { name: 'DestinationAddress.Name' }, - DestAddressLine1: { name: 'DestinationAddress.Line1' }, - DestAddressLine2: { name: 'DestinationAddress.Line2' }, - DestAddressLine3: { name: 'DestinationAddress.Line3' }, - DestCity: { name: 'DestinationAddress.City' }, - DestStateOrProvince: { name: 'DestinationAddress.StateOrProvinceCode' }, - DestPostalCode: { name: 'DestinationAddress.PostalCode' }, - DestCountryCode: { name: 'DestinationAddress.CountryCode' }, - DestDistrictOrCounty: { name: 'DestinationAddress.DistrictOrCounty' }, - DestPhoneNumber: { name: 'DestinationAddress.PhoneNumber' }, - LineItems: { name: 'LineItems', type: 'Complex', required: true, construct: complex.CreateLineItems } - }); - }, - - GetFulfillmentOrder: function() { - return new FbaOutboundRequest('GetFulfillmentOrder', { - SellerFulfillmentOrderId: { name: 'SellerFulfillmentOrderId', required: true } - }); - }, - - GetFulfillmentPreview: function() { - return new FbaOutboundRequest('GetFulfillmentPreview', { - ToName: { name: 'Address.Name' }, - ToAddressLine1: { name: 'Address.Line1' }, - ToAddressLine2: { name: 'Address.Line2' }, - ToAddressLine3: { name: 'Address.Line3' }, - ToCity: { name: 'Address.City' }, - ToStateOrProvince: { name: 'Address.StateOrProvinceCode' }, - ToPostalCode: { name: 'Address.PostalCode' }, - ToCountry: { name: 'Address.CountryCode' }, - ToDistrictOrCounty: { name: 'Address.DistrictOrCounty' }, - ToPhoneNumber: { name: 'Address.PhoneNumber' }, - LineItems: { name: 'LineItems', type: 'Complex', required: true, construct: complex.PreviewLineItems }, - ShippingSpeeds: { name: 'ShippingSpeedCategories.member', list: true, type: 'fba.ShippingSpeedCategory' } - }); - }, - - ListAllFulfillmentOrders: function() { - return new FbaOutboundRequest('ListAllFulfillmentOrders', { - QueryStartDateTime: { name: 'QueryStartDateTime', required: true, type: 'Timestamp' }, - FulfillentMethods: { name: 'FulfillmentMethod.member', list: true } - }); - }, - - ListAllFulfillmentOrdersByNextToken: function() { - return new FbaOutboundRequest('ListAllFulfillmentOrdersByNextToken', { - NextToken: { name: 'NextToken', required: true } - }); - } - - } - -}; +// Generated by CoffeeScript 1.6.3 +(function() { + var Address_Base, FBAInboundClient, FBAInventoryClient, FBAOutboundClient, MWS_FBA_INBOUND, MWS_FBA_INVENTORY, MWS_FBA_OUTBOUND, complex, enums, mws, requests, types, _ref, _ref1, _ref2, + __hasProp = {}.hasOwnProperty, + __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }; + + mws = require('./core'); + + MWS_FBA_INBOUND = new mws.Service({ + name: 'Fulfillment', + group: 'Inbound Shipments', + path: '/FulfillmentInboundShipment/2010-10-01', + version: '2010-10-01', + legacy: false + }); + + MWS_FBA_OUTBOUND = new mws.Service({ + name: 'Fulfillment', + group: 'Outbound Shipments', + path: '/FulfillmentOutboundShipment/2010-10-01', + version: '2010-10-01', + legacy: false + }); + + MWS_FBA_INVENTORY = new mws.Service({ + name: 'Fulfillment', + group: 'Inventory', + path: '/FulfillmentInventory/2010-10-01', + version: '2010-10-01', + legacy: false + }); + + complex = { + DisplayableOrder: (function(_super) { + __extends(_Class, _super); + + function _Class(name, required, init) { + this.name = name != null ? name : 'DisplayableOrder'; + this.required = required != null ? required : false; + this.params = { + id: new mws.Param('DisplayableOrderId', true), + dateTime: new mws.Timestamp('DisplayableOrderDateTime', false), + comment: new mws.Param('DisplayableOrderComment', false) + }; + if (init != null) { + this.set(init); + } + } + + return _Class; + + })(mws.ComplexParam), + Address: Address_Base = (function(_super) { + __extends(Address_Base, _super); + + function Address_Base(name, required, init) { + this.name = name != null ? name : 'Address'; + this.required = required != null ? required : false; + this.params = { + name: new mws.Param('Name', true), + line1: new mws.Param('Line1', true), + line2: new mws.Param('Line2', false), + line3: new mws.Param('Line3', false), + city: new mws.Param('City', true), + county: new mws.Param('DistrictOrCounty', false), + state: new mws.Param('StateOrProvinceCode', true), + zip: new mws.Param('PostalCode', true), + country: new mws.Param('CountryCode', true), + phone: new mws.Param('PhoneNumber', false) + }; + if (init != null) { + this.set(init); + } + } + + return Address_Base; + + })(mws.ComplexParam), + DestinationAddress: (function(_super) { + __extends(_Class, _super); + + function _Class(required, init) { + _Class.__super__.constructor.call(this, 'DestinationAddress', required, init); + } + + return _Class; + + })(Address_Base), + ShipFromAddress: (function(_super) { + __extends(_Class, _super); + + function _Class(required, init) { + this.required = required != null ? required : false; + this.name = 'ShipFromAddress'; + this.params = { + name: new mws.Param('Name', true), + line1: new mws.Param('AddressLine1', true), + line2: new mws.Param('AddressLine2', false), + city: new mws.Param('City', true), + county: new mws.Param('DistrictOrCounty', false), + state: new mws.Param('StateOrProvinceCode', true), + zip: new mws.Param('PostalCode', true), + country: new mws.Param('CountryCode', true) + }; + if (init != null) { + this.set(init); + } + } + + return _Class; + + })(mws.ComplexParam), + InboundShipmentHeader: (function(_super) { + __extends(_Class, _super); + + function _Class(required, init) { + this.required = required != null ? required : false; + this.name = 'InboundShipmentHeader'; + this.params = { + shipmentName: new mws.Param('ShipmentName', true), + shipFromAddress: new complex.ShipFromAddress(true), + destFCID: new mws.Param('DestinationFulfillmentCenterId', true), + shipmentStatus: new mws.Param('ShipmentStatus', false), + labelPrepPref: new mws.Param('LabelPrepPreference', false) + }; + } + + return _Class; + + })(mws.ComplexParam), + LineItem: (function(_super) { + __extends(_Class, _super); + + function _Class(required, init) { + this.required = required != null ? required : false; + this.params = { + comment: new mws.Param('DisplayableComment'), + giftMessage: new mws.Param('GiftMessage'), + declaredValue: new mws.Param('PerUnitDeclaredValue.Value'), + declaredCurrency: new mws.Param('PerUnitDeclaredValue.CurrencyCode'), + quantity: new mws.Param('Quantity'), + itemId: new mws.Param('SellerFulfillmentOrderItemId'), + sku: new mws.Param('SellerSKU') + }; + if (init != null) { + this.set(init); + } + } + + return _Class; + + })(mws.ComplexParam), + LineItems: (function(_super) { + __extends(_Class, _super); + + function _Class(init) { + _Class.__super__.constructor.call(this, 'Items', 'member'); + } + + _Class.prototype.addItem = function(itemId, sku, quantity, declaredValue, declaredCurrency, giftMessage, comment) { + if (arguments.length === 1 && typeof itemId === 'object') { + if (itemId.render != null) { + return this.value.push(itemId); + } else { + return this.value.push(new complex.LineItem(itemId)); + } + } else { + return this.value.push(new complex.LineItem({ + itemId: itemId, + sku: sku, + quantity: quantity, + declaredValue: declaredValue, + declaredCurrency: declaredCurrency, + giftMessage: giftMessage, + comment: comment + })); + } + }; + + return _Class; + + })(mws.ComplexList), + InboundShipmentItem: (function(_super) { + __extends(_Class, _super); + + function _Class(init) { + this.params = { + quantity: new mws.Param('QuantityShipped'), + sku: new mws.Param('SellerSKU') + }; + if (init != null) { + this.set(init); + } + } + + return _Class; + + })(mws.ComplexParam), + InboundShipmentItems: (function(_super) { + __extends(_Class, _super); + + function _Class(required, init) { + _Class.__super__.constructor.call(this, 'InboundShipmentItems', 'member', required, init); + } + + _Class.prototype.addItem = function(quantity, sku) { + if (arguments.length === 1 && typeof quantity === 'object') { + if (quantity.render != null) { + this.value.push(itemId); + } else { + this.value.push(new complex.InboundShipmentItem(quantity)); + } + } + return this.value.push(new complex.InboundShipmentItem({ + quantity: quantity, + sku: sku + })); + }; + + return _Class; + + })(mws.ComplexList), + InboundShipmentPlanRequestItem: (function(_super) { + __extends(_Class, _super); + + function _Class(init) { + this.params = { + quantity: new mws.Param('Quantity'), + sku: new mws.Param('SellerSKU'), + asin: new mws.Param('ASIN'), + condition: new mws.Param('Condition') + }; + if (init != null) { + this.set(init); + } + } + + return _Class; + + })(mws.ComplexParam), + InboundShipmentPlanRequestItems: (function(_super) { + __extends(_Class, _super); + + function _Class(required, init) { + _Class.__super__.constructor.call(this, 'InboundShipmentPlanRequestItems', 'member', required, init); + } + + _Class.prototype.addItem = function(quantity, sku, asin, condition) { + if (arguments.length === 1 && typeof quantity === 'object') { + if (quantity.render != null) { + this.value.push(itemId); + } else { + this.value.push(new complex.InboundShipmentPlanRequestItem(quantity)); + } + } + return this.value.push(new complex.InboundShipmentPlanRequestItem({ + quantity: quantity, + sku: sku, + asin: asin, + condition: condition + })); + }; + + return _Class; + + })(mws.ComplexList) + }; + + enums = { + ResponseGroup: (function(_super) { + __extends(_Class, _super); + + function _Class(options) { + var _ref; + if (options == null) { + options = {}; + } + _Class.__super__.constructor.call(this, 'ResponseGroup', ['Basic', 'Detailed'], (_ref = options.required) != null ? _ref : false); + } + + return _Class; + + })(mws.Enum), + ShippingSpeedCategory: (function(_super) { + __extends(_Class, _super); + + function _Class(options) { + var _ref; + if (options == null) { + options = {}; + } + _Class.__super__.constructor.call(this, 'ShippingSpeedCategory', ['Standard', 'Expedited', 'Priority'], (_ref = options.required) != null ? _ref : false); + } + + return _Class; + + })(mws.Enum), + ShippingSpeedCategories: (function(_super) { + __extends(_Class, _super); + + function _Class(options) { + var _ref; + if (options == null) { + options = {}; + } + _Class.__super__.constructor.call(this, 'ShippingSpeedCategories', 'member', ['Standard', 'Expedited', 'Priority'], (_ref = options.required) != null ? _ref : false); + } + + return _Class; + + })(mws.EnumList), + FulfillmentPolicy: (function(_super) { + __extends(_Class, _super); + + function _Class(options) { + var _ref; + if (options == null) { + options = {}; + } + _Class.__super__.constructor.call(this, 'FulfillmentPolicy', ['FillOrKill', 'FillAll', 'FillAllAvailable'], (_ref = options.required) != null ? _ref : false); + } + + return _Class; + + })(mws.Enum) + }; + + types = { + ServiceStatus: mws.types.ServiceStatus + }; + + requests = { + inbound: { + GetServiceStatus: (function(_super) { + __extends(_Class, _super); + + function _Class(init) { + _Class.__super__.constructor.call(this, MWS_FBA_INBOUND, 'GetServiceStatus', [], {}, null, init); + } + + return _Class; + + })(mws.Request), + CreateInboundShipment: (function(_super) { + __extends(_Class, _super); + + function _Class(init) { + _Class.__super__.constructor.call(this, MWS_FBA_INBOUND, 'CreateInboundShipment', [new mws.Param('ShipmentId', true), new complex.InboundShipmentHeader(true), new complex.InboundShipmentItems(true)], {}, null, init); + } + + return _Class; + + })(mws.Request), + CreateInboundShipmentPlan: (function(_super) { + __extends(_Class, _super); + + function _Class(init) { + _Class.__super__.constructor.call(this, MWS_FBA_INBOUND, 'CreateInboundShipmentPlan', [new mws.Param('LabelPrepPreference', true), new mws.Param(new mws.Param), new complex.ShipFromAddress(true), new mws.Param('InboundShipmentPlanRequestItems', true)], {}, null, init); + } + + return _Class; + + })(mws.Request), + ListInboundShipmentItems: (function(_super) { + __extends(_Class, _super); + + function _Class(init) { + _Class.__super__.constructor.call(this, MWS_FBA_INBOUND, 'ListInboundShipmentItems', [ + new mws.Param('ShipmentId', { + required: true + }), new mws.Timestamp('LastUpdatedAfter'), new mws.Timestamp('LastUpdatedBefore') + ], {}, null, init); + } + + return _Class; + + })(mws.Request), + ListInboundShipmentItemsByNextToken: (function(_super) { + __extends(_Class, _super); + + function _Class(init) { + _Class.__super__.constructor.call(this, MWS_FBA_INBOUND, 'ListInboundShipmentItemsByNextToken', [new mws.Param('NextToken', true)], {}, null, init); + } + + return _Class; + + })(mws.Request), + ListInboundShipments: (function(_super) { + __extends(_Class, _super); + + function _Class(init) { + _Class.__super__.constructor.call(this, MWS_FBA_INBOUND, 'ListInboundShipments', [new mws.ParamList('ShipmentStatusList', 'member'), new mws.ParamList('ShipmentIdList', 'member'), new mws.Timestamp('LastUpdatedAfter'), new mws.Timestamp('LastUpdatedBefore')], {}, null, init); + } + + return _Class; + + })(mws.Request), + ListInboundShipmentsByNextToken: (function(_super) { + __extends(_Class, _super); + + function _Class(init) { + _Class.__super__.constructor.call(this, MWS_FBA_INBOUND, 'ListInboundShipmentsByNextToken', [new mws.Param('NextToken', true)], {}, null, init); + } + + return _Class; + + })(mws.Request), + UpdateInboundShipment: (function(_super) { + __extends(_Class, _super); + + function _Class(init) { + _Class.__super__.constructor.call(this, MWS_FBA_INBOUND, 'UpdateInboundShipment', [new mws.Param('ShipmentId', true), new complex.InboundShipmentHeader(true), new complex.InboundShipmentItems(true)], {}, null, init); + } + + return _Class; + + })(mws.Request) + }, + outbound: { + GetServiceStatus: (function(_super) { + __extends(_Class, _super); + + function _Class(init) { + _Class.__super__.constructor.call(this, MWS_FBA_OUTBOUND, 'GetServiceStatus', [], {}, null, init); + } + + return _Class; + + })(mws.Request), + CancelFulfillmentOrder: (function(_super) { + __extends(_Class, _super); + + function _Class(init) { + _Class.__super__.constructor.call(this, MWS_FBA_OUTBOUND, 'CancelFulfillmentOrder', [new mws.Param('SellerFulfillmentOrderId', true)], {}, null, init); + } + + return _Class; + + })(mws.Request), + CreateFulfillmentOrder: (function(_super) { + __extends(_Class, _super); + + function _Class(init) { + _Class.__super__.constructor.call(this, MWS_FBA_OUTBOUND, 'CreateFulfillmentOrder', [ + new mws.Param('SellerFulfillmentOrderId', true), new enums.ShippingSpeedCategory({ + required: true + }), new enums.FulfillmentPolicy(), new mws.Param('FulfillmentMethod'), new mws.ParamList('NotificationEmailList', 'member'), new complex.DestinationAddress(), new complex.LineItems() + ], {}, null, init); + } + + return _Class; + + })(mws.Request), + GetFulfillmentOrder: (function(_super) { + __extends(_Class, _super); + + function _Class(init) { + _Class.__super__.constructor.call(this, MWS_FBA_OUTBOUND, 'GetFulfillmentOrder', [new mws.Param('SellerFulfillmentOrderId', true)], {}, null, init); + } + + return _Class; + + })(mws.Request), + GetFulfillmentPreview: (function(_super) { + __extends(_Class, _super); + + function _Class(init) { + _Class.__super__.constructor.call(this, MWS_FBA_OUTBOUND, 'GetFulfillmentPreview', [new complex.Address('Address'), new complex.LineItems('LineItems'), new enums.ShippingSpeedCategories()], {}, null, init); + } + + return _Class; + + })(mws.Request), + ListAllFulfillmentOrders: (function(_super) { + __extends(_Class, _super); + + function _Class(init) { + _Class.__super__.constructor.call(this, MWS_FBA_OUTBOUND, 'ListAllFulfillmentOrders', [new mws.Timestamp('QueryStartDateTime', true), new mws.ParamList('FulfillmentMethod', 'member')], {}, null, init); + } + + return _Class; + + })(mws.Request), + ListAllFulfillmentOrdersByNextToken: (function(_super) { + __extends(_Class, _super); + + function _Class(init) { + _Class.__super__.constructor.call(this, MWS_FBA_OUTBOUND, 'ListAllFulfillmentOrdersByNextToken', [new mws.Param('NextToken', true)], {}, null, init); + } + + return _Class; + + })(mws.Request) + }, + inventory: { + GetServiceStatus: (function(_super) { + __extends(_Class, _super); + + function _Class(init) { + _Class.__super__.constructor.call(this, MWS_FBA_INVENTORY, 'GetServiceStatus', [], {}, null, init); + } + + return _Class; + + })(mws.Request), + ListInventorySupply: (function(_super) { + __extends(_Class, _super); + + function _Class(init) { + _Class.__super__.constructor.call(this, MWS_FBA_INVENTORY, 'ListInventorySupply', [new mws.ParamList('SellerSkus', 'member'), new mws.Timestamp('QueryStartDateTime'), new enums.ResponseGroup()], {}, null, init); + } + + return _Class; + + })(mws.Request), + ListInventorySupplyByNextToken: (function(_super) { + __extends(_Class, _super); + + function _Class(init) { + _Class.__super__.constructor.call(this, MWS_FBA_INVENTORY, 'ListInventorySupplyByNextToken', [new mws.Param('NextToken', true)], {}, null, init); + } + + return _Class; + + })(mws.Request) + } + }; + + FBAInboundClient = (function(_super) { + __extends(FBAInboundClient, _super); + + function FBAInboundClient() { + _ref = FBAInboundClient.__super__.constructor.apply(this, arguments); + return _ref; + } + + FBAInboundClient.prototype.getServiceStatus = function(cb) { + var _this = this; + return this.invoke(new requests.inbound.GetServiceStatus(), {}, function(res) { + var status, _ref1, _ref2; + status = (_ref1 = (_ref2 = res.result) != null ? _ref2.Status : void 0) != null ? _ref1 : null; + return cb(status, res); + }); + }; + + FBAInboundClient.prototype.listInboundShipments = function(options, cb) { + var req; + if (options.ShipmentStatusList && options.ShipmentIdList) { + req = new requests.inbound.ListInboundShipments(options); + return this.invoke(req, { + nextTokenCall: requests.ListInboundShipmentsByNextToken + }, function(res) { + var shipments, _ref1, _ref2; + shipments = (_ref1 = (_ref2 = res.result) != null ? _ref2.ShipmentData : void 0) != null ? _ref1 : null; + if (typeof cb === 'function') { + return cb(shipments, res); + } + }); + } else { + throw 'Special Case: requires either ShipmentStatusList list or ShipmentIdList list be used!'; + } + }; + + FBAInboundClient.prototype.listInboundShipmentItems = function(options, cb) { + var req; + if (options.ShipmentId || (options.LastUpdatedAfter && options.LastUpdatedBefore)) { + req = new requests.inbound.ListInboundShipmentItems(options); + return this.invoke(req, { + nextTokenCall: requests.ListInboundShipmentItemsByNextToken + }, function(res) { + var items, _ref1, _ref2; + items = (_ref1 = (_ref2 = res.result) != null ? _ref2.ItemData : void 0) != null ? _ref1 : null; + if (typeof cb === 'function') { + return cb(items, res); + } + }); + } else { + throw 'Special Case: requires either ShipmentId number or LastUpdatedAfter and LastUpdatedBefore timestamps be used!'; + } + }; + + return FBAInboundClient; + + })(mws.Client); + + FBAOutboundClient = (function(_super) { + __extends(FBAOutboundClient, _super); + + function FBAOutboundClient() { + _ref1 = FBAOutboundClient.__super__.constructor.apply(this, arguments); + return _ref1; + } + + FBAOutboundClient.prototype.getServiceStatus = function(cb) { + var _this = this; + return this.invoke(new requests.outbound.GetServiceStatus(), {}, function(res) { + var status, _ref2, _ref3; + status = (_ref2 = (_ref3 = res.result) != null ? _ref3.Status : void 0) != null ? _ref2 : null; + if (typeof cb === 'function') { + return cb(status, res); + } + }); + }; + + return FBAOutboundClient; + + })(mws.Client); + + FBAInventoryClient = (function(_super) { + __extends(FBAInventoryClient, _super); + + function FBAInventoryClient() { + _ref2 = FBAInventoryClient.__super__.constructor.apply(this, arguments); + return _ref2; + } + + FBAInventoryClient.prototype.getServiceStatus = function(cb) { + var _this = this; + return this.invoke(new requests.inventory.GetServiceStatus(), {}, function(res) { + var status, _ref3, _ref4; + status = (_ref3 = (_ref4 = res.result) != null ? _ref4.Status : void 0) != null ? _ref3 : null; + if (typeof cb === 'function') { + return cb(status, res); + } + }); + }; + + FBAInventoryClient.prototype.listInventorySupply = function(options, cb) { + var req; + if (options.SellerSkus && !options.QueryStartDateTime || options.QueryStartDateTime) { + req = new requests.inventory.ListInventorySupply(options); + return this.invoke(req, { + nextTokenCall: requests.ListInventorySupplyByNextToken + }, function(res) { + var inventory, _ref3, _ref4; + inventory = (_ref3 = (_ref4 = res.result) != null ? _ref4.InventorySupplyList : void 0) != null ? _ref3 : null; + if (typeof cb === 'function') { + return cb(inventory, res); + } + }); + } else { + throw 'Special Case: requires EXCLUSIVELY either SellerSkus list or QueryStartDateTime timestamp be used!'; + } + }; + + return FBAInventoryClient; + + })(mws.Client); + + module.exports = { + inbound: { + service: MWS_FBA_INBOUND, + requests: requests.inbound, + Client: FBAInboundClient + }, + outbound: { + service: MWS_FBA_OUTBOUND, + requests: requests.outbound, + Client: FBAOutboundClient + }, + inventory: { + service: MWS_FBA_INVENTORY, + requests: requests.inventory, + Client: FBAInventoryClient + }, + complex: complex, + types: types, + requests: requests + }; + +}).call(this); diff --git a/lib/feeds.js b/lib/feeds.js index 69db95b..a7d5322 100644 --- a/lib/feeds.js +++ b/lib/feeds.js @@ -1,109 +1,349 @@ -/** - * Feeds API requests and definitions for Amazon's MWS web services. - * For information on using, please see examples folder. - * - * @author Robert Saunders - */ -var mws = require('./mws'); - -/** - * Construct a Feeds API request for mws.Client.invoke() - * - * @param {String} action Action parameter of request - * @param {Object} params Schemas for all supported parameters - */ -function FeedsRequest(action, params) { - var opts = { - name: 'Feeds', - group: 'Feeds', - path: '/', - version: '2009-01-01', - legacy: true, - action: action, - params: params - }; - return new mws.Request(opts); -} - -/** - * Ojects to represent enum collections used by some request(s) - * @type {Object} - */ -var enums = exports.enums = { - - FeedProcessingStatuses: function() { - return new mws.Enum(['_SUBMITTED_', '_IN_PROGRESS_', '_CANCELLED_', '_DONE_']); - }, - - FeedTypes: function() { - return new mws.Enum([ - '_POST_PRODUCT_DATA_', '_POST_PRODUCT_RELATIONSHIP_DATA_', '_POST_ITEM_DATA_', '_POST_PRODUCT_OVERRIDES_DATA_', '_POST_PRODUCT_IMAGE_DATA_', - '_POST_PRODUCT_PRICING_DATA_', '_POST_INVENTORY_AVAILABILITY_DATA_', '_POST_ORDER_ACKNOWLEDGEMENT_DATA_', '_POST_ORDER_FULFILLMENT_DATA_', - '_POST_FULFILLMENT_ORDER_REQUEST_DATA_', '_POST_FULFILLMENT_ORDER_CANCELLATION', '_POST_PAYMENT_ADJUSTMENT_DATA_', '_POST_INVOICE_CONFIRMATION_DATA_', - '_POST_FLAT_FILE_LISTINGS_DATA_', '_POST_FLAT_FILE_ORDER_ACKNOWLEDGEMENT_DATA_', '_POST_FLAT_FILE_FULFILLMENT_DATA_', - '_POST_FLAT_FILE_FBA_CREATE_INBOUND_SHIPMENT_', '_POST_FLAT_FILE_FBA_UPDATE_INBOUND_SHIPMENT_', '_POST_FLAT_FILE_PAYMENT_ADJUSTMENT_DATA_', - '_POST_FLAT_FILE_INVOICE_CONFIRMATION_DATA_', '_POST_FLAT_FILE_INVLOADER_DATA_', '_POST_FLAT_FILE_CONVERGENCE_LISTINGS_DATA_', - '_POST_FLAT_FILE_BOOKLOADER_DATA_', '_POST_FLAT_FILE_LISTINGS_DATA_', '_POST_FLAT_FILE_PRICEANDQUANTITYONLY', '_POST_UIEE_BOOKLOADER_DATA_' - ]); - } +// Generated by CoffeeScript 1.6.3 +(function() { + var FeedsClient, MWS_FEEDS, enums, fs, mws, requests, types, _ref, + __hasProp = {}.hasOwnProperty, + __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }, + __indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; }, + __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }; -}; - -/** - * A collection of currently supported request constructors. Once created and - * configured, the returned requests can be passed to an mws client `invoke` call - * @type {Object} - */ -var calls = exports.requests = { - - CancelFeedSubmissions: function() { - return new FeedsRequest('CancelFeedSubmissions', { - FeedSubmissionIds: { name: 'FeedSubmissionIdList.Id', list: true, required: false }, - FeedTypes: { name: 'FeedTypeList.Type', list: true}, - SubmittdFrom: { name: 'SubmittedFromDate', type: 'Timestamp' }, - SubmittedTo: { name: 'SubmittedToDate', type: 'Timestamp' } - }); - }, + fs = require('fs'); - GetFeedSubmissionList: function() { - return new FeedsRequest('GetFeedSubmissionList', { - FeedSubmissionIds: { name: 'FeedSubmissionIdList.Id', list: true, required: false }, - MaxCount: { name: 'MaxCount' }, - FeedTypes: { name: 'FeedTypeList.Type', list: true}, - FeedProcessingStatuses: { name: 'FeedProcessingStatusList.Status', list: true, type: 'bde.FeedProcessingStatuses' }, - SubmittedFrom: { name: 'SubmittedFromDate', type: 'Timestamp' }, - SubmittedTo: { name: 'SubmittedToDate', type: 'Timestamp' } - }); - }, + mws = require("./core"); - GetFeedSubmissionListByNextToken: function() { - return new FeedsRequest('GetFeedSubmissionListByNextToken', { - NextToken: { name: 'NextToken', required: true } - }); - }, + MWS_FEEDS = new mws.Service({ + name: "Feeds", + group: "Feeds", + path: "/", + version: "2009-01-01", + legacy: true + }); - GetFeedSubmissionCount: function() { - return new FeedsRequest('GetFeedSubmissionCount', { - FeedTypes: { name: 'FeedTypeList.Type', list: true}, - FeedProcessingStatuses: { name: 'FeedProcessingStatusList.Status', list: true, type: 'bde.FeedProcessingStatuses' }, - SubmittedFrom: { name: 'SubmittedFromDate', type: 'Timestamp' }, - SubmittedTo: { name: 'SubmittedToDate', type: 'Timestamp' } - }); + types = { + FeedTypes: { + XML: ['_POST_PRODUCT_DATA_', '_POST_PRODUCT_RELATIONSHIP_DATA_', '_POST_ITEM_DATA_', '_POST_PRODUCT_OVERRIDES_DATA_', '_POST_PRODUCT_IMAGE_DATA_', '_POST_PRODUCT_PRICING_DATA_', '_POST_INVENTORY_AVAILABILITY_DATA_', '_POST_ORDER_ACKNOWLEDGEMENT_DATA_', '_POST_ORDER_FULFILLMENT_DATA_', '_POST_FULFILLMENT_ORDER_REQUEST_DATA_', '_POST_FULFILLMENT_ORDER_CANCELLATION_REQUEST_DATA_', '_POST_PAYMENT_ADJUSTMENT_DATA_'], + Flat: ['_POST_FLAT_FILE_LISTINGS_DATA_', '_POST_FLAT_FILE_ORDER_ACKNOWLEDGEMENT_DATA_', '_POST_FLAT_FILE_FULFILLMENT_DATA_', '_POST_FLAT_FILE_PAYMENT_ADJUSTMENT_DATA_', '_POST_FLAT_FILE_INVLOADER_DATA_', '_POST_FLAT_FILE_CONVERGENCE_LISTINGS_DATA_', '_POST_FLAT_FILE_BOOKLOADER_DATA_', '_POST_FLAT_FILE_PRICEANDQUANTITYONLY_UPDATE_DATA_'], + Other: ['_POST_UIEE_BOOKLOADER_DATA_'] }, - - GetFeedSubmissionResult: function() { - return new FeedsRequest('GetFeedSubmissionResult', { - FeedSubmissionId: { name: 'FeedSubmissionId', required: true } - }); + FeedTypeFormats: { + _POST_PRODUCT_DATA_: 'XML', + _POST_PRODUCT_RELATIONSHIP_DATA_: 'XML', + _POST_ITEM_DATA_: 'XML', + _POST_PRODUCT_OVERRIDES_DATA_: 'XML', + _POST_PRODUCT_IMAGE_DATA_: 'XML', + _POST_PRODUCT_PRICING_DATA_: 'XML', + _POST_INVENTORY_AVAILABILITY_DATA_: 'XML', + _POST_ORDER_ACKNOWLEDGEMENT_DATA_: 'XML', + _POST_ORDER_FULFILLMENT_DATA_: 'XML', + _POST_FULFILLMENT_ORDER_REQUEST_DATA_: 'XML', + _POST_FULFILLMENT_ORDER_CANCELLATION_REQUEST_DATA_: 'XML', + _POST_PAYMENT_ADJUSTMENT_DATA_: 'XML', + _POST_FLAT_FILE_LISTINGS_DATA_: 'FlatFile', + _POST_FLAT_FILE_ORDER_ACKNOWLEDGEMENT_DATA_: 'FlatFile', + _POST_FLAT_FILE_FULFILLMENT_DATA_: 'FlatFile', + _POST_FLAT_FILE_PAYMENT_ADJUSTMENT_DATA_: 'FlatFile', + _POST_FLAT_FILE_INVLOADER_DATA_: 'FlatFile', + _POST_FLAT_FILE_CONVERGENCE_LISTINGS_DATA_: 'FlatFile', + _POST_FLAT_FILE_BOOKLOADER_DATA_: 'FlatFile', + _POST_FLAT_FILE_PRICEANDQUANTITYONLY_UPDATE_DATA_: 'FlatFile', + _POST_UIEE_BOOKLOADER_DATA_: 'UIEE' }, + FeedProcessingStatus: { + _SUBMITTED_: 'Submitted', + _IN_PROGRESS_: 'In Progress', + _CANCELLED_: 'Cancelled', + _DONE_: 'Done' + } + }; + + enums = exports.enums = { + FeedProcessingStatus: (function(_super) { + __extends(_Class, _super); + + function _Class(required, init) { + var k, v; + _Class.__super__.constructor.call(this, 'FeedProcessingStatus', (function() { + var _ref, _results; + _ref = types.FeedProcessingStatus; + _results = []; + for (k in _ref) { + v = _ref[k]; + _results.push(k); + } + return _results; + })()); + } + + return _Class; + + })(mws.Enum), + FeedTypeList: (function(_super) { + __extends(_Class, _super); + + function _Class(required, init) { + var k, v; + _Class.__super__.constructor.call(this, 'FeedTypeList', 'Type', (function() { + var _ref, _results; + _ref = types.FeedTypeFormats; + _results = []; + for (k in _ref) { + v = _ref[k]; + _results.push(k); + } + return _results; + })(), required, init); + } + + return _Class; + + })(mws.EnumList), + FeedProcessingStatusList: (function(_super) { + __extends(_Class, _super); + + function _Class(required, init) { + var k, v; + _Class.__super__.constructor.call(this, 'FeedProcessingStatusList', 'Status', (function() { + var _ref, _results; + _ref = types.FeedProcessingStatus; + _results = []; + for (k in _ref) { + v = _ref[k]; + _results.push(k); + } + return _results; + })(), required, init); + } + + return _Class; + + })(mws.EnumList) + }; + + requests = { + GetServiceStatus: (function(_super) { + __extends(_Class, _super); + + function _Class(init) { + _Class.__super__.constructor.call(this, MWS_FEEDS, 'GetServiceStatus', [], {}, null, init); + } + + return _Class; + + })(mws.Request), + CancelFeedSubmissions: (function(_super) { + __extends(_Class, _super); + + function _Class(init) { + _Class.__super__.constructor.call(this, MWS_FEEDS, "CancelFeedSubmissions", [new mws.ParamList('FeedSubmissionIdList', 'Id'), new enums.FeedTypeList(), new mws.Timestamp('SubmittedFromDate'), new mws.Timestamp('SubmittedToDate')], {}, null, init); + } + + return _Class; + + })(mws.Request), + GetFeedSubmissionList: (function(_super) { + __extends(_Class, _super); + + function _Class(init) { + _Class.__super__.constructor.call(this, MWS_FEEDS, "GetFeedSubmissionList", [new mws.ParamList('FeedSubmissionIdList', 'Id'), new mws.Param('MaxCount'), new enums.FeedTypeList(), new enums.FeedProcessingStatusList(), new mws.Timestamp('SubmittedFromDate'), new mws.Timestamp('SubmittedToDate')], {}, null, init); + } + + return _Class; - SubmitFeed: function() { - return new FeedsRequest('SubmitFeed', { - FeedContents: { name: '_BODY_', required: true }, - FeedType: { name: 'FeedType', required: true}, - MarketplaceIds: { name: 'MarketplaceIdList.Id', list: true, required: false }, - PurgeAndReplace: { name: 'PurgeAndReplace', required: false, type: 'Boolean' } - }); + })(mws.Request), + GetFeedSubmissionListByNextToken: (function(_super) { + __extends(_Class, _super); + + function _Class(init) { + _Class.__super__.constructor.call(this, MWS_FEEDS, "GetFeedSubmissionListByNextToken", [new mws.Param('NextToken', true)], {}, null, init); + } + + return _Class; + + })(mws.Request), + GetFeedSubmissionCount: (function(_super) { + __extends(_Class, _super); + + function _Class(init) { + _Class.__super__.constructor.call(this, MWS_FEEDS, "GetFeedSubmissionCount", [new enums.FeedTypeList(), new enums.FeedProcessingStatusList(), new mws.Timestamp('SubmittedFromDate'), new mws.Timestamp('SubmittedToDate')], {}, null, init); + } + + return _Class; + + })(mws.Request), + GetFeedSubmissionResult: (function(_super) { + __extends(_Class, _super); + + function _Class(init) { + _Class.__super__.constructor.call(this, MWS_FEEDS, "GetFeedSubmissionResult", [new mws.Param('FeedSubmissionId', true)], {}, null, init); + } + + return _Class; + + })(mws.Request), + SubmitFeed: (function(_super) { + __extends(_Class, _super); + + function _Class(init, body) { + var _ref; + _Class.__super__.constructor.call(this, MWS_FEEDS, "SubmitFeed", [new mws.Param('FeedType', true), new mws.ParamList('MarketplaceIdList', 'Id'), new mws.Bool('PurgeAndReplace')], {}, (_ref = body != null ? body : init != null ? init.body : void 0) != null ? _ref : null, init); + } + + _Class.prototype.attachFile = function(filename, format, encoding, cb) { + var _ref, + _this = this; + if (format == null) { + if (/\.xml$/gi.test(filename) || (_ref = this.FeedType != null, __indexOf.call(types.FeedTypes.XML, _ref) >= 0)) { + format = "text/xml"; + } else { + format = "text"; + } + } + if (typeof cb === 'function') { + return fs.readFile(filename, encoding, function(err, data) { + if (err) { + throw err; + } else { + return _this.attach(data, format, e); + } + }); + } else { + return this.attach(fs.readFileSync(filename, format)); + } + }; + + return _Class; + + })(mws.Request) + }; + + FeedsClient = (function(_super) { + __extends(FeedsClient, _super); + + function FeedsClient() { + this.submitFeed = __bind(this.submitFeed, this); + _ref = FeedsClient.__super__.constructor.apply(this, arguments); + return _ref; } -}; \ No newline at end of file + FeedsClient.prototype.getServiceStatus = function(cb) { + var _this = this; + return this.invoke(new requests.GetServiceStatus(), {}, function(res) { + var status, _ref1, _ref2; + status = (_ref1 = (_ref2 = res.result) != null ? _ref2.Status : void 0) != null ? _ref1 : null; + if (typeof cb === 'function') { + return cb(status, res); + } + }); + }; + + FeedsClient.prototype.cancelFeedSubmissions = function(submissionIds, feedTypes, submittedFrom, submittedTo, cb) { + var req, + _this = this; + req = new requests.CancelFeedSubmissions({ + FeedSubmissionIdList: submissionIds != null ? submissionIds : [], + FeedTypeList: feedTypes != null ? feedTypes : [], + SubmittedFromDate: submittedFrom, + SubmittedToDate: submittedTo + }); + return this.invoke(req, {}, function(res) { + if (typeof cb === 'function') { + return cb(res); + } + }); + }; + + FeedsClient.prototype.getFeedSubmissionList = function(options, cb) { + var req, + _this = this; + if (options == null) { + options = {}; + } + req = new requests.GetFeedSubmissionList(options); + return this.invoke(req, { + nextTokenCall: requests.GetFeedSubmissionListByNextToken + }, function(res) { + if (typeof cb === 'function') { + return cb(res); + } + }); + }; + + FeedsClient.prototype.getFeedSubmissionListByNextToken = function(token, cb) { + var req, + _this = this; + req = new requests.GetFeedSubmissionListByNextToken({ + NextToken: token + }); + return this.invoke(req, { + nextTokenCall: requests.GetFeedSubmissionListByNextToken + }, function(res) { + if (typeof cb === 'function') { + return cb(res); + } + }); + }; + + FeedsClient.prototype.getFeedSubmissionCount = function(feedTypes, statusList, submittedFrom, submittedTo, cb) { + var req, + _this = this; + req = new requests.GetFeedSubmissionCount({ + FeedTypeList: feedTypes, + FeedProcessingStatusList: statusList, + SubmittedFromDate: submittedFrom, + SubmittedToDate: submittedTo + }); + return this.invoke(req, {}, function(res) { + if (typeof cb === 'function') { + return cb(res); + } + }); + }; + + FeedsClient.prototype.getFeedSubmissionResult = function(id, cb) { + var req, + _this = this; + req = new requests.GetFeedSubmissionResult({ + FeedSubmissionId: id + }); + return this.invoke(req, {}, function(res) { + if (typeof cb === 'function') { + return cb(res); + } + }); + }; + + FeedsClient.prototype.submitFeed = function(feedType, feedBody, marketplaces, purgeReplace, cb) { + var req, _ref1, + _this = this; + if (purgeReplace == null) { + purgeReplace = false; + } + req = new requests.SubmitFeed({ + FeedType: feedType, + MarketplaceIdList: (_ref1 = marketplaces != null ? marketplaces : this.marketplaceIds) != null ? _ref1 : [this.marketplaceId], + PurgeAndReplace: purgeReplace + }, feedBody); + return this.invoke(req, { + method: 'POST', + headers: { + 'Content-Type': 'text/xml' + } + }, function(res) { + if (typeof cb === 'function') { + return cb(res); + } + }); + }; + + return FeedsClient; + + })(mws.Client); + + module.exports = { + service: MWS_FEEDS, + enums: enums, + types: types, + requests: requests, + Client: FeedsClient + }; + +}).call(this); diff --git a/lib/mws.js b/lib/mws.js deleted file mode 100644 index a409315..0000000 --- a/lib/mws.js +++ /dev/null @@ -1,380 +0,0 @@ -var https = require('https'), - qs = require("querystring"), - crypto = require('crypto'), - xml2js = require('xml2js'); - - -var MARKETPLACE_IDS = { - -}; - -/** - * Constructor for the main MWS client interface used to make api calls and - * various data structures to encapsulate MWS requests, definitions, etc. - * - * @param {String} accessKeyId Id for your secret Access Key (required) - * @param {String} secretAccessKey Secret Access Key provided by Amazon (required) - * @param {String} merchantId Aka SellerId, provided by Amazon (required) - * @param {Object} options Additional configuration options for this instance - */ -function AmazonMwsClient(accessKeyId, secretAccessKey, merchantId, options) { - this.host = options.host || 'mws.amazonservices.com'; - this.port = options.port || 443; - this.conn = options.conn || https; - this.creds = crypto.createCredentials(options.creds || {}); - this.appName = options.appName || 'mws-js'; - this.appVersion = options.appVersion || '0.1.0'; - this.appLanguage = options.appLanguage || 'JavaScript'; - this.accessKeyId = accessKeyId || null; - this.secretAccessKey = secretAccessKey || null; - this.merchantId = merchantId || null; -} - -/** - * The method used to invoke calls against MWS Endpoints. Recommended usage is - * through the invoke wrapper method when the api call you're invoking has a - * request defined in one of the submodules. However, you can use call() manually - * when a lower level of control is necessary (custom or new requests, for example). - * - * @param {Object} api Settings object unique to each API submodule - * @param {String} action Api `Action`, such as GetServiceStatus or GetOrder - * @param {Object} query Any parameters belonging to the current action - * @param {Function} callback Callback function to send any results recieved - */ -AmazonMwsClient.prototype.call = function(api, action, query, callback) { - if (this.secretAccessKey == null || this.accessKeyId == null || this.merchantId == null) { - throw("accessKeyId, secretAccessKey, and merchantId must be set"); - } - - // Check if we're dealing with a file (such as a feed) upload - if (api.upload) { - var body = query._BODY_, - bformat = query._FORMAT_; - delete query._BODY_; - delete query._FORMAT_; - } - - // Add required parameters and sign the query - query['Action'] = action; - query['Version'] = api.version; - query["Timestamp"] = (new Date()).toISOString(); - query["AWSAccessKeyId"] = this.accessKeyId; - if (api.legacy) { query['Merchant'] = this.merchantId; } - else { query['SellerId'] = this.merchantId; } - query = this.sign(api.path, query); - - if (!api.upload) { - var body = qs.stringify(query); - } - - // Setup our HTTP headers and connection options - var headers = { - 'Host': this.host, - 'User-Agent': this.appName + '/' + this.appVersion + ' (Language=' + this.appLanguage + ')', - 'Content-Type': bformat || 'application/x-www-form-urlencoded; charset=utf-8', - 'Content-Length': body.length - }; - if (api.upload) { - headers['Content-MD5'] = cryto.createHash('md5').update(body).digest("base64"); - } - var options = { - host: this.host, - port: this.port, - path: api.path + (api.upload ? '?' + qs.stringify(query) : ''), - method: "POST", - headers: headers - }; - - // Make the initial request and define callbacks - var req = this.conn.request(options, function (res) { - var data = ''; - // Append each incoming chunk to data variable - res.addListener('data', function (chunk) { - data += chunk.toString(); - }); - // When response is complete, parse the XML and pass it to callback - res.addListener('end', function() { - var parser = new xml2js.Parser(); - parser.addListener('end', function (result) { - // Throw an error if there was a problem reported - if (result.Error != null) - throw(result.Error.Code + ": " + result.Error.Message); - callback(result); - }); - if (data.slice(0, 5) == '= 0; i--) { - setValue(p.name + '.' + (i+1), value[i]); - } - } else { - for (var key in value) { - setValue(p.name + '.' + (++i), value[key]); - } - } - } - } else { - setValue(p.name, value) - } - - return this; -}; - -/** - * Builds a query object and checks for required parameters. - * - * @return {Object} KvP's of all provided parameters (used by invoke()) - */ -AmazonMwsRequest.prototype.query = function() { - var q = {}; - for (var param in this.params) { - var value = this.params[param].value, - name = this.params[param].name, - complex = (this.params[param].type === 'Complex'); - required = this.params[param].required; - console.log("v " + value + "\nn " + name + "\nr " + required); - if ((value !== undefined) && (value !== null)) { - if (complex) { - value.appendTo(q); - } else { - for (var val in value) { - q[val] = value[val]; - } - } - } else { - if (param.required === true) { - throw("ERROR: Missing required parameter, " + name + "!") - } - } - }; - return q -}; - - -/** - * Contructor for objects used to represent enumeration states. Useful - * when you need to make programmatic updates to an enumerated data type or - * wish to encapsulate enum states in a handy, re-usable variable. - * - * @param {Array} choices An array of any possible values (choices) - */ -function EnumType(choices) { - for (var choice in choices) { - this[choices[choice]] = false; - } - this._choices = choices; -} - -/** - * Enable one or more choices (accepts a variable number of arguments) - * @return {Object} Current instance of EnumType for chaining - */ -EnumType.prototype.enable = function() { - for (var arg in arguments) { - this[arguments[arg]] = true; - } - return this; -}; - -/** - * Disable one or more choices (accepts a variable number of arguments) - * @return {Object} Current instance of EnumType for chaining - */ -EnumType.prototype.disable = function() { - for (var arg in arguments) { - this[arguments[arg]] = false; - } - return this; -}; - -/** - * Toggles one or more choices (accepts a variable number of arguments) - * @return {Object} Current instance of EnumType for chaining - */ -EnumType.prototype.toggle = function() { - for (var arg in arguments) { - this[arguments[arg]] = ! this[arguments[arg]]; - } - return this; -}; - -/** - * Return all possible values without regard to current state - * @return {Array} Choices passed to EnumType constructor - */ -EnumType.prototype.all = function() { - return this._choices; -}; - -/** - * Return all enabled choices as an array (used to set list params, usually) - * @return {Array} Choice values for each choice set to true - */ -EnumType.prototype.values = function() { - var value = []; - for (var choice in this._choices) { - if (this[this._choices[choice]] === true) { - value.push(this._choices[choice]); - } - } - return value; -}; - - -// /** -// * Takes an object and adds an appendTo function that will add -// * each kvp of object to a query. Used when dealing with complex -// * parameters that need to be built in an abnormal or unique way. -// * -// * @param {String} name Name of parameter, prefixed to each key -// * @param {Object} obj Parameters belonging to the complex type -// */ -// function ComplexType(name) { -// this.pre = name; -// var _obj = obj; -// obj.appendTo = function(query) { -// for (var k in _obj) { -// query[name + '.' k] = _obj[k]; -// } -// return query; -// } -// return obj; -// } - -// ComplexType.prototype.appendTo = function(query) { -// for (var k in value) -// } - -/** - * Complex List helper object. Once initialized, you should set - * an add(args) method which pushes a new complex object to members. - * - * @param {String} name Name of Complex Type (including .member or subtype) - */ -function ComplexListType(name) { - this.pre = name; - this.members = []; -} - -/** - * Appends each member object as a complex list item - * @param {Object} query Query object to append to - * @return {Object} query - */ -ComplexListType.prototype.appendTo = function(query) { - var members = this.members; - for (var i = 0; i < members.length; i++) { - for (var j in members[i]) { - query[this.pre + '.' + (i+1) + '.' + j] = members[i][j] - } - } - return query; -}; - -exports.Client = AmazonMwsClient; -exports.Request = AmazonMwsRequest; -exports.Enum = EnumType; -exports.ComplexList = ComplexListType; diff --git a/lib/orders.js b/lib/orders.js index 1f1f7d1..645b0d4 100644 --- a/lib/orders.js +++ b/lib/orders.js @@ -1,154 +1,286 @@ -/** - * Orders API requests and definitions for Amazon's MWS web services. - * For information on using, please see examples folder. - * - * @author Robert Saunders - */ -var mws = require('./mws'); - -/** - * Construct an Orders API request for mws.Client.invoke() - * - * @param {String} action Action parameter of request - * @param {Object} params Schemas for all supported parameters - */ -function OrdersRequest(action, params) { - var opts = { - name: 'Orders', - group: 'Order Retrieval', - path: '/Orders/2011-01-01', - version: '2011-01-01', - legacy: false, - action: action, - params: params - }; - return new mws.Request(opts); -} - -/** - * Ojects to represent enum collections used by some request(s) - * @type {Object} - */ -var enums = exports.enums = { - - FulfillmentChannels: function() { - return new mws.Enum(['AFN', 'MFN']); - }, - - OrderStatuses: function() { - return new mws.Enum(['Pending', 'Unshipped', 'PartiallyShipped', 'Shipped', 'Canceled', 'Unfulfillable']); - }, - - PaymentMethods: function() { - return new mws.Enum(['COD', 'CVS', 'Other']); - } - -}; - -/** - * Contains brief definitions for unique data type values. - * Can be used to explain input/output to users via tooltips, for example - * @type {Object} - */ -var types = exports.types = { - - FulfillmentChannel: { - 'AFN':'Amazon Fulfillment Network', - 'MFN':'Merchant\'s Fulfillment Network' }, - - OrderStatus: { - 'Pending':'Order placed but payment not yet authorized. Not ready for shipment.', - 'Unshipped':'Payment has been authorized. Order ready for shipment, but no items shipped yet. Implies PartiallyShipped.', - 'PartiallyShipped':'One or more (but not all) items have been shipped. Implies Unshipped.', - 'Shipped':'All items in the order have been shipped.', - 'Canceled':'The order was canceled.', - 'Unfulfillable':'The order cannot be fulfilled. Applies only to Amazon-fulfilled orders not placed on Amazon.' }, - - PaymentMethod: { - 'COD':'Cash on delivery', - 'CVS':'Convenience store payment', - 'Other':'Any payment method other than COD or CVS' }, - - ServiceStatus: { - 'GREEN':'The service is operating normally.', - 'GREEN_I':'The service is operating normally + additional info provided', - 'YELLOW':'The service is experiencing higher than normal error rates or degraded performance.', - 'RED':'The service is unabailable or experiencing extremely high error rates.' }, - - ShipServiceLevelCategory: { - 'Expedited':'Expedited shipping', - 'NextDay':'Overnight shipping', - 'SecondDay':'Second-day shipping', - 'Standard':'Standard shipping' } - -}; - -/** - * A collection of currently supported request constructors. Once created and - * configured, the returned requests can be passed to an mws client `invoke` call - * @type {Object} - */ -var calls = exports.requests = { - - /** - * Requests the operational status of the Orders API section. - */ - GetServiceStatus: function() { - return new OrdersRequest('GetServiceStatus', {}); - }, - - /** - * Returns orders created or updated during a time frame you specify. - */ - ListOrders: function() { - return new OrdersRequest('ListOrders', { - CreatedAfter: { name: 'CreatedAfter', type: 'Timestamp' }, - CreatedBefore: { name: 'CreatedBefore', type: 'Timestamp' }, - LastUpdatedAfter: { name: 'LastUpdatedAfter', type: 'Timestamp' }, - MarketplaceId: { name: 'MarketplaceId.Id', list: true, required: true }, - LastUpdatedBefore: { name: 'LastUpdatedBefore', type: 'Timestamp' }, - OrderStatus: { name: 'OrderStatus.Status', type: 'orders.OrderStatuses', list: true }, - FulfillmentChannel: { name: 'FulfillmentChannel.Channel', type: 'orders.FulfillmentChannels', list: true }, - PaymentMethod: { name: 'PaymentMethod.Method', type: 'orders.PaymentMethods', list: true }, - BuyerEmail: { name: 'BuyerEmail' }, - SellerOrderId: { name: 'SellerOrderId' }, - MaxResultsPerPage: { name: 'MaxResultsPerPage' } - }); - }, - - /** - * Returns the next page of orders using the NextToken parameter. - */ - ListOrdersByNextToken: function() { - return new OrdersRequest('ListOrdersByNextToken', { - NextToken: { name: 'NextToken', required: true } - }); - }, - - /** - * Returns orders based on the AmazonOrderId values that you specify. - */ - GetOrder: function() { - return new OrdersRequest('GetOrder', { - AmazonOrderId: { name: 'AmazonOrderId.Id', required: true, list: true } - }); - }, +// Generated by CoffeeScript 1.6.3 +(function() { + var MWS_ORDERS, OrdersClient, enums, mws, requests, types, _ref, + __hasProp = {}.hasOwnProperty, + __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }; + + mws = require('./core'); + + MWS_ORDERS = new mws.Service({ + name: "Orders", + group: "Order Retrieval", + path: "/Orders/2011-01-01", + version: "2011-01-01", + legacy: false + }); + + enums = { + OrderStatus: (function(_super) { + __extends(_Class, _super); + + function _Class() { + var k, v; + _Class.__super__.constructor.call(this, 'OrderStatus', 'Status', (function() { + var _ref, _results; + _ref = types.OrderStatus; + _results = []; + for (k in _ref) { + v = _ref[k]; + _results.push(k); + } + return _results; + })()); + } + + _Class.prototype.render = function(obj) { + if (obj == null) { + obj = {}; + } + if (this.value.Unshipped !== this.value.PartiallyShipped) { + throw "Unshipped & PartiallyShipped must both be enabled on the OrderStatus Param"; + } + return _Class.__super__.render.call(this, obj); + }; + + return _Class; + + })(mws.EnumList), + FulfillmentChannel: (function(_super) { + __extends(_Class, _super); + + function _Class() { + var k, v; + _Class.__super__.constructor.call(this, 'FulfillmentChannel', 'Channel', (function() { + var _ref, _results; + _ref = types.FulfillmentChannel; + _results = []; + for (k in _ref) { + v = _ref[k]; + _results.push(k); + } + return _results; + })()); + } + + return _Class; + + })(mws.EnumList), + PaymentMethod: (function(_super) { + __extends(_Class, _super); - /** - * Returns order items based on the AmazonOrderId that you specify. - */ - ListOrderItems: function() { - return new OrdersRequest('ListOrderItems', { - AmazonOrderId: { name: 'AmazonOrderId', required: true } }); + function _Class() { + var k, v; + _Class.__super__.constructor.call(this, 'PaymentMethod', 'Method', (function() { + var _ref, _results; + _ref = types.PaymentMethod; + _results = []; + for (k in _ref) { + v = _ref[k]; + _results.push(k); + } + return _results; + })()); + } + + return _Class; + + })(mws.EnumList) + }; + + types = { + ServiceStatus: mws.types.ServiceStatus, + FulfillmentChannel: { + AFN: "Amazon Fulfillment Network", + MFN: "Merchant's Fulfillment Network" }, + OrderStatus: { + Pending: "Order placed but payment not yet authorized. Not ready for shipment.", + Unshipped: "Payment has been authorized. Order ready for shipment, but no items shipped yet. Implies PartiallyShipped.", + PartiallyShipped: "One or more (but not all) items have been shipped. Implies Unshipped.", + Shipped: "All items in the order have been shipped.", + Canceled: "The order was canceled.", + Unfulfillable: "The order cannot be fulfilled. Applies only to Amazon-fulfilled orders not placed on Amazon." + }, + PaymentMethod: { + COD: "Cash on delivery", + CVS: "Convenience store payment", + Other: "Any payment method other than COD or CVS" + }, + ShipServiceLevelCategory: { + Expedited: "Expedited shipping", + NextDay: "Overnight shipping", + SecondDay: "Second-day shipping", + Standard: "Standard shipping" + } + }; + + requests = { + GetServiceStatus: (function(_super) { + __extends(_Class, _super); + + function _Class(init) { + _Class.__super__.constructor.call(this, MWS_ORDERS, 'GetServiceStatus', [], {}, null, init); + } + + return _Class; + + })(mws.Request), + ListOrders: (function(_super) { + __extends(_Class, _super); + + function _Class(init) { + _Class.__super__.constructor.call(this, MWS_ORDERS, 'ListOrders', [new mws.Timestamp('CreatedAfter'), new mws.Timestamp('CreatedBefore'), new mws.Timestamp('LastUpdatedAfter'), new mws.Timestamp('LastUpdatedBefore'), new mws.ParamList('MarketplaceId', 'Id', true), new enums.OrderStatus(), new enums.FulfillmentChannel(), new enums.PaymentMethod(), new mws.Param('BuyerEmail'), new mws.Param('SellerOrderId'), new mws.Param('MaxResultsPerPage')], {}, null, init); + } + + return _Class; - /** - * Returns the next page of order items using the NextToken parameter. - */ - ListOrderItemsByNextToken: function() { - return new OrdersRequest('ListOrderItemsByNextToken', { - NextToken: { name: 'NextToken', required: true } - }); + })(mws.Request), + ListOrdersByNextToken: (function(_super) { + __extends(_Class, _super); + + function _Class(init) { + _Class.__super__.constructor.call(this, MWS_ORDERS, 'ListOrdersByNextToken', [new mws.Param('NextToken', true)], {}, null, init); + } + + return _Class; + + })(mws.Request), + GetOrder: (function(_super) { + __extends(_Class, _super); + + function _Class(init) { + _Class.__super__.constructor.call(this, MWS_ORDERS, 'GetOrder', [new mws.ParamList('AmazonOrderId', 'Id', true)], {}, null, init); + } + + return _Class; + + })(mws.Request), + ListOrderItems: (function(_super) { + __extends(_Class, _super); + + function _Class(init) { + _Class.__super__.constructor.call(this, MWS_ORDERS, 'ListOrderItems', [new mws.Param('AmazonOrderId', true)], {}, null, init); + } + + return _Class; + + })(mws.Request), + ListOrderItemsByNextToken: (function(_super) { + __extends(_Class, _super); + + function _Class(init) { + _Class.__super__.constructor.call(this, MWS_ORDERS, 'ListOrderItemsByNextToken', [new mws.Param('NextToken', true)], {}, null, init); + } + + return _Class; + + })(mws.Request) + }; + + OrdersClient = (function(_super) { + __extends(OrdersClient, _super); + + function OrdersClient() { + _ref = OrdersClient.__super__.constructor.apply(this, arguments); + return _ref; } -}; \ No newline at end of file + OrdersClient.prototype.getServiceStatus = function(cb) { + var _this = this; + return this.invoke(new requests.GetServiceStatus(), {}, function(res) { + var status, _ref1, _ref2; + status = (_ref1 = (_ref2 = res.result) != null ? _ref2.Status : void 0) != null ? _ref1 : null; + return cb(status, res); + }); + }; + + OrdersClient.prototype.listOrders = function(options, cb) { + var req, _ref1, + _this = this; + if ((options.CreatedAfter != null) || (options.LastUpdatedAfter != null)) { + if (options.MarketplaceId == null) { + options.MarketplaceId = (_ref1 = this.marketplaceIds) != null ? _ref1 : this.marketplaceId; + } + req = new requests.ListOrders(options); + return this.invoke(req, { + nextTokenCall: requests.ListOrdersByNextToken + }, function(res) { + var orders, _ref2, _ref3, _ref4; + orders = (_ref2 = (_ref3 = res.result) != null ? (_ref4 = _ref3.Orders) != null ? _ref4.Order : void 0 : void 0) != null ? _ref2 : null; + return cb(orders, res); + }); + } else { + throw 'Special Case: requires AT LEAST ONE OF either CreatedAfter or LastUpdatedAfter timestamps be used!'; + } + }; + + OrdersClient.prototype.listOrdersByNextToken = function(token, cb) { + var req, + _this = this; + req = new requests.ListOrdersByNextToken({ + NextToken: token + }); + return this.invoke(req, { + nextTokenCall: requests.ListOrdersByNextToken + }, function(res) { + var orders, _ref1, _ref2, _ref3; + orders = (_ref1 = (_ref2 = res.result) != null ? (_ref3 = _ref2.Orders) != null ? _ref3.Order : void 0 : void 0) != null ? _ref1 : null; + return cb(orders, res); + }); + }; + + OrdersClient.prototype.getOrder = function(orderId, cb) { + var req, + _this = this; + req = new requests.GetOrder({ + AmazonOrderId: orderId + }); + return this.invoke(req, {}, function(res) { + var orders, _ref1, _ref2, _ref3; + orders = (_ref1 = (_ref2 = res.result) != null ? (_ref3 = _ref2.Orders) != null ? _ref3.Order : void 0 : void 0) != null ? _ref1 : null; + return cb(orders, res); + }); + }; + + OrdersClient.prototype.listOrderItems = function(orderId, cb) { + var req, + _this = this; + req = new requests.ListOrderItems({ + AmazonOrderId: orderId + }); + return this.invoke(req, { + nextTokenCall: requests.ListOrderItemsByNextToken + }, function(res) { + var items, _ref1, _ref2, _ref3; + items = (_ref1 = (_ref2 = res.result) != null ? (_ref3 = _ref2.OrderItems) != null ? _ref3.OrderItem : void 0 : void 0) != null ? _ref1 : null; + return cb(items, res); + }); + }; + + OrdersClient.prototype.listOrderItemsByNextToken = function(token, cb) { + var req, + _this = this; + req = new requests.ListOrderItemsByNextToken({ + NextToken: token + }); + return this.invoke(req, { + nextTokenCall: requests.ListOrderItemsByNextToken + }, function(res) { + var items, _ref1, _ref2, _ref3; + items = (_ref1 = (_ref2 = res.result) != null ? (_ref3 = _ref2.OrderItems) != null ? _ref3.OrderItem : void 0 : void 0) != null ? _ref1 : null; + return cb(items, res); + }); + }; + + return OrdersClient; + + })(mws.Client); + + module.exports = { + service: MWS_ORDERS, + enums: enums, + requests: requests, + Client: OrdersClient + }; + +}).call(this); diff --git a/lib/products.js b/lib/products.js index 22beb94..b4428b7 100644 --- a/lib/products.js +++ b/lib/products.js @@ -1,162 +1,330 @@ -/** - * Products API requests and definitions for Amazon's MWS web services. - * For information on using, please see examples folder. - * - * @author Robert Saunders - */ -var mws = require('./mws'); - -/** - * Construct a Products API request for using with mws.Client.invoke() - * - * @param {String} action Action parameter of request - * @param {Object} params Schemas for all supported parameters - */ -function ProductsRequest(action, params) { - var opts = { - name: 'Products', - group: 'Products', - path: '/Products/2011-10-01', - version: '2011-10-01', - legacy: false, - action: action, - params: params - }; - return new mws.Request(opts); -} +// Generated by CoffeeScript 1.6.3 +(function() { + var MWS_PRODUCTS, ProductsClient, enums, mws, requests, types, + __hasProp = {}.hasOwnProperty, + __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }; + + mws = require('./core'); + + MWS_PRODUCTS = new mws.Service({ + name: "Products", + group: "Products", + path: "/Products/2011-10-01", + version: "2011-10-01", + legacy: false + }); + + enums = { + ItemCondition: (function(_super) { + __extends(_Class, _super); + + function _Class() { + _Class.__super__.constructor.call(this, 'ItemCondition', ['New', 'Used', 'Collectible', 'Refurbished', 'Club']); + } -/** - * Ojects to represent enum collections used by some request(s) - * @type {Object} - */ -var enums = exports.enums = { + return _Class; - ItemConditions: function() { - return new mws.Enum([ 'New', 'Used', 'Collectible', 'Refurbished', 'Club' ]); + })(mws.Enum) + }; + + types = { + ServiceStatus: mws.types.ServiceStatus, + MarketplaceId: { + ATVPDKIKX0DER: 'amazon.com', + A1F83G8C2ARO7P: 'amazon.co.uk', + A13V1IB3VIYZZH: 'amazon.fr', + A1PA6795UKMFR9: 'amazon.de', + APJ6JRA9NG5V4: 'amazon.it', + A1RKKUPIHCS9HS: 'amazon.es' } + }; + + requests = { + GetServiceStatus: (function(_super) { + __extends(_Class, _super); + + function _Class(init) { + _Class.__super__.constructor.call(this, MWS_PRODUCTS, 'GetServiceStatus', [], {}, null, init); + } + + return _Class; + + })(mws.Request), + ListMatchingProducts: (function(_super) { + __extends(_Class, _super); + + function _Class(init) { + _Class.__super__.constructor.call(this, MWS_PRODUCTS, 'ListMatchingProducts', [new mws.Param('MarketplaceId', 'Id', true), new mws.Param('Query', true), new mws.Param('QueryContextId', false)], {}, null, init); + } + + return _Class; + + })(mws.Request), + GetMatchingProduct: (function(_super) { + __extends(_Class, _super); + + function _Class(init) { + _Class.__super__.constructor.call(this, MWS_PRODUCTS, 'GetMatchingProduct', [new mws.Param('MarketplaceId', true), new mws.ParamList('ASINList', 'ASIN')], {}, null, init); + } + + return _Class; + + })(mws.Request), + GetMatchingProductForId: (function(_super) { + __extends(_Class, _super); + + function _Class(init) { + _Class.__super__.constructor.call(this, MWS_PRODUCTS, 'GetMatchingProductForId', [new mws.Param('MarketplaceId', true), new mws.Param('IdType', true), new mws.ParamList('IdList', 'Id')], {}, null, init); + } + + return _Class; + + })(mws.Request), + GetCompetitivePricingForSKU: (function(_super) { + __extends(_Class, _super); + + function _Class(init) { + _Class.__super__.constructor.call(this, MWS_PRODUCTS, 'GetCompetitivePricingForSKU', [new mws.Param('MarketplaceId', 'Id', true), new mws.ParamList('SellerSKUList', 'SellerSKU', true)], {}, null, init); + } + + return _Class; + + })(mws.Request), + GetCompetitivePricingForASIN: (function(_super) { + __extends(_Class, _super); + + function _Class(init) { + _Class.__super__.constructor.call(this, MWS_PRODUCTS, 'GetCompetitivePricingForASIN', [new mws.Param('MarketplaceId', 'Id', true), new mws.ParamList('ASINList', 'ASIN')], {}, null, init); + } + + return _Class; + + })(mws.Request), + GetLowestOfferListingsForSKU: (function(_super) { + __extends(_Class, _super); + + function _Class(init) { + _Class.__super__.constructor.call(this, MWS_PRODUCTS, 'GetLowestOfferListingsForSKU', [new mws.Param('MarketplaceId', 'Id', true), new mws.ParamList('SellerSKUList', 'SellerSKU', true), new enums.ItemCondition('ItemCondition')], {}, null, init); + } + + return _Class; + + })(mws.Request), + GetLowestOfferListingsForASIN: (function(_super) { + __extends(_Class, _super); + + function _Class(init) { + _Class.__super__.constructor.call(this, MWS_PRODUCTS, 'GetLowestOfferListingsForASIN', [new mws.Param('MarketplaceId', 'Id', true), new enums.ItemCondition('ItemCondition'), new mws.ParamList('ASINList', 'ASIN')], {}, null, init); + } + + return _Class; + + })(mws.Request), + GetMyPriceForSKU: (function(_super) { + __extends(_Class, _super); + + function _Class(init) { + _Class.__super__.constructor.call(this, MWS_PRODUCTS, 'GetMyPriceForSKU', [new mws.Param('MarketplaceId', 'Id', true), new mws.ParamList('SellerSKUList', 'SellerSKU', true), new enums.ItemCondition('ItemCondition')], {}, null, init); + } + + return _Class; + + })(mws.Request), + GetMyPriceForASIN: (function(_super) { + __extends(_Class, _super); + + function _Class(init) { + _Class.__super__.constructor.call(this, MWS_PRODUCTS, 'GetMyPriceForASIN', [new mws.Param('MarketplaceId', 'Id', true), new enums.ItemCondition('ItemCondition'), new mws.ParamList('ASINList', 'ASIN')], {}, null, init); + } + + return _Class; -}; - -/** - * Contains brief definitions for unique data type values. - * Can be used to explain input/output to users via tooltips, for example - * @type {Object} - */ -var types = exports.types = { - - CompetitivePriceId: { - '1':'New Buy Box Price', - '2':'Used Buy Box Price' }, - - ServiceStatus: { - 'GREEN':'The service is operating normally.', - 'GREEN_I':'The service is operating normally + additional info provided', - 'YELLOW':'The service is experiencing higher than normal error rates or degraded performance.', - 'RED':'The service is unabailable or experiencing extremely high error rates.' }, - -}; - -/** - * A collection of currently supported request constructors. Once created and - * configured, the returned requests can be passed to an mws client `invoke` call - * @type {Object} - */ -var calls = exports.requests = { - - /** - * Requests the operational status of the Products API section. - */ - GetServiceStatus: function() { - return new ProductsRequest('GetServiceStatus', {}); - }, - - /** - * Returns a list of products and their attributes, ordered by relevancy, - * based on a search query that you specify - */ - ListMatchingProducts: function() { - return new ProductsRequest('ListMatchingProducts', { - MarketplaceId: { name: 'MarketplaceId', required: true}, - Query: { name: 'Query', required: true}, - QueryContextId: { name: 'QueryContextId'} - }); - }, - - /** - * Returns a list of products and their attributes, - * based on a list of ASIN values that you specify - */ - GetMatchingProduct: function() { - return new ProductsRequest('GetMatchingProduct', { - MarketplaceId: { name: 'MarketplaceId', required: true}, - ASINList: { name: 'ASINList.ASIN', list: true, required: true} - }); - }, - - /** - * Returns the current competitive pricing of a product, - * based on the SellerSKU and MarketplaceId that you specify - */ - GetCompetitivePricingForSKU: function() { - return new ProductsRequest('GetCompetitivePricingForSKU', { - MarketplaceId: { name: 'MarketplaceId', required: true}, - SellerSKUList: { name: 'SellerSKUList.SellerSKU', list: true, required: true} - }); - }, - - /** - * Same as above, except that it uses a MarketplaceId and an ASIN to uniquely - * identify a product, and it does not return the SKUIdentifier element - */ - GetCompetitivePricingForASIN: function() { - return new ProductsRequest('GetCompetitivePricingForASIN', { - MarketplaceId: { name: 'MarketplaceId', required: true}, - ASINList: { name: 'ASINList.ASIN', list: true, required: true} - }); - }, - - /** - * Returns the lowest price offer listings for a specific product by item condition. - */ - GetLowestOfferListingsForSKU: function() { - return new ProductsRequest('GetLowestOfferListingsForSKU', { - MarketplaceId: { name: 'MarketplaceId', required: true}, - ItemCondition: { name: 'ItemCondition'}, - SellerSKUList: { name: 'SellerSKUList.SellerSKU', list: true, required: true } - }); - }, - - /** - * Same as above but by a list of ASIN's you provide - */ - GetLowestOfferListingsForASIN: function() { - return new ProductsRequest('GetLowestOfferListingsForASIN', { - MarketplaceId: { name: 'MarketplaceId', required: true}, - ItemCondition: { name: 'ItemCondition'}, - ASINList: { name: 'ASINList.ASIN', list: true, required: true} - }); - }, - - /** - * Returns the product categories that a product belongs to, - * including parent categories back to the root for the marketplace - */ - GetProductCategoriesForSKU: function() { - return new ProductsRequest('GetProductCategoriesForSKU', { - MarketplaceId: { name: 'MarketplaceId', required: true}, - SellerSKU: { name: 'SellerSKU', required: true} - }); - }, - - /** - * Same as above, except that it uses a MarketplaceId and an ASIN to - *uniquely identify a product. - */ - GetProductCategoriesForASIN: function() { - return new ProductsRequest('GetProductCategoriesForASIN', { - MarketplaceId: { name: 'MarketplaceId', required: true}, - ASIN: { name: 'ASIN', required: true} - }); + })(mws.Request), + GetProductCategoriesForSKU: (function(_super) { + __extends(_Class, _super); + + function _Class(init) { + _Class.__super__.constructor.call(this, MWS_PRODUCTS, 'GetProductCategoriesForSKU', [new mws.Param('MarketplaceId', 'Id', true), new mws.Param('SellerSKU', true)], {}, null, init); + } + + return _Class; + + })(mws.Request), + GetProductCategoriesForASIN: (function(_super) { + __extends(_Class, _super); + + function _Class(init) { + _Class.__super__.constructor.call(this, MWS_PRODUCTS, 'GetProductCategoriesForASIN', [new mws.Param('MarketplaceId', 'Id', true), new mws.Param('ASIN', true)], {}, null, init); + } + + return _Class; + + })(mws.Request) + }; + + ProductsClient = (function(_super) { + __extends(ProductsClient, _super); + + function ProductsClient() { + ProductsClient.__super__.constructor.apply(this, arguments); } -}; + ProductsClient.prototype.getServiceStatus = function(cb) { + var _this = this; + return this.invoke(new requests.GetServiceStatus(), {}, function(res) { + var status, _ref, _ref1; + status = (_ref = (_ref1 = res.result) != null ? _ref1.Status : void 0) != null ? _ref : null; + return cb(status, res); + }); + }; + + ProductsClient.prototype.listMatchingProducts = function(query, context, cb) { + var req, + _this = this; + req = new requests.ListMatchingProducts({ + MarketplaceId: this.marketplaceId, + Query: query, + QueryContextId: context != null ? context : void 0 + }); + return this.invoke(req, {}, function(res) { + return cb(res); + }); + }; + + ProductsClient.prototype.getMatchingProduct = function(asins, cb) { + var req, + _this = this; + req = new requests.GetMatchingProduct({ + MarketplaceId: this.marketplaceId, + ASINList: asins != null ? asins : [] + }); + return this.invoke(req, {}, function(res) { + return cb(res); + }); + }; + + ProductsClient.prototype.getMatchingProductForId = function(idType, ids, cb) { + var req, + _this = this; + req = new requests.GetMatchingProductForId({ + MarketplaceId: this.marketplaceId, + IdType: idType, + IdList: ids + }); + return this.invoke(req, {}, function(res) { + return cb(res); + }); + }; + + ProductsClient.prototype.getCompetitivePricingForSKU = function(skus, cb) { + var req, + _this = this; + req = new requests.GetCompetitivePricingForSKU({ + MarketplaceId: this.marketplaceId, + SellerSKUList: skus != null ? skus : [] + }); + return this.invoke(req, {}, function(res) { + return cb(res); + }); + }; + + ProductsClient.prototype.getCompetitivePricingForASIN = function(asins, cb) { + var req, + _this = this; + req = new requests.GetCompetitivePricingForASIN({ + MarketplaceId: this.marketplaceId, + ASINList: asins != null ? asins : [] + }); + return this.invoke(req, {}, function(res) { + return cb(res); + }); + }; + + ProductsClient.prototype.getLowestOfferListingsForSKU = function(skus, condition, cb) { + var req, + _this = this; + req = new requests.GetLowestOfferListingsForSKU({ + MarketplaceId: this.marketplaceId, + SellerSKUList: skus != null ? skus : [], + ItemCondition: condition != null ? condition : void 0 + }); + return this.invoke(req, {}, function(res) { + return cb(res); + }); + }; + + ProductsClient.prototype.getLowestOfferListingsForASIN = function(asins, condition, cb) { + var req, + _this = this; + req = new requests.GetLowestOfferListingsForASIN({ + MarketplaceId: this.marketplaceId, + ASINList: asins != null ? asins : [], + ItemCondition: condition != null ? condition : void 0 + }); + return this.invoke(req, {}, function(res) { + return cb(res); + }); + }; + + ProductsClient.prototype.getMyPriceForSKU = function(skus, condition, cb) { + var req, + _this = this; + req = new requests.GetMyPriceForSKU({ + MarketplaceId: this.marketplaceId, + SellerSKUList: skus != null ? skus : [], + ItemCondition: condition != null ? condition : void 0 + }); + return this.invoke(req, {}, function(res) { + return cb(res); + }); + }; + + ProductsClient.prototype.getMyPriceForASIN = function(asins, condition, cb) { + var req, + _this = this; + req = new requests.GetMyPriceForASIN({ + MarketplaceId: this.marketplaceId, + ASINList: asins != null ? asins : [], + ItemCondition: condition != null ? condition : void 0 + }); + return this.invoke(req, {}, function(res) { + return cb(res); + }); + }; + + ProductsClient.prototype.getProductCategoriesForSKU = function(sku, cb) { + var req, + _this = this; + req = new requests.GetProductCategoriesForSKU({ + MarketplaceId: this.marketplaceId, + SellerSKU: sku + }); + return this.invoke(req, {}, function(res) { + return cb(res); + }); + }; + + ProductsClient.prototype.getProductCategoriesForASIN = function(asin, cb) { + var req, + _this = this; + req = new requests.GetProductCategoriesForASIN({ + MarketplaceId: this.marketplaceId, + ASIN: asin + }); + return this.invoke(req, {}, function(res) { + return cb(res); + }); + }; + + return ProductsClient; + + })(mws.Client); + + module.exports = { + service: MWS_PRODUCTS, + enums: enums, + requests: requests, + Client: ProductsClient + }; + +}).call(this); diff --git a/lib/reports.js b/lib/reports.js index 332cb07..0093566 100644 --- a/lib/reports.js +++ b/lib/reports.js @@ -1,166 +1,608 @@ -/** - * Reports API requests and definitions for Amazon's MWS web services. - * For information on using, please see examples folder. - * - * @author Robert Saunders - */ -var mws = require('./mws'); - -/** - * Construct a Reports API request for mws.Client.invoke() - * - * @param {String} action Action parameter of request - * @param {Object} params Schemas for all supported parameters - */ -function ReportsRequest(action, params) { - var opts = { - name: 'Reports', - group: 'Reports & Report Scheduling', - path: '/', - version: '2009-01-01', - legacy: true, - action: action, - params: params - }; - return new mws.Request(opts); -} - -/** - * Ojects to represent enum collections used by some request(s) - * @type {Object} - */ -var enums = exports.enums = { - - Schedules: function() { - return new mws.Enum(['_15_MINUTES_', '_30_MINUTES_', '_1_HOUR_', '_2_HOURS_', '_4_HOURS_', '_8_HOURS_', '_12_HOURS_', '_72_HOURS_', '_1_DAY_', '_2_DAYS_', '_7_DAYS_', '_14_DAYS_', '_15_DAYS_', '_30_DAYS_', '_NEVER_']); - }, - - ReportProcessingStatuses: function() { - return new mws.Enum(['_SUBMITTED_', '_IN_PROGRESS_', '_CANCELLED_', '_DONE_', '_DONE_NO_DATA_']); - }, - - ReportOptions: function() { - return new mws.Enum(['ShowSalesChannel=true']); - } - -}; - -/** - * A collection of currently supported request constructors. Once created and - * configured, the returned requests can be passed to an mws client `invoke` call - * @type {Object} - */ -var calls = exports.requests = { - - GetReport: function() { - return new ReportsRequest('GetReport', { - ReportId: { name: 'ReportId', required: true } - }); - }, - - GetReportCount: function() { - return new ReportsRequest('GetReportCount', { - ReportTypes: { name: 'ReportTypeList.Type', list: true}, - Acknowledged: { name: 'Acknowledged', type: 'Boolean' }, - AvailableFrom: { name: 'AvailableFromDate', type: 'Timestamp' }, - AvailableTo: { name: 'AvailableToDate', type: 'Timestamp' } - }); - }, - - GetReportList: function() { - return new ReportsRequest('GetReportList', { - MaxCount: { name: 'MaxCount' }, - ReportTypes: { name: 'ReportTypeList.Type', list: true}, - Acknowledged: { name: 'Acknowledged', type: 'Boolean' }, - AvailableFrom: { name: 'AvailableFromDate', type: 'Timestamp' }, - AvailableTo: { name: 'AvailableToDate', type: 'Timestamp' }, - ReportRequestIds: { name: 'ReportRequestIdList.Id', list: true } - }); - }, - - GetReportListByNextToken: function() { - return new ReportsRequest('GetReportListByNextToken', { - NextToken: { name: 'NextToken', required: true } - }); - }, - - GetReportRequestCount: function() { - return new ReportsRequest('GetReportRequestCount', { - RequestedFrom: { name: 'RequestedFromDate', type: 'Timestamp' }, - RequestedTo: { name: 'RequestedToDate', type: 'Timestamp' }, - ReportTypes: { name: 'ReportTypeList.Type', list: true }, - ReportProcessingStatuses: { name: 'ReportProcessingStatusList.Status', list: true, type: 'reports.ReportProcessingStatuses' } - }); - }, - - GetReportRequestList: function() { - return new ReportsRequest('GetReportRequestList', { - MaxCount: { name: 'MaxCount' }, - RequestedFrom: { name: 'RequestedFromDate', type: 'Timestamp' }, - RequestedTo: { name: 'RequestedToDate', type: 'Timestamp' }, - ReportRequestIds: { name: 'ReportRequestIdList.Id', list: true }, - ReportTypes: { name: 'ReportTypeList.Type', list: true }, - ReportProcessingStatuses: { name: 'ReportProcessingStatusList.Status', list: true, type: 'reports.ReportProcessingStatuses' } - }); - }, - - GetReportRequestListByNextToken: function() { - return new ReportsRequest('GetReportRequestListByNextToken', { - NextToken: { name: 'NextToken', required: true } - }); - }, - - CancelReportRequests: function() { - return new ReportsRequest('CancelReportRequests', { - RequestedFrom: { name: 'RequestedFromDate', type: 'Timestamp' }, - RequestedTo: { name: 'RequestedToDate', type: 'Timestamp' }, - ReportRequestIds: { name: 'ReportRequestIdList.Id', list: true }, - ReportTypes: { name: 'ReportTypeList.Type', list: true }, - ReportProcessingStatuses: { name: 'ReportProcessingStatusList.Status', list: true, type: 'reports.ReportProcessingStatuses' } - }); - }, - - RequestReport: function() { - return new ReportsRequest('RequestReport', { - ReportType: { name: 'ReportType', required: true }, - MarketplaceIds: { name: 'MarketplaceIdList.Id', list: true, required: false }, - StartDate: { name: 'StartDate', type: 'Timestamp' }, - EndDate: { name: 'EndDate', type: 'Timestamp' }, - ReportOptions: { name: 'ReportOptions', type: 'reports.ReportOptions' } - }); - }, - - ManageReportSchedule: function() { - return new ReportsRequest('ManageReportSchedule', { - ReportType: { name: 'ReportType', required: true }, - Schedule: { name: 'Schedule', type: 'reports.Schedules', required: true }, - ScheduleDate: { name: 'ScheduleDate', type: 'Timestamp' } - }); - }, - - GetReportScheduleList: function() { - return new ReportsRequest('GetReportScheduleList', { - ReportTypes: { name: 'ReportTypeList.Type', list: true } - }); - }, - - GetReportScheduleListByNextToken: function() { - return new ReportsRequest('GetReportScheduleListByNextToken', { - NextToken: { name: 'NextToken', required: true } - }); - }, - - GetReportScheduleCount: function() { - return new ReportsRequest('GetReportScheduleCount', { - ReportTypes: { name: 'ReportTypeList.Type', list: true } - }); - }, - - UpdateReportAcknowledgements: function() { - return new ReportsRequest('UpdateReportAcknowledgements', { - ReportIds: { name: 'ReportIdList.Id', list: true, required: true }, - Acknowledged: { name: 'Acknowledged', type: 'Boolean' } - }); +// Generated by CoffeeScript 1.6.3 +(function() { + var MWS_REPORTS, ReportsClient, enums, mws, reportTypes, requests, _ref, + __hasProp = {}.hasOwnProperty, + __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }; + + mws = require("./core"); + + MWS_REPORTS = new mws.Service({ + name: "Reports", + group: "Reports & Report Scheduling", + path: "/", + version: "2009-01-01", + legacy: true + }); + + reportTypes = { + '_GET_FLAT_FILE_OPEN_LISTINGS_DATA_': { + title: 'Inventory Report', + group: 'Listings', + format: 'flat', + request: true + }, + '_GET_MERCHANT_LISTINGS_DATA_BACK_COMPAT_': { + title: 'Open Listings Report', + group: 'Listings', + format: 'flat', + request: true + }, + '_GET_MERCHANT_LISTINGS_DATA_': { + title: 'Merchant Listings Report', + group: 'Listings', + format: 'flat', + request: true + }, + '_GET_MERCHANT_LISTINGS_DATA_LITE_': { + title: 'Merchant Listings Report - Lite', + group: 'Listings', + format: 'flat', + request: true + }, + '_GET_MERCHANT_LISTINGS_DATA_LITER_': { + title: 'Merchant Listings Report - Liter', + group: 'Listings', + format: 'flat', + request: true + }, + '_GET_CONVERGED_FLAT_FILE_SOLD_LISTINGS_DATA': { + title: 'Sold Listings Report', + group: 'Listings', + format: 'flat', + request: true + }, + '_GET_MERCHANT_CANCELLED_LISTINGS_DATA_': { + title: 'Canceled Listings Report', + group: 'Listings', + format: 'flat', + request: true + }, + '_GET_MERCHANT_LISTINGS_DEFECT_DATA_': { + title: 'Quality Listing Report', + group: 'Listings', + format: 'flat', + request: true + }, + '_GET_FLAT_FILE_ACTIONABLE_ORDER_DATA_': { + title: 'Unshipped Orders Report', + group: 'Orders', + format: 'flat', + request: true + }, + '_GET_ORDERS_DATA_': { + title: 'Scheduled XML Order Report', + group: 'Orders', + format: 'xml', + schedule: true + }, + '_GET_FLAT_FILE_ORDER_REPORT_DATA_': { + title: 'Flat File Order Report', + group: 'Orders', + format: 'flat', + request: true + }, + '_GET_FLAT_FILE_ORDERS_DATA_': { + title: 'Requested or Scheduled Flat File Order Report', + group: 'Orders', + format: 'flat', + schedule: true, + request: true + }, + '_GET_CONVERGED_FLAT_FILE_ORDER_REPORT_DATA_': { + title: 'Flat File Order Report', + group: 'Orders', + format: 'flat', + schedule: true, + request: true + }, + '_GET_FLAT_FILE_ALL_ORDERS_DATA_BY_LAST_UPDATE_': { + title: 'Flat File Orders By Last Update Report', + group: 'Orders', + format: 'flat', + request: true + }, + '_GET_FLAT_FILE_ALL_ORDERS_DATA_BY_ORDER_DATE_': { + title: 'Flat File Orders By Order Date', + group: 'Orders', + format: 'flat', + request: true + }, + '_GET_XML_ALL_ORDERS_DATA_BY_LAST_UPDATE_': { + title: 'XML Orders By Last Update Report', + group: 'Orders', + format: 'xml', + request: true + }, + '_GET_XML_ALL_ORDERS_DATA_BY_ORDER_DATE_': { + title: 'XML Orders By Order Date', + group: 'Orders', + format: 'xml', + request: true + }, + '_GET_FLAT_FILE_PENDING_ORDERS_DATA_': { + title: 'Flat File Pending Orders Report', + group: 'Orders', + format: 'flat', + schedule: true, + request: true + }, + '_GET_PENDING_ORDERS_DATA_': { + title: 'XML Pending Orders Report', + format: 'xml', + schedule: true, + request: true + }, + '_GET_CONVERGED_FLAT_FILE_PENDING_ORDERS_DATA_': { + title: 'Converged Flat File Pending Orders Report', + group: 'Orders', + format: 'flat', + schedule: true, + request: true + }, + '_GET_SELLER_FEEDBACK_DATA_': { + title: 'Flat File Feedback', + group: 'Performance', + format: 'flat', + request: true + }, + '_GET_AFN_INVENTORY_DATA_': { + title: 'FBA Inventory Report', + group: 'Fulfillment', + format: 'flat', + request: true + } + }; + + /* + Ojects to represent enum collections used by some request(s) + @type {Object} + */ + + + enums = { + Schedule: (function(_super) { + __extends(_Class, _super); + + function _Class() { + _Class.__super__.constructor.call(this, "Schedule", ["_15_MINUTES_", "_30_MINUTES_", "_1_HOUR_", "_2_HOURS_", "_4_HOURS_", "_8_HOURS_", "_12_HOURS_", "_72_HOURS_", "_1_DAY_", "_2_DAYS_", "_7_DAYS_", "_14_DAYS_", "_15_DAYS_", "_30_DAYS_", "_NEVER_"], true); + } + + return _Class; + + })(mws.Enum), + ReportProcessingStatusList: (function(_super) { + __extends(_Class, _super); + + function _Class() { + _Class.__super__.constructor.call(this, "ReportTypeList", "Status", ["_SUBMITTED_", "_IN_PROGRESS_", "_CANCELLED_", "_DONE_", "_DONE_NO_DATA_"], false); + } + + return _Class; + + })(mws.EnumList), + ReportOptions: (function(_super) { + __extends(_Class, _super); + + function _Class() { + _Class.__super__.constructor.call(this, "ReportOptions", ["ShowSalesChannel=true", "ShowSalesChannel=false"], false); + } + + return _Class; + + })(mws.Enum), + RequestableReportType: (function(_super) { + __extends(_Class, _super); + + function _Class() { + var k, reqReportsTypes, v; + reqReportsTypes = (function() { + var _results; + _results = []; + for (k in reportTypes) { + v = reportTypes[k]; + if (v.request) { + _results.push(k); + } + } + return _results; + })(); + _Class.__super__.constructor.call(this, "ReportType", reqReportsTypes, true); + } + + return _Class; + + })(mws.Enum), + SchedulableReportType: (function(_super) { + __extends(_Class, _super); + + function _Class() { + var k, schedReportsTypes, v; + schedReportsTypes = (function() { + var _results; + _results = []; + for (k in reportTypes) { + v = reportTypes[k]; + if (v.schedule) { + _results.push(k); + } + } + return _results; + })(); + _Class.__super__.constructor.call(this, "ReportType", schedReportsTypes, true); + } + + return _Class; + + })(mws.Enum), + ReportTypeList: (function(_super) { + __extends(_Class, _super); + + function _Class() { + var k, reportTypesList, v; + reportTypesList = (function() { + var _results; + _results = []; + for (k in reportTypes) { + v = reportTypes[k]; + if (v.schedule) { + _results.push(k); + } + } + return _results; + })(); + _Class.__super__.constructor.call(this, "ReportTypeList", "Type", reportTypesList, false); + } + + return _Class; + + })(mws.EnumList) + }; + + /* + A collection of currently supported request constructors. Once created and + configured, the returned requests can be passed to an mws client `invoke` call + @type {Object} + */ + + + requests = { + RequestReport: (function(_super) { + __extends(_Class, _super); + + function _Class(init) { + _Class.__super__.constructor.call(this, MWS_REPORTS, 'RequestReport', [new enums.RequestableReportType(), new mws.Timestamp('StartDate'), new mws.Timestamp('EndDate'), new enums.ReportOptions(), new mws.ParamList('MarketplaceIdList', 'Id')], {}, null, init); + } + + return _Class; + + })(mws.Request), + GetReportRequestList: (function(_super) { + __extends(_Class, _super); + + function _Class(init) { + _Class.__super__.constructor.call(this, MWS_REPORTS, 'GetReportRequestList', [new mws.ParamList('ReportRequestIdList', 'Id'), new enums.ReportTypeList(), new enums.ReportProcessingStatusList(), new mws.Param('MaxCount'), new mws.Timestamp('RequestedFromDate'), new mws.Timestamp('RequestedToDate')], {}, null, init); + } + + return _Class; + + })(mws.Request), + GetReportRequestListByNextToken: (function(_super) { + __extends(_Class, _super); + + function _Class(init) { + _Class.__super__.constructor.call(this, MWS_REPORTS, 'GetReportRequestListByNextToken', [new mws.Param('NextToken', true)], {}, null, init); + } + + return _Class; + + })(mws.Request), + GetReportRequestCount: (function(_super) { + __extends(_Class, _super); + + function _Class(init) { + _Class.__super__.constructor.call(this, MWS_REPORTS, 'GetReportRequestCount', [new enums.ReportTypeList(), new enums.ReportProcessingStatusList(), new mws.Timestamp('RequestedFromDate'), new mws.Timestamp('RequestedToDate')], {}, null, init); + } + + return _Class; + + })(mws.Request), + CancelReportRequests: (function(_super) { + __extends(_Class, _super); + + function _Class(init) { + _Class.__super__.constructor.call(this, MWS_REPORTS, 'CancelReportRequests', [new mws.ParamList('ReportRequestIdList', 'Id'), new enums.ReportTypeList(), new enums.ReportProcessingStatusList(), new mws.Timestamp('RequestedFromDate'), new mws.Timestamp('RequestedToDate')], {}, null, init); + } + + return _Class; + + })(mws.Request), + GetReportList: (function(_super) { + __extends(_Class, _super); + + function _Class(init) { + _Class.__super__.constructor.call(this, MWS_REPORTS, 'GetReportList', [new mws.Param('MaxCount'), new enums.ReportTypeList(), new mws.Bool('Acknowledged'), new mws.Timestamp('AvailableFromDate'), new mws.Timestamp('AvailableToDate'), new mws.ParamList('ReportRequestIdList', 'Id')], {}, null, init); + } + + return _Class; + + })(mws.Request), + GetReportListByNextToken: (function(_super) { + __extends(_Class, _super); + + function _Class(init) { + _Class.__super__.constructor.call(this, MWS_REPORTS, 'GetReportListByNextToken', [new mws.Param('NextToken', true)], {}, null, init); + } + + return _Class; + + })(mws.Request), + GetReportCount: (function(_super) { + __extends(_Class, _super); + + function _Class(init) { + _Class.__super__.constructor.call(this, MWS_REPORTS, 'GetReportCount', [new enums.ReportTypeList(), new mws.Bool('Acknowledged'), new mws.Timestamp('AvailableFromDate'), new mws.Timestamp('AvailableToDate')], {}, null, init); + } + + return _Class; + + })(mws.Request), + GetReport: (function(_super) { + __extends(_Class, _super); + + function _Class(init) { + _Class.__super__.constructor.call(this, MWS_REPORTS, 'GetReport', [new mws.Param('ReportId', true)], {}, null, init); + } + + return _Class; + + })(mws.Request), + ManageReportSchedule: (function(_super) { + __extends(_Class, _super); + + function _Class(init) { + _Class.__super__.constructor.call(this, MWS_REPORTS, 'ManageReportSchedule', [new enums.SchedulableReportType(), new enums.Schedule(), new mws.Timestamp('ScheduledDate')], {}, null, init); + } + + return _Class; + + })(mws.Request), + GetReportScheduleList: (function(_super) { + __extends(_Class, _super); + + function _Class(init) { + _Class.__super__.constructor.call(this, MWS_REPORTS, 'GetReportScheduleList', [new enums.ReportTypeList()], {}, null, init); + } + + return _Class; + + })(mws.Request), + GetReportScheduleListByNextToken: (function(_super) { + __extends(_Class, _super); + + function _Class(init) { + _Class.__super__.constructor.call(this, MWS_REPORTS, 'GetReportScheduleListByNextToken', [new mws.Param('NextToken', true)], {}, null, init); + } + + return _Class; + + })(mws.Request), + GetReportScheduleCount: (function(_super) { + __extends(_Class, _super); + + function _Class(init) { + _Class.__super__.constructor.call(this, MWS_REPORTS, 'GetReportScheduleCount', [new enums.ReportTypeList()], {}, null, init); + } + + return _Class; + + })(mws.Request), + UpdateReportAcknowledgements: (function(_super) { + __extends(_Class, _super); + + function _Class(init) { + _Class.__super__.constructor.call(this, MWS_REPORTS, 'UpdateReportAcknowledgements', [new mws.ParamList('ReportIdList', 'Id', true), new mws.Bool('Acknowledged')], {}, null, init); + } + + return _Class; + + })(mws.Request) + }; + + ReportsClient = (function(_super) { + __extends(ReportsClient, _super); + + function ReportsClient() { + _ref = ReportsClient.__super__.constructor.apply(this, arguments); + return _ref; } -}; \ No newline at end of file + ReportsClient.prototype.requestReport = function(options, cb) { + var req, + _this = this; + req = new requests.RequestReport(options); + return this.invoke(req, {}, function(res) { + var reportReqInfo, _ref1, _ref2; + reportReqInfo = (_ref1 = (_ref2 = res.result) != null ? _ref2.ReportRequestInfo : void 0) != null ? _ref1 : null; + return cb(reportReqInfo, res); + }); + }; + + ReportsClient.prototype.getReportRequestList = function(options, cb) { + var req, + _this = this; + req = new requests.GetReportRequestList(options); + return this.invoke(req, { + nextTokenCall: requests.GetReportRequestListByNextToken, + nextTokenCallUseHasNext: true + }, function(res) { + var reportReqInfoList, _ref1, _ref2; + reportReqInfoList = (_ref1 = (_ref2 = res.result) != null ? _ref2.ReportRequestInfo : void 0) != null ? _ref1 : null; + return cb(reportReqInfoList, res); + }); + }; + + ReportsClient.prototype.getReportRequestListByNextToken = function(token, cb) { + var req, + _this = this; + req = new requests.GetReportRequestListByNextToken({ + NextToken: token + }); + return this.invoke(req, { + nextTokenCall: requests.GetReportRequestListByNextToken, + nextTokenCallUseHasNext: true + }, function(res) { + var reportReqInfoList, _ref1, _ref2; + reportReqInfoList = (_ref1 = (_ref2 = res.result) != null ? _ref2.ReportRequestInfo : void 0) != null ? _ref1 : null; + return cb(reportReqInfoList, res); + }); + }; + + ReportsClient.prototype.getReportRequestCount = function(options, cb) { + var req, + _this = this; + req = new requests.GetReportRequestCount(options); + return this.invoke(req, {}, function(res) { + var count, _ref1, _ref2; + count = (_ref1 = (_ref2 = res.result) != null ? _ref2.Count : void 0) != null ? _ref1 : null; + return cb(count, res); + }); + }; + + ReportsClient.prototype.cancelReportRequests = function(options, cb) { + var req, + _this = this; + req = new requests.CancelReportRequests(options); + return this.invoke(req, {}, function(res) { + var canceledReportReqInfoList, _ref1, _ref2; + canceledReportReqInfoList = (_ref1 = (_ref2 = res.result) != null ? _ref2.ReportRequestInfo : void 0) != null ? _ref1 : null; + return cb(canceledReportReqInfoList, res); + }); + }; + + ReportsClient.prototype.getReportList = function(options, cb) { + var req, + _this = this; + req = new requests.GetReportList(options); + return this.invoke(req, { + nextTokenCall: requests.GetReportListByNextToken, + nextTokenCallUseHasNext: true + }, function(res) { + var reportInfo, _ref1, _ref2; + reportInfo = (_ref1 = (_ref2 = res.result) != null ? _ref2.ReportInfo : void 0) != null ? _ref1 : null; + return cb(reportInfo, res); + }); + }; + + ReportsClient.prototype.getReportListByNextToken = function(token, cb) { + var req, + _this = this; + req = new requests.GetReportListByNextToken({ + NextToken: token + }); + return this.invoke(req, { + nextTokenCall: requests.GetReportListByNextToken, + nextTokenCallUseHasNext: true + }, function(res) { + var reportInfo, _ref1, _ref2; + reportInfo = (_ref1 = (_ref2 = res.result) != null ? _ref2.ReportInfo : void 0) != null ? _ref1 : null; + return cb(reportInfo, res); + }); + }; + + ReportsClient.prototype.getReportCount = function(options, cb) { + var req, + _this = this; + req = new requests.GetReportCount(options); + return this.invoke(req, {}, function(res) { + var count, _ref1, _ref2; + count = (_ref1 = (_ref2 = res.result) != null ? _ref2.Count : void 0) != null ? _ref1 : null; + return cb(count, res); + }); + }; + + ReportsClient.prototype.getReport = function(options, cb) { + var req, + _this = this; + req = new requests.GetReport(options); + return this.invoke(req, { + allowedContentTypes: ['application/octet-stream'] + }, function(res) { + var report; + report = res.response; + return cb(report, res); + }); + }; + + ReportsClient.prototype.manageReportSchedule = function(options, cb) { + var req, + _this = this; + req = new requests.ManageReportSchedule(options); + return this.invoke(req, {}, function(res) { + var reportSchedules, _ref1, _ref2; + reportSchedules = (_ref1 = (_ref2 = res.result) != null ? _ref2.ReportSchedule : void 0) != null ? _ref1 : null; + return cb(reportSchedules, res); + }); + }; + + ReportsClient.prototype.getReportScheduleList = function(options, cb) { + var req, + _this = this; + req = new requests.GetReportScheduleList(options); + return this.invoke(req, { + nextTokenCall: requests.GetReportScheduleListByNextToken + }, function(res) { + var reportSchedule, _ref1, _ref2; + reportSchedule = (_ref1 = (_ref2 = res.result) != null ? _ref2.ReportSchedule : void 0) != null ? _ref1 : null; + return cb(reportSchedule, res); + }); + }; + + ReportsClient.prototype.getReportScheduleListByNextToken = function(token, cb) { + var req, + _this = this; + req = new requests.GetReportScheduleListByNextToken({ + NextToken: token + }); + return this.invoke(req, { + nextTokenCall: requests.GetReportScheduleListByNextToken + }, function(res) { + var reportSchedule, _ref1, _ref2; + reportSchedule = (_ref1 = (_ref2 = res.result) != null ? _ref2.ReportSchedule : void 0) != null ? _ref1 : null; + return cb(reportSchedule, res); + }); + }; + + ReportsClient.prototype.getReportScheduleCount = function(options, cb) { + var req, + _this = this; + req = new requests.GetReportScheduleCount(options); + return this.invoke(req, {}, function(res) { + var count, _ref1, _ref2; + count = (_ref1 = (_ref2 = res.result) != null ? _ref2.Count : void 0) != null ? _ref1 : null; + return cb(count, res); + }); + }; + + ReportsClient.prototype.updateReportAcknowledgements = function(options, cb) { + var req, + _this = this; + req = new requests.UpdateReportAcknowledgements(options); + return this.invoke(req, {}, function(res) { + var reportInfo, _ref1, _ref2; + reportInfo = (_ref1 = (_ref2 = res.result) != null ? _ref2.ReportInfo : void 0) != null ? _ref1 : null; + return cb(reportInfo, res); + }); + }; + + return ReportsClient; + + })(mws.Client); + + module.exports = { + service: MWS_REPORTS, + enums: enums, + requests: requests, + Client: ReportsClient + }; + +}).call(this); diff --git a/lib/sellers.js b/lib/sellers.js index b23ae01..b9e1106 100644 --- a/lib/sellers.js +++ b/lib/sellers.js @@ -1,67 +1,123 @@ -/** - * Sellers API requests and definitions for Amazon's MWS web services. - * For information on using, please see examples folder. - * - * @author Robert Saunders - */ -var mws = require('./mws'); - -/** - * Construct a Sellers API request for mws.Client.invoke() - * - * @param {String} action Action parameter of request - * @param {Object} params Schemas for all supported parameters - */ -function SellersRequest(action, params) { - var opts = { - name: 'Sellers', - group: 'Sellers Retrieval', - path: '/Sellers/2011-07-01', - version: '2011-07-01', - legacy: false, - action: action, - params: params - }; - return new mws.Request(opts); -} - -/** - * Contains brief definitions for unique data type values. - * Can be used to explain input/output to users via tooltips, for example - * @type {Object} - */ -var types = exports.types = { - - ServiceStatus: { - 'GREEN':'The service is operating normally.', - 'GREEN_I':'The service is operating normally + additional info provided', - 'YELLOW':'The service is experiencing higher than normal error rates or degraded performance.', - 'RED':'The service is unabailable or experiencing extremely high error rates.' } - -}; - -/** - * A collection of currently supported request constructors. Once created and - * configured, the returned requests can be passed to an mws client `invoke` call - * @type {Object} - */ -var calls = exports.requests = { - - /** - * Requests the operational status of the Sellers API section. - */ - GetServiceStatus: function() { - return new SellersRequest('GetServiceStatus', {}); - }, - - ListMarketplaceParticipations: function() { - return new SellersRequest('ListMarketplaceParticipations', {}); - }, - - ListMarketplaceParticipationsByNextToken: function() { - return new SellersRequest('ListMarketplaceParticipationsByNextToken', { - NextToken: { name: 'NextToken', required: true } - }); +// Generated by CoffeeScript 1.4.0 +(function() { + var MWS_SELLERS, SellersClient, mws, requests, types, + __hasProp = {}.hasOwnProperty, + __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }; + + mws = require('./core'); + + MWS_SELLERS = new mws.Service({ + name: "Sellers", + group: "Sellers Retrieval", + path: "/Sellers/2011-07-01", + version: "2011-07-01", + legacy: false + }); + + types = { + ServiceStatus: mws.types.ServiceStatus + }; + + requests = { + GetServiceStatus: (function(_super) { + + __extends(_Class, _super); + + function _Class(init) { + _Class.__super__.constructor.call(this, MWS_SELLERS, 'GetServiceStatus', [], {}, null, init); + } + + return _Class; + + })(mws.Request), + ListMarketplaceParticipations: (function(_super) { + + __extends(_Class, _super); + + function _Class(init) { + _Class.__super__.constructor.call(this, MWS_SELLERS, 'ListMarketplaceParticipations', [], {}, null, init); + } + + return _Class; + + })(mws.Request), + ListMarketplaceParticipationsByNextToken: (function(_super) { + + __extends(_Class, _super); + + function _Class(init) { + _Class.__super__.constructor.call(this, MWS_SELLERS, 'ListMarketplaceParticipationsByNextToken', [new mws.Param('NextToken', true)], {}, null, init); + } + + return _Class; + + })(mws.Request) + }; + + SellersClient = (function(_super) { + + __extends(SellersClient, _super); + + function SellersClient() { + return SellersClient.__super__.constructor.apply(this, arguments); } -}; \ No newline at end of file + SellersClient.prototype.getServiceStatus = function(cb) { + var _this = this; + return this.invoke(new requests.GetServiceStatus(), {}, function(res) { + var status, _ref, _ref1; + status = (_ref = (_ref1 = res.result) != null ? _ref1.Status : void 0) != null ? _ref : null; + return cb(status, res); + }); + }; + + SellersClient.prototype.listMarketplaceParticipations = function(cb) { + var opt, req, + _this = this; + opt = { + nextTokenCall: requests.ListMarketplaceParticipationsByNextToken + }; + req = new requests.ListMarketplaceParticipations(); + return this.invoke(req, opt, function(res) { + var markets, partips, _ref, _ref1, _ref2, _ref3; + markets = (_ref = res != null ? (_ref1 = res.ListMarketplaces) != null ? _ref1.Marketplace : void 0 : void 0) != null ? _ref : null; + partips = (_ref2 = res != null ? (_ref3 = res.ListParticipations) != null ? _ref3.Participation : void 0 : void 0) != null ? _ref2 : null; + return cb({ + marketplaces: markets, + participations: partips + }, res); + }); + }; + + SellersClient.prototype.listMarketplaceParticipationsByNextToken = function(token, cb) { + var opt, req, + _this = this; + opt = { + nextTokenCall: requests.ListMarketplaceParticipationsByNextToken + }; + req = new requests.ListMarketplaceParticipationsByNextToken({ + NextToken: token + }); + return this.invoke(req, opt, function(res) { + var markets, partips, _ref, _ref1, _ref2, _ref3; + markets = (_ref = res != null ? (_ref1 = res.ListMarketplaces) != null ? _ref1.Marketplace : void 0 : void 0) != null ? _ref : null; + partips = (_ref2 = res != null ? (_ref3 = res.ListParticipations) != null ? _ref3.Participation : void 0 : void 0) != null ? _ref2 : null; + return cb({ + marketplaces: markets, + participations: partips + }, res); + }); + }; + + return SellersClient; + + })(mws.Client); + + module.exports = { + service: MWS_SELLERS, + types: types, + requests: requests, + Client: SellersClient + }; + +}).call(this); diff --git a/package.json b/package.json index 03fe6c3..96b7c3e 100644 --- a/package.json +++ b/package.json @@ -1,20 +1,20 @@ -{ - "name" : "mws-js", - "description" : "Amazon Marketplace Web Services client with support for all api calls.", - "keywords" : ["mws", "amazon", "marketplace"], - "homepage" : "_", - "version" : "0.1.0", - "author" : "Eibbor Srenduas (http://eibbors.net)", - "contributors" : [ ], - "main" : "./lib/mws", - "directories" : { - "lib": "./lib" - }, - "repository" : { - "type" : "git", - "url" : "https://github.com/eibbors/mws-js.git" - }, - "dependencies" : { - "xml2js" : ">=0.1.13" - } -} +{ + "name" : "mws-js", + "description" : "Amazon Marketplace Web Services client with support for all api calls.", + "keywords" : ["mws", "amazon", "marketplace"], + "homepage" : "_", + "version" : "0.1.1", + "author" : "Eibbor Srenduas (http://eibbors,com)", + "contributors" : [ ], + "main" : "./lib/mws", + "directories" : { + "lib": "./lib" + }, + "repository" : { + "type" : "git", + "url" : "https://github.com/eibbors/mws-js.git" + }, + "dependencies" : { + "xml2js" : "=0.1.13" + } +} diff --git a/src/core.coffee b/src/core.coffee new file mode 100644 index 0000000..90a3972 --- /dev/null +++ b/src/core.coffee @@ -0,0 +1,525 @@ +# ---------------------------------------------------------- +# mws-js • core.coffee • by robbie saunders [eibbors.com] +# ---------------------------------------------------------- +# Core classes and types required for communication with Amazon's +# MWS services. This mainly includes https client + request + +# response wrappers with helpers galore and the param schema + +# model classes used to declare services in submodules. +# ---------------------------------------------------------- + +{EventEmitter} = require "events" +https = require "https" +qs = require "querystring" +crypto = require "crypto" +xml2js = require 'xml2js' + +# Constants required by the method used to sign requests +MWS_SIGNATURE_METHOD = 'HmacSHA256' +MWS_SIGNATURE_VERSION = 2 + +# Constant marketplaceIds are annoying to keep track of so I put them here +MWS_MARKETPLACES = + # allow translation to country code + ATVPDKIKX0DER: 'US' + A1F83G8C2ARO7P: 'UK' + A13V1IB3VIYZZH: 'FR' + A1PA6795UKMFR9: 'DE' + APJ6JRA9NG5V4: 'IT' + A1RKKUPIHCS9HS: 'ES' + # allow lookup by country code + US: 'ATVPDKIKX0DER' + UK: 'A1F83G8C2ARO7P' + FR: 'A13V1IB3VIYZZH' + DE: 'A1PA6795UKMFR9' + IT: 'APJ6JRA9NG5V4' + ES: 'A1RKKUPIHCS9HS' + CA: null + CN: null + JP: null + +# I'm piecing these together from various sources, if you can help, please let me know! +MWS_LOCALES = + US: { host: "mws.amazonservices.com", country: 'UnitedStates', domain: 'www.amazon.com', marketplaceId: MWS_MARKETPLACES.US } + UK: { host: "mws.amazonservices.co", country: 'UnitedKingdom', domain: 'www.amazon.co.uk', marketplaceId: MWS_MARKETPLACES.UK } + FR: { host: "mws.amazonservices.fr", country: 'France', domain: 'www.amazon.fr', marketplaceId: MWS_MARKETPLACES.FR } + DE: { host: "mws.amazonservices.de", country: 'Germany', domain: 'www.amazon.de', marketplaceId: MWS_MARKETPLACES.DE } + IT: { host: "mws.amazonservices.it", country: 'Italy', domain: 'www.amazon.it', marketplaceId: MWS_MARKETPLACES.IT } + ES: { host: "mws.amazonservices.es", country: 'Spain', domain: 'www.amazon.es', marketplaceId: MWS_MARKETPLACES.ES } + CA: { host: "mws.amazonservices.ca", country: 'Canada', domain: 'www.amazon.ca', marketplaceId: MWS_MARKETPLACES.CA } + CN: { host: "mws.amazonservices.cn", country: 'China', domain: 'www.amazon.cn', marketplaceId: MWS_MARKETPLACES.CN } + JP: { host: "mws.amazonservices.jp", country: 'Japan', domain: 'www.amazon.jp', marketplaceId: MWS_MARKETPLACES.JP } + +# Core and common type definitions -- likely to be moved to a seperate file after +# the Feeds generation module is working, as there's a buttload of them +types = + ServiceStatus: + GREEN: "The service is operating normally." + GREEN_I: "The service is operating normally + additional info provided" + YELLOW: "The service is experiencing higher than normal error rates or degraded performance." + RED: "The service is unabailable or experiencing extremely high error rates." + + +class MWSClient extends EventEmitter + + constructor: (options = {}, extras...) -> + for e in extras when typeof e is 'object' + (options[k] = v) for k,v of e + # Load the settings if they pass in one of the MWS_LOCALES or their own + if options.locale? + unless typeof options.locale is 'object' + options.locale = MWS_LOCALES[options.locale] ? null + @host = options.host ? (options.locale.host ? "mws.amazonservices.com") + @marketplaceId = options.locale.marketplaceId + @country = options.locale.country ? undefined + @domain = options.locale.domain ? undefined + # Connection settings + @host = @host ? (options.host ? "mws.amazonservices.com") + @port = options.port ? 443 + # Credentials required by every request + @merchantId = options.merchantId ? null + @accessKeyId = options.accessKeyId ? null + @secretAccessKey = options.secretAccessKey ? null + # MarketplaceId required by many requests + @marketplaceId ?= @marketplaceId ? (options.marketplaceId ? null) + # Application information + @appName = options.appName or 'mws-js' + @appVersion = options.appVersion or "0.2.0" + @appLanguage = options.appLanguage or "JavaScript" + @appHost = options.appHost ? undefined + @appPlatform = options.appPlatform ? undefined + options + + # Used to sign + sign: (service, q={}) -> + path = service.path ? '/' + hash = crypto.createHmac("sha256", @secretAccessKey) + # Tack on access params + signature details + if service.legacy then q['Merchant'] = @merchantId + else q['SellerId'] = @merchantId + q['AWSAccessKeyId'] ?= @accessKeyId + q['SignatureMethod'] = MWS_SIGNATURE_METHOD + q['SignatureVersion'] = MWS_SIGNATURE_VERSION + # Sort the nearly complete query string + sorted = {} + keys = (k for k,v of q).sort() + (sorted[k] = q[k] for k in keys) + stringToSign = "POST\n#{@host}\n#{path}\n#{qs.stringify(sorted)}" + # Encode a few possible problem characters + stringToSign = stringToSign.replace( /'/g, '%27') + stringToSign = stringToSign.replace(/\*/g, '%2A') + stringToSign = stringToSign.replace(/\(/g, '%28') + stringToSign = stringToSign.replace(/\)/g, '%29') + # Finally we generate and append our signature parameter + q['Signature'] = hash.update(stringToSign).digest('base64') + q + + invoke: (request, options, cb) -> + # Calculate MD5 / Attach options.body as appropriate + if request?.body then request.md5Calc() + if options?.body then request.attach options.body, 'text' + # Load request path + sign query + options.path ?= request.service?.path ? '/' + q = @sign(options.service ? request.service ? null, request.query(options.query ? {})) + # Load request headers + options.headers ?= {} + (options.headers[h] = v) for h,v of request.headers + # Take care of body, whether explicitly defined or defaulting to query + if request.body or options.body + options.body ?= request.body + options.path = "#{options.path}?#{qs.stringify(q)}" + else + options.body = qs.stringify(q) + options.headers['content-type'] = 'application/x-www-form-urlencoded; charset=utf-8' + # Finish off other basic headers + options.headers['host'] = @host + agentParams = ["Language=#{@appLanguage}"] + if @appHost then agentParams.push "Host=#{@appHost}" + if @appPlatform then agentParams.push "Platform=#{@appPlatform}" + options.headers['user-agent'] = "#{@appName}/#{@appVersion} (#{agentParams.join('; ')})" + options.headers['content-length'] = options.body.length + # http(s) request options completes the request options + options.host ?= @host + options.port ?= @port + options.method ?= 'POST' + # Instantiate an http(s) request + req = https.request options, (res) => + # Join chunked data until EOF reached, then parse or pass error + data = [] + res.on 'data', (chunk) => + data.push( chunk ) + res.on 'end', => + data = Buffer.concat(data) + mwsres = new MWSResponse res, data, options + mwsres.parseHeaders() + mwsres.parseBody (err, parsed) => + if options.nextTokenCall? and (mwsres.result?.NextToken?.length > 0) + invokeOpts = { nextTokenCall : options.nextTokenCall } + # on calls that use HasNext parameter, set nextToken only if HasNext is 'true' + if options.nextTokenCallUseHasNext + invokeOpts.nextTokenCallUseHasNext = options.nextTokenCallUseHasNext + mwsres.nextToken = mwsres.result.NextToken if mwsres.result?.HasNext is 'true' + else + mwsres.nextToken = mwsres.result.NextToken + nextRequest = new options.nextTokenCall(NextToken: mwsres.nextToken) + mwsres.getNext = ()=> + opts = {} + for k,v of invokeOpts + opts[k] = v + @invoke nextRequest, opts, cb + @emit 'response', mwsres, parsed + cb mwsres + res.on 'error', (err) => + @emit 'error', err + cb err, null, Buffer.concat(data).toString() + @emit 'request', req, options + req.write options.body + req.end() + +# Basic Service definition +class MWSService + + constructor: (options) -> + (@[k] = v) for k,v of options + @name ?= null + @path ?= '/' + @version ?= '2009-01-01' + @legacy ?= false + +class MWSRequest + + constructor: (@service, @action, @params=[], @headers={}, @body=null, init={}) -> + @service ?= new MWSService + for i,p of @params + pid = p.name ? i + if init[pid]? then p.set init[pid] + @[pid] = @params[i] ? null + + query: (q={}) -> + for i,p of @params + val = @[p.name ? i] ? p ? {} + if val.render? then val.render(q) + else q[val.name ? i] = val.value ? p + q['Action'] = @action + q['Version'] = @service.version ? '2009-01-01' + q['Timestamp'] = (new Date()).toISOString() + q + + set: (param, value) -> + if typeof param is 'object' and value is undefined + for k, v of param + @set k, v + else + if @[param]?.set? + @[param].set(value ? null) + else + throw "#{param} is not a valid parameter for this request type" + + attach: (body, format) -> + @body = body + @headers['content-type'] = format ? 'text' + @md5Calc() + + md5Calc: -> + @headers['content-md5'] = crypto.createHash('md5').update(@body).digest("base64") + +class MWSResponse + + # Accepts an http(s) response object and raw response body + constructor: (response, body, options={}) -> + @statusCode = response.statusCode + @headers = response.headers + @body = body ? null + @meta = {} + @options = options + @allowedContentTypes = options?.allowedContentTypes ? [] + + # Looks for x-(ns)-(id) matches within header keys + # and stores them in @meta[ns][id] where id is camelCase + # ie: 'x-mws-timestamp' ~ @meta.mws.timestamp + # & 'x-amz-some-thing' ~ @meta.amz.someThing + parseHeaders: -> + for header,value of @headers + xreg = /x-(\w+)-(.*)/gi.exec header + if xreg + ns = xreg[1] + id = xreg[2].replace /(\-[a-z])/g, ($1) -> $1.toUpperCase().replace('-','') + @meta[ns] ?= {} + @meta[ns][id] = value + + # Handle xml2js conversion as well as any report formats later on + parseBody: (cb) -> + isXml = false + if @headers['content-type'].indexOf('text/xml') == 0 + @body = @body.toString() + isXml = true + else if @headers['content-type'].indexOf('text/plain') == 0 + @body = @body.toString().trim() + isXml = @body.indexOf(' + if err then throw err + else + @response = res ? {} + # This simply checks the root elements for "#{x}Response" and sets responseType + for k, v of @response + rtype = /([A-Z]\w+)Response/.exec k + if rtype + @responseType = rtype[1] + if @responseType is 'Error' + @error = v.Error ? v + @requestI + if v["#{@responseType}Result"] + @result = v["#{@responseType}Result"] + # if @result.NextToken? then @nextToken = @result.NextToken + if v.ResponseMetadata? then @meta.response = v.ResponseMetadata + cb err, res + else if @headers['content-type'] in @allowedContentTypes + md5 = crypto.createHash('md5').update(@body).digest("base64") + if @headers['content-md5'] == md5 + @response = @body + cb null, @body + else + @responseType = 'Error' + @error = + Type: {}, + Code: 'Client_WrongMD5', + Message: "Invalid MD5 on received content: amazon=#{ @headers['content-md5']} , calculated=#{ md5 }" + @response = null + @responseWithInvalidMD5 = @body + cb @error, null + else + @responseType = 'Error' + @error = + Type: {}, + Code: 'Client_UknownContent', + Message: "Unrecognized content format: #{@headers['content-type'] ? 'undefined'}" + @response = null + cb @error, null + +class MWSParam + constructor: (@name, @required=false, value) -> + if value? then @set value + + render: (obj={}) -> + val = @get() + if val? + obj[@name] = @get() + obj + else if @required + throw "Required parameter #{@name} must be defined!" + + get: -> + @value + + set: (val) -> + @value = val + this + +# Converts true/false or truthy/not values to literal 'true' or 'false' +class MWSBool extends MWSParam + + get: -> + if @value then "true" + else if @value? then "false" + else undefined + +class MWSTimestamp extends MWSParam + + get: -> + if @value?.constructor is Date + @value.toISOString() + else + @value + + set: (val) -> + val ?= new Date() + if val.constructor isnt Date + try + @value = new Date(val) + catch e + @value = val + else + @value = val + this + +class MWSParamList extends MWSParam + constructor: (@name, @type, @required, value) -> + super @name, @required, value ? [] + @list = true + + render: (obj={}) -> + if @value.length < 1 and @required + throw "Required parameter list, #{@name} is empty!" + for k,v of @get() + obj[k] = v + obj + + clear: -> @value = [] + + add: (vals...) -> @value = @value.concat vals + + get: (index...) -> + list = {} + count = 0 + if index.length < 1 + for v in @value + list["#{@name}.#{@type}.#{++count}"] = v + else + for i in index + throw "ERROR: INVALID INDEX #{i}" unless @value[i]? + list["#{@name}.#{@type}.#{++count}"] = @value[i] + list + + set: (val) -> + if Array.isArray val then @value = val + else @value = [val] + + +class MWSEnum extends MWSParam + constructor: (@name, @members=[], @required=false, value) -> + @value = null + if value? then @set value + + set: (val) -> + if val in @members + @value = val + else if @members[val]? + @value = @members[val] + else + throw "Invalid enumeration value, '#{val}', must be a member or index of #{@members}" + +# Model for enum params that accept +# Is used for enum fields that support multiple values. In other words, +class MWSEnumList extends MWSParamList + + constructor: (@name, @type, @members, @required=false, initValue) -> + @list = true + @value = {} + for m in @members + @value[m] = initValue ? false + + render: (obj={}) -> + onset = @get() + if onset.length < 1 and @required + throw "Required paremeter list (enum), #{@name} is empty!" + for k,v of onset + obj[k] = v + obj + + enable: (values...) -> + for v of values when v in @members + @value[v] = true + + disable: (values...) -> + for v of values when v in @members + @value[v] = false + + toggle: (values...) -> + for v of values when v in @members + @value[v] = if @value[v] then false else true + + # Resets (disables) all members + clear: -> @disable @members + + # Enables all members + all: -> @enable @members + + # Toggles every + invert: -> @toggle @members + + # Can be used to override default behavior and add custom enum members + add: (value, enabled=true) -> + @members[value] = enabled + @value[value] = enabled + this + + get: -> + list = {} + count = 0 + for i of @value + for k, v of @value[i] when v is true + list["#{@name}.#{@type}.#{++count}"] = k + list + +class MWSComplexParam extends MWSParam + constructor: (@name, @params, @required, value) -> + @params ?= {} + # @set value + + render: (obj={}) -> + fields = @get() + for k,v of fields + if v is null then throw "Missing required parameter #{k}" + else obj[k] = v + obj + + render: (obj={}) -> + for k,p of @params + n = p.name ? k + v = p.get?() ? p.value + if v? + obj["#{@name}.#{n}"] = v + else if p.required + throw "Missing required parameter #{@name}.#{n}" + obj + + get: (field) -> + if field? and @params[field]? + @params[field].get() + else if not field? + obj = {} + (obj[k] = p) for k,p of @params + else + for k,p of @params + if p.name is field then return p + throw "There is no field, #{field}, in #{@name}" + + set: (field, value) -> + if arguments.length is 1 and typeof field is 'object' + for k,v of field + @set k, v + else if @params[field]? + if @params[field].set? then @params[field].set(value) + else @params[field].value = value + else + for k,v of @params + if v.name.toLowerCase() is field.toLowerCase() + @set k, value + +class MWSComplexList extends MWSParamList + constructor: (@name, @type, @required, value) -> + super @name, @required, value ? [] + @list = true + + render: (obj={}) -> + if @value.length < 1 and @required + throw "Required (complex) parameter list, #{@name} is empty!" + for k,v of @get() + v.name = k + v.render(obj) + obj + +# Export all of the juicy goodness! +module.exports = + # namespaced constants and definitions + MARKETPLACES: MWS_MARKETPLACES + LOCALES: MWS_LOCALES + types: types + # core classes used by submodules + Client: MWSClient + Request: MWSRequest + Response: MWSResponse + Service: MWSService + Param: MWSParam + Bool: MWSBool + Timestamp: MWSTimestamp + ParamList: MWSParamList + Enum: MWSEnum + EnumList: MWSEnumList + ComplexParam: MWSComplexParam + ComplexList: MWSComplexList \ No newline at end of file diff --git a/src/fba.coffee b/src/fba.coffee new file mode 100644 index 0000000..a80024d --- /dev/null +++ b/src/fba.coffee @@ -0,0 +1,372 @@ +# ---------------------------------------------------------- +# mws-js • fba.coffee • by robbie saunders [eibbors.com] +# ---------------------------------------------------------- +# Module containing Amazon's newer Fulfillment service APIs +# ---------------------------------------------------------- + +mws = require './core' + +# Larger service definition than most other modules, be sure to +# note the difference in format MWS_FBA(DOT)(GROUP) +MWS_FBA_INBOUND = new mws.Service + name: 'Fulfillment' + group: 'Inbound Shipments' + path: '/FulfillmentInboundShipment/2010-10-01' + version: '2010-10-01' + legacy: false +MWS_FBA_OUTBOUND = new mws.Service + name: 'Fulfillment' + group: 'Outbound Shipments' + path: '/FulfillmentOutboundShipment/2010-10-01' + version: '2010-10-01' + legacy: false +MWS_FBA_INVENTORY = new mws.Service + name: 'Fulfillment' + group: 'Inventory' + path: '/FulfillmentInventory/2010-10-01' + version: '2010-10-01' + legacy: false + + +# Complex Parameters are those which contain child parameters +complex = + + DisplayableOrder: class extends mws.ComplexParam + constructor: (@name='DisplayableOrder', @required=false, init) -> + @params = + id: new mws.Param('DisplayableOrderId', true) + dateTime: new mws.Timestamp('DisplayableOrderDateTime', false) + comment: new mws.Param('DisplayableOrderComment', false) + if init? then @set init + + Address: class Address_Base extends mws.ComplexParam + constructor: (@name='Address', @required=false, init) -> + @params = + name: new mws.Param('Name', true) + line1: new mws.Param('Line1', true) + line2: new mws.Param('Line2', false) + line3: new mws.Param('Line3', false) + city: new mws.Param('City', true) + county: new mws.Param('DistrictOrCounty', false) + state: new mws.Param('StateOrProvinceCode', true) + zip: new mws.Param('PostalCode', true) + country: new mws.Param('CountryCode', true) + phone: new mws.Param('PhoneNumber', false) + if init? then @set init + + DestinationAddress: class extends Address_Base + constructor: (required, init) -> + super 'DestinationAddress', required, init + + ShipFromAddress: class extends mws.ComplexParam + constructor: (@required=false, init) -> + @name = 'ShipFromAddress' + @params = + name: new mws.Param('Name', true) + line1: new mws.Param('AddressLine1', true) + line2: new mws.Param('AddressLine2', false) + city: new mws.Param('City', true) + county: new mws.Param('DistrictOrCounty', false) + state: new mws.Param('StateOrProvinceCode', true) + zip: new mws.Param('PostalCode', true) + country: new mws.Param('CountryCode', true) + if init? then @set init + + InboundShipmentHeader: class extends mws.ComplexParam + constructor: (@required=false,init) -> + @name = 'InboundShipmentHeader' + @params = + shipmentName: new mws.Param('ShipmentName', true) + shipFromAddress: new complex.ShipFromAddress(true) + destFCID: new mws.Param('DestinationFulfillmentCenterId', true) + shipmentStatus: new mws.Param('ShipmentStatus', false) + labelPrepPref: new mws.Param('LabelPrepPreference',false) + + # The following classes pertain to the various Item lists (plural classes) + # and their child classes (optional if you use the addItem function) + + # Child parameter of LineItems + LineItem: class extends mws.ComplexParam + constructor: (@required=false, init) -> + @params = + comment: new mws.Param('DisplayableComment') + giftMessage: new mws.Param('GiftMessage') + declaredValue: new mws.Param('PerUnitDeclaredValue.Value') + declaredCurrency: new mws.Param('PerUnitDeclaredValue.CurrencyCode') + quantity: new mws.Param('Quantity') + itemId: new mws.Param('SellerFulfillmentOrderItemId') + sku: new mws.Param('SellerSKU') + if init? then @set init + + LineItems: class extends mws.ComplexList + constructor: (init) -> + super 'Items', 'member' + # Constructs (unless you pass a single object) and stores a LineItem instance + addItem: (itemId, sku, quantity, declaredValue, declaredCurrency, giftMessage, comment) -> + if arguments.length is 1 and typeof itemId is 'object' + if itemId.render? then @value.push itemId + else @value.push new complex.LineItem itemId + else + @value.push new complex.LineItem {itemId, sku, quantity, declaredValue, declaredCurrency, giftMessage, comment} + + # Child parameter of InboundShipmentItems < InboundShipmentHeader + InboundShipmentItem: class extends mws.ComplexParam + constructor: (init) -> + @params = + quantity: new mws.Param('QuantityShipped') + sku: new mws.Param('SellerSKU') + if init? then @set init + + # Stores a set of InboundShipmentItem instances for request params + InboundShipmentItems: class extends mws.ComplexList + constructor: (required, init) -> + super 'InboundShipmentItems', 'member', required, init + + # Add additional InboundShipmentItem via quantity/sku or existing instance + addItem: (quantity, sku) -> + if arguments.length is 1 and typeof quantity is 'object' + if quantity.render? then @value.push itemId + else @value.push new complex.InboundShipmentItem quantity + @value.push new complex.InboundShipmentItem { quantity, sku } + + InboundShipmentPlanRequestItem: class extends mws.ComplexParam + constructor: (init) -> + @params = + quantity: new mws.Param('Quantity') + sku: new mws.Param('SellerSKU') + asin: new mws.Param('ASIN') + condition: new mws.Param('Condition') + if init? then @set init + + InboundShipmentPlanRequestItems: class extends mws.ComplexList + constructor: (required, init) -> + super 'InboundShipmentPlanRequestItems', 'member', required, init + + # Add additional InboundShipmentItem via quantity/sku or existing instance + addItem: (quantity, sku, asin, condition) -> + if arguments.length is 1 and typeof quantity is 'object' + if quantity.render? then @value.push itemId + else @value.push new complex.InboundShipmentPlanRequestItem quantity + @value.push new complex.InboundShipmentPlanRequestItem { quantity, sku, asin, condition } + + +enums = + # Not exactly screaming for an enum class, but the only two values + # # currently allowed as part of the inventory api + ResponseGroup: class extends mws.Enum + constructor: (options={}) -> + super('ResponseGroup', [ 'Basic', 'Detailed' ], options.required ? false) + + ShippingSpeedCategory: class extends mws.Enum + constructor: (options={}) -> + super('ShippingSpeedCategory', [ 'Standard', 'Expedited', 'Priority'], options.required ? false) + + ShippingSpeedCategories: class extends mws.EnumList + constructor: (options={}) -> + super('ShippingSpeedCategories', 'member', [ 'Standard', 'Expedited', 'Priority'], options.required ? false) + + FulfillmentPolicy: class extends mws.Enum + constructor: (options={}) -> + super('FulfillmentPolicy', [ 'FillOrKill', 'FillAll', 'FillAllAvailable' ], options.required ? false) + + +# Simple types +types = + ServiceStatus: mws.types.ServiceStatus + + +requests = + inbound: + GetServiceStatus: class extends mws.Request + constructor: (init) -> + super MWS_FBA_INBOUND, 'GetServiceStatus', [], {}, null, init + + CreateInboundShipment: class extends mws.Request + constructor: (init) -> + super MWS_FBA_INBOUND, 'CreateInboundShipment',[ + new mws.Param('ShipmentId', true), + new complex.InboundShipmentHeader(true), + new complex.InboundShipmentItems(true) + ], {}, null, init + + CreateInboundShipmentPlan: class extends mws.Request + constructor: (init) -> + super MWS_FBA_INBOUND, 'CreateInboundShipmentPlan',[ + new mws.Param('LabelPrepPreference', true), + new mws.Param(new mws.Param), + new complex.ShipFromAddress(true), + new mws.Param('InboundShipmentPlanRequestItems', true) + ], {}, null, init + + ListInboundShipmentItems: class extends mws.Request + constructor: (init) -> + super MWS_FBA_INBOUND, 'ListInboundShipmentItems',[ + new mws.Param('ShipmentId', required: true), + new mws.Timestamp('LastUpdatedAfter'), + new mws.Timestamp('LastUpdatedBefore') + ], {}, null, init + + ListInboundShipmentItemsByNextToken: class extends mws.Request + constructor: (init) -> + super MWS_FBA_INBOUND, 'ListInboundShipmentItemsByNextToken',[ + new mws.Param('NextToken', true) + ], {}, null, init + + ListInboundShipments: class extends mws.Request + constructor: (init) -> + super MWS_FBA_INBOUND, 'ListInboundShipments',[ + new mws.ParamList('ShipmentStatusList', 'member') + new mws.ParamList('ShipmentIdList', 'member'), + new mws.Timestamp('LastUpdatedAfter'), + new mws.Timestamp('LastUpdatedBefore') + ], {}, null, init + + ListInboundShipmentsByNextToken: class extends mws.Request + constructor: (init) -> + super MWS_FBA_INBOUND, 'ListInboundShipmentsByNextToken',[ + new mws.Param('NextToken', true) + ], {}, null, init + + UpdateInboundShipment: class extends mws.Request + constructor: (init) -> + super MWS_FBA_INBOUND, 'UpdateInboundShipment',[ + new mws.Param('ShipmentId', true) + new complex.InboundShipmentHeader(true) + new complex.InboundShipmentItems(true) + ], {}, null, init + + outbound: + GetServiceStatus: class extends mws.Request + constructor: (init) -> + super MWS_FBA_OUTBOUND, 'GetServiceStatus', [], {}, null, init + + CancelFulfillmentOrder: class extends mws.Request + constructor: (init) -> + super MWS_FBA_OUTBOUND, 'CancelFulfillmentOrder', [ + new mws.Param('SellerFulfillmentOrderId', true) + ], {}, null, init + + CreateFulfillmentOrder: class extends mws.Request + constructor: (init) -> + super MWS_FBA_OUTBOUND, 'CreateFulfillmentOrder', [ + new mws.Param('SellerFulfillmentOrderId', true) + new enums.ShippingSpeedCategory(required: true) + new enums.FulfillmentPolicy() + new mws.Param('FulfillmentMethod') + new mws.ParamList('NotificationEmailList', 'member') + new complex.DestinationAddress() + new complex.LineItems() + ], {}, null, init + + GetFulfillmentOrder: class extends mws.Request + constructor: (init) -> + super MWS_FBA_OUTBOUND, 'GetFulfillmentOrder', [ + new mws.Param('SellerFulfillmentOrderId', true) + ], {}, null, init + + GetFulfillmentPreview: class extends mws.Request + constructor: (init) -> + super MWS_FBA_OUTBOUND, 'GetFulfillmentPreview', [ + new complex.Address('Address') + new complex.LineItems('LineItems') + new enums.ShippingSpeedCategories() + ], {}, null, init + + ListAllFulfillmentOrders: class extends mws.Request + constructor: (init) -> + super MWS_FBA_OUTBOUND, 'ListAllFulfillmentOrders', [ + new mws.Timestamp('QueryStartDateTime', true), + new mws.ParamList('FulfillmentMethod', 'member') + ], {}, null, init + + ListAllFulfillmentOrdersByNextToken: class extends mws.Request + constructor: (init) -> + super MWS_FBA_OUTBOUND, 'ListAllFulfillmentOrdersByNextToken', [ + new mws.Param('NextToken', true) + ], {}, null, init + + inventory: + GetServiceStatus: class extends mws.Request + constructor: (init) -> + super MWS_FBA_INVENTORY, 'GetServiceStatus', [], {}, null, init + + ListInventorySupply: class extends mws.Request + constructor: (init) -> + super MWS_FBA_INVENTORY, 'ListInventorySupply', [ + new mws.ParamList('SellerSkus', 'member'), + new mws.Timestamp('QueryStartDateTime'), + new enums.ResponseGroup() + ], {}, null, init + + ListInventorySupplyByNextToken: class extends mws.Request + constructor: (init) -> + super MWS_FBA_INVENTORY, 'ListInventorySupplyByNextToken', [ + new mws.Param('NextToken', true) + ], {}, null, init + +class FBAInboundClient extends mws.Client + + getServiceStatus: (cb) -> + @invoke new requests.inbound.GetServiceStatus(), {}, (res) => + status = res.result?.Status ? null + cb status, res + + listInboundShipments: (options, cb) -> + if options.ShipmentStatusList and options.ShipmentIdList + req = new requests.inbound.ListInboundShipments options + + @invoke req, { nextTokenCall: requests.ListInboundShipmentsByNextToken }, (res) -> + shipments = res.result?.ShipmentData ? null + if typeof cb is 'function' then cb shipments, res + else + throw 'Special Case: requires either ShipmentStatusList list or ShipmentIdList list be used!' + + listInboundShipmentItems: (options, cb) -> + if options.ShipmentId or (options.LastUpdatedAfter and options.LastUpdatedBefore) + req = new requests.inbound.ListInboundShipmentItems options; + @invoke req, { nextTokenCall: requests.ListInboundShipmentItemsByNextToken }, (res) -> + items = res.result?.ItemData ? null + if typeof cb is 'function' then cb items, res + else + throw 'Special Case: requires either ShipmentId number or LastUpdatedAfter and LastUpdatedBefore timestamps be used!'; + +class FBAOutboundClient extends mws.Client + + getServiceStatus: (cb) -> + @invoke new requests.outbound.GetServiceStatus(), {}, (res) => + status = res.result?.Status ? null + if typeof cb is 'function' then cb status, res + +class FBAInventoryClient extends mws.Client + + getServiceStatus: (cb) -> + @invoke new requests.inventory.GetServiceStatus(), {}, (res) => + status = res.result?.Status ? null + if typeof cb is 'function' then cb status, res + + listInventorySupply: (options, cb) -> + if (options.SellerSkus and not options.QueryStartDateTime or options.QueryStartDateTime) + req = new requests.inventory.ListInventorySupply options + + @invoke req, { nextTokenCall: requests.ListInventorySupplyByNextToken }, (res) -> + inventory = res.result?.InventorySupplyList ? null + if typeof cb is 'function' then cb inventory, res + else + throw 'Special Case: requires EXCLUSIVELY either SellerSkus list or QueryStartDateTime timestamp be used!' + +module.exports = + inbound: + service: MWS_FBA_INBOUND + requests: requests.inbound + Client: FBAInboundClient + outbound: + service: MWS_FBA_OUTBOUND + requests: requests.outbound + Client: FBAOutboundClient + inventory: + service: MWS_FBA_INVENTORY + requests: requests.inventory + Client: FBAInventoryClient + complex: complex + types: types + requests: requests \ No newline at end of file diff --git a/src/feeds.coffee b/src/feeds.coffee new file mode 100644 index 0000000..6411c05 --- /dev/null +++ b/src/feeds.coffee @@ -0,0 +1,233 @@ +# ---------------------------------------------------------- +# mws-js • feeds.coffee • by robbie saunders [eibbors.com] +# ---------------------------------------------------------- +# Module containing Amazon's newer Fulfillment service APIs +# ---------------------------------------------------------- + +fs = require 'fs' +mws = require("./core") + + +MWS_FEEDS = new mws.Service + name: "Feeds" + group: "Feeds" + path: "/" + version: "2009-01-01" + legacy: true + +types = + FeedTypes: + XML: [ + '_POST_PRODUCT_DATA_' + '_POST_PRODUCT_RELATIONSHIP_DATA_' + '_POST_ITEM_DATA_' + '_POST_PRODUCT_OVERRIDES_DATA_' + '_POST_PRODUCT_IMAGE_DATA_' + '_POST_PRODUCT_PRICING_DATA_' + '_POST_INVENTORY_AVAILABILITY_DATA_' + '_POST_ORDER_ACKNOWLEDGEMENT_DATA_' + '_POST_ORDER_FULFILLMENT_DATA_' + '_POST_FULFILLMENT_ORDER_REQUEST_DATA_' + '_POST_FULFILLMENT_ORDER_CANCELLATION_REQUEST_DATA_' + '_POST_PAYMENT_ADJUSTMENT_DATA_' + ] + Flat: [ + '_POST_FLAT_FILE_LISTINGS_DATA_' + '_POST_FLAT_FILE_ORDER_ACKNOWLEDGEMENT_DATA_' + '_POST_FLAT_FILE_FULFILLMENT_DATA_' + '_POST_FLAT_FILE_PAYMENT_ADJUSTMENT_DATA_' + '_POST_FLAT_FILE_INVLOADER_DATA_' + '_POST_FLAT_FILE_CONVERGENCE_LISTINGS_DATA_' + '_POST_FLAT_FILE_BOOKLOADER_DATA_' + '_POST_FLAT_FILE_PRICEANDQUANTITYONLY_UPDATE_DATA_' + ] + Other: [ + '_POST_UIEE_BOOKLOADER_DATA_' + ] + + FeedTypeFormats: + _POST_PRODUCT_DATA_: 'XML' + _POST_PRODUCT_RELATIONSHIP_DATA_: 'XML' + _POST_ITEM_DATA_: 'XML' + _POST_PRODUCT_OVERRIDES_DATA_: 'XML' + _POST_PRODUCT_IMAGE_DATA_: 'XML' + _POST_PRODUCT_PRICING_DATA_: 'XML' + _POST_INVENTORY_AVAILABILITY_DATA_: 'XML' + _POST_ORDER_ACKNOWLEDGEMENT_DATA_: 'XML' + _POST_ORDER_FULFILLMENT_DATA_: 'XML' + _POST_FULFILLMENT_ORDER_REQUEST_DATA_: 'XML' + _POST_FULFILLMENT_ORDER_CANCELLATION_REQUEST_DATA_: 'XML' + _POST_PAYMENT_ADJUSTMENT_DATA_: 'XML' + _POST_FLAT_FILE_LISTINGS_DATA_: 'FlatFile' + _POST_FLAT_FILE_ORDER_ACKNOWLEDGEMENT_DATA_: 'FlatFile' + _POST_FLAT_FILE_FULFILLMENT_DATA_: 'FlatFile' + _POST_FLAT_FILE_PAYMENT_ADJUSTMENT_DATA_: 'FlatFile' + _POST_FLAT_FILE_INVLOADER_DATA_: 'FlatFile' + _POST_FLAT_FILE_CONVERGENCE_LISTINGS_DATA_: 'FlatFile' + _POST_FLAT_FILE_BOOKLOADER_DATA_: 'FlatFile' + _POST_FLAT_FILE_PRICEANDQUANTITYONLY_UPDATE_DATA_: 'FlatFile' + _POST_UIEE_BOOKLOADER_DATA_: 'UIEE' + + FeedProcessingStatus: + _SUBMITTED_: 'Submitted' + _IN_PROGRESS_: 'In Progress' + _CANCELLED_: 'Cancelled' + _DONE_: 'Done' + +enums = exports.enums = + FeedProcessingStatus: class extends mws.Enum + constructor: (required, init) -> + super 'FeedProcessingStatus', (k for k,v of types.FeedProcessingStatus) + + FeedTypeList: class extends mws.EnumList + constructor: (required, init) -> + super 'FeedTypeList', 'Type', (k for k,v of types.FeedTypeFormats) , required, init + + FeedProcessingStatusList: class extends mws.EnumList + constructor: (required, init) -> + super 'FeedProcessingStatusList', 'Status', (k for k,v of types.FeedProcessingStatus), required, init + +# requests ns +requests = + + GetServiceStatus: class extends mws.Request + constructor: (init) -> + super MWS_FEEDS, 'GetServiceStatus', [], {}, null, init + + CancelFeedSubmissions: class extends mws.Request + constructor: (init) -> + super MWS_FEEDS, "CancelFeedSubmissions", [ + new mws.ParamList('FeedSubmissionIdList', 'Id') + new enums.FeedTypeList() + new mws.Timestamp('SubmittedFromDate') + new mws.Timestamp('SubmittedToDate') + ], {}, null, init + + GetFeedSubmissionList: class extends mws.Request + constructor: (init) -> + super MWS_FEEDS, "GetFeedSubmissionList", [ + new mws.ParamList('FeedSubmissionIdList', 'Id') + new mws.Param('MaxCount') + new enums.FeedTypeList() + new enums.FeedProcessingStatusList() + new mws.Timestamp('SubmittedFromDate') + new mws.Timestamp('SubmittedToDate') + ], {}, null, init + + GetFeedSubmissionListByNextToken: class extends mws.Request + constructor: (init) -> + super MWS_FEEDS, "GetFeedSubmissionListByNextToken", [ + new mws.Param('NextToken', true) + ], {}, null, init + + GetFeedSubmissionCount: class extends mws.Request + constructor: (init) -> + super MWS_FEEDS, "GetFeedSubmissionCount", [ + new enums.FeedTypeList() + new enums.FeedProcessingStatusList() + new mws.Timestamp('SubmittedFromDate') + new mws.Timestamp('SubmittedToDate') + ], {}, null, init + + GetFeedSubmissionResult: class extends mws.Request + constructor: (init) -> + super MWS_FEEDS, "GetFeedSubmissionResult", [ + new mws.Param('FeedSubmissionId', true) + ], {}, null, init + + SubmitFeed: class extends mws.Request + constructor: (init, body) -> + super MWS_FEEDS, "SubmitFeed", [ + new mws.Param('FeedType', true) + new mws.ParamList('MarketplaceIdList', 'Id') + new mws.Bool('PurgeAndReplace') + ], {}, body ? init?.body ? null, init + + # Sync. helper for loading an existing feed from the file ststem + attachFile: (filename, format, encoding, cb) -> + unless format? + if /\.xml$/gi.test(filename) or @FeedType? in types.FeedTypes.XML + format = "text/xml" + else + format = "text" + if typeof cb is 'function' + fs.readFile filename, encoding, (err, data) => + if err then throw err + else @attach data, format, e + else + @attach fs.readFileSync filename, format + +# New client class providing more convenient access to service via camelCased +# versions of the request as methods. +class FeedsClient extends mws.Client + + # The standard mws GetServiceStatus request. Callback function should be of the form + # (status, response) -> # ... + getServiceStatus: (cb) -> + @invoke new requests.GetServiceStatus(), {}, (res) => + status = res.result?.Status ? null + if typeof cb is 'function' then cb status, res + + # Cancel one or more previous submissions + cancelFeedSubmissions: (submissionIds, feedTypes, submittedFrom, submittedTo, cb) -> + req = new requests.CancelFeedSubmissions + FeedSubmissionIdList: submissionIds ? [] + FeedTypeList: feedTypes ? [] + SubmittedFromDate: submittedFrom + SubmittedToDate: submittedTo + @invoke req, {}, (res) => + # TODO: test and parse + if typeof cb is 'function' then cb res + + # Optional Parameters: + # FeedSubmissionIdList, FeedTypeList, FeedProcessingStatusList, + # SubmittedFromDate, SubmittedToDate, MaxCount + getFeedSubmissionList: (options={}, cb) -> + req = new requests.GetFeedSubmissionList options + @invoke req, { nextTokenCall: requests.GetFeedSubmissionListByNextToken }, (res) => + # TODO: test and parse + if typeof cb is 'function' then cb res + + # Request next page of feed submissions listed in GetFeedSubmissionListResult + getFeedSubmissionListByNextToken: (token, cb) -> + req = new requests.GetFeedSubmissionListByNextToken(NextToken: token) + @invoke req, { nextTokenCall: requests.GetFeedSubmissionListByNextToken }, (res) => + # TODO: test and parse + if typeof cb is 'function' then cb res + + # Works as expected, same parameters as cancel request + getFeedSubmissionCount: (feedTypes, statusList, submittedFrom, submittedTo, cb) -> + req = new requests.GetFeedSubmissionCount + FeedTypeList: feedTypes + FeedProcessingStatusList: statusList + SubmittedFromDate: submittedFrom + SubmittedToDate: submittedTo + @invoke req, {}, (res) => + # TODO: test and parse + if typeof cb is 'function' then cb res + + # Fetch any errors or results in response to feed submission (by id) + getFeedSubmissionResult: (id, cb) -> + req = new requests.GetFeedSubmissionResult FeedSubmissionId: id + @invoke req, {}, (res) => + # TODO: test and parse + if typeof cb is 'function' then cb res + + # Upload feed data for submission + submitFeed: (feedType, feedBody, marketplaces, purgeReplace=false, cb) => + req = new requests.SubmitFeed + FeedType: feedType + MarketplaceIdList: marketplaces ? @marketplaceIds ? [@marketplaceId] + PurgeAndReplace: purgeReplace + , feedBody + + @invoke req, {method:'POST', headers:{'Content-Type':'text/xml'}}, (res) => + # TODO: test and parse + if typeof cb is 'function' then cb res + +module.exports = + service: MWS_FEEDS + enums: enums + types: types + requests: requests + Client: FeedsClient diff --git a/src/orders.coffee b/src/orders.coffee new file mode 100644 index 0000000..7a6a8a7 --- /dev/null +++ b/src/orders.coffee @@ -0,0 +1,173 @@ +# ---------------------------------------------------------- +# mws-js • orders.coffee • by robbie saunders [eibbors.com] +# ---------------------------------------------------------- +# Provides the formal data structures necessary for working +# with Amazon's order retrieval services. If you need to look +# up details about your orders, you do it with this. +# ---------------------------------------------------------- + +mws = require './core' + +# MWS API Group configuration for Order Retrieval +MWS_ORDERS = new mws.Service + name: "Orders" + group: "Order Retrieval" + path: "/Orders/2011-01-01" + version: "2011-01-01" + legacy: false + +# Enumeration param definitions +enums = + # Order statuses with a little extra verification to help avoid errors + OrderStatus: class extends mws.EnumList + constructor: -> + super('OrderStatus', 'Status', (k for k,v of types.OrderStatus)) + + render: (obj={}) -> + if @value.Unshipped isnt @value.PartiallyShipped + throw "Unshipped & PartiallyShipped must both be enabled on the OrderStatus Param" + super(obj) + + FulfillmentChannel: class extends mws.EnumList + constructor: -> + super('FulfillmentChannel', 'Channel', (k for k,v of types.FulfillmentChannel)) + + PaymentMethod: class extends mws.EnumList + constructor: -> + super('PaymentMethod', 'Method', (k for k,v of types.PaymentMethod)) + +# Simple type definitions -- mostly helpful for providing hints through gui +types = + ServiceStatus: mws.types.ServiceStatus + + FulfillmentChannel: + AFN: "Amazon Fulfillment Network" + MFN: "Merchant's Fulfillment Network" + + OrderStatus: + Pending: "Order placed but payment not yet authorized. Not ready for shipment." + Unshipped: "Payment has been authorized. Order ready for shipment, but no items shipped yet. Implies PartiallyShipped." + PartiallyShipped: "One or more (but not all) items have been shipped. Implies Unshipped." + Shipped: "All items in the order have been shipped." + Canceled: "The order was canceled." + Unfulfillable: "The order cannot be fulfilled. Applies only to Amazon-fulfilled orders not placed on Amazon." + + PaymentMethod: + COD: "Cash on delivery" + CVS: "Convenience store payment" + Other: "Any payment method other than COD or CVS" + + ShipServiceLevelCategory: + Expedited: "Expedited shipping" + NextDay: "Overnight shipping" + SecondDay: "Second-day shipping" + Standard: "Standard shipping" + +# Order Retrieval Request Classes +requests = + + GetServiceStatus: class extends mws.Request + constructor: (init) -> + super MWS_ORDERS, 'GetServiceStatus', [], {}, null, init + + ListOrders: class extends mws.Request + constructor: (init) -> + super MWS_ORDERS, 'ListOrders', [ + new mws.Timestamp('CreatedAfter'), + new mws.Timestamp('CreatedBefore'), + new mws.Timestamp('LastUpdatedAfter'), + new mws.Timestamp('LastUpdatedBefore'), + new mws.ParamList('MarketplaceId', 'Id', true), + new enums.OrderStatus(), + new enums.FulfillmentChannel(), + new enums.PaymentMethod(), + new mws.Param('BuyerEmail'), + new mws.Param('SellerOrderId'), + new mws.Param('MaxResultsPerPage') + ], {}, null, init + + ListOrdersByNextToken: class extends mws.Request + constructor: (init) -> + super MWS_ORDERS, 'ListOrdersByNextToken', [ + new mws.Param('NextToken', true) + ], {}, null, init + + GetOrder: class extends mws.Request + constructor: (init) -> + super MWS_ORDERS, 'GetOrder', [ + new mws.ParamList('AmazonOrderId', 'Id', true) + ], {}, null, init + + ListOrderItems: class extends mws.Request + constructor: (init) -> + super MWS_ORDERS, 'ListOrderItems', [ + new mws.Param('AmazonOrderId', true) + # new mws.ParamList('MarketplaceId', 'Id', true) + ], {}, null, init + + ListOrderItemsByNextToken: class extends mws.Request + constructor: (init) -> + super MWS_ORDERS, 'ListOrderItemsByNextToken', [ + new mws.Param('NextToken', true) + ], {}, null, init + + +# New client class providing more convenient access to service via camelCased +# versions of the request as methods. +class OrdersClient extends mws.Client + + # The standard mws GetServiceStatus request. Callback function should be of the form + # (status, response) -> # ... + getServiceStatus: (cb) -> + @invoke new requests.GetServiceStatus(), {}, (res) => + status = res.result?.Status ? null + cb status, res + + # List the orders matching a set of criteria. + # See the ListOrders request above for a complete list of + # properties available for filtering the results. + listOrders: (options, cb) -> + if options.CreatedAfter? or options.LastUpdatedAfter? + options.MarketplaceId ?= @marketplaceIds ? @marketplaceId + req = new requests.ListOrders options + @invoke req, { nextTokenCall: requests.ListOrdersByNextToken }, (res) => + orders = res.result?.Orders?.Order ? null + cb orders, res + else + throw 'Special Case: requires AT LEAST ONE OF either CreatedAfter or LastUpdatedAfter timestamps be used!' + + # If your query returned more than one page of results, you + # should receive a token that can be used with this function + # to query the next chunk of order data. + listOrdersByNextToken: (token, cb) -> + req = new requests.ListOrdersByNextToken(NextToken: token) + @invoke req, { nextTokenCall: requests.ListOrdersByNextToken }, (res) => + orders = res.result?.Orders?.Order ? null + cb orders, res + + # Accepts an array of orderIds or a single orderId + getOrder: (orderId, cb) -> + req = new requests.GetOrder(AmazonOrderId: orderId) + @invoke req, {}, (res) => + orders = res.result?.Orders?.Order ? null + cb orders, res + + # Lists the items ordered for a given order id + listOrderItems: (orderId, cb) -> + req = new requests.ListOrderItems(AmazonOrderId: orderId) + @invoke req, { nextTokenCall: requests.ListOrderItemsByNextToken }, (res) => + items = res.result?.OrderItems?.OrderItem ? null + cb items, res + + # Use to request next set of results from a previous query + listOrderItemsByNextToken: (token, cb) -> + req = new requests.ListOrderItemsByNextToken(NextToken: token) + @invoke req, { nextTokenCall: requests.ListOrderItemsByNextToken }, (res) => + items = res.result?.OrderItems?.OrderItem ? null + cb items, res + +module.exports = + service: MWS_ORDERS + enums: enums + requests: requests + Client: OrdersClient \ No newline at end of file diff --git a/src/products.coffee b/src/products.coffee new file mode 100644 index 0000000..3b98da2 --- /dev/null +++ b/src/products.coffee @@ -0,0 +1,246 @@ +# ---------------------------------------------------------- +# mws-js • products.coffee • by robbie saunders [eibbors.com] +# ---------------------------------------------------------- +# Description soon +# ---------------------------------------------------------- + +mws = require './core' + +# MWS API Group configuration for Order Retrieval +MWS_PRODUCTS = new mws.Service + name: "Products" + group: "Products" + path: "/Products/2011-10-01" + version: "2011-10-01" + legacy: false + + +# Enumeration param definitions +enums = + # Only the following item conditions are supported + ItemCondition: class extends mws.Enum + constructor: -> + super('ItemCondition', ['New', 'Used', 'Collectible', 'Refurbished', 'Club']) + +# Simple type definitions -- mostly helpful for providing hints through gui +types = + ServiceStatus: mws.types.ServiceStatus + + MarketplaceId: + ATVPDKIKX0DER: 'amazon.com' + A1F83G8C2ARO7P: 'amazon.co.uk' + A13V1IB3VIYZZH: 'amazon.fr' + A1PA6795UKMFR9: 'amazon.de' + APJ6JRA9NG5V4: 'amazon.it' + A1RKKUPIHCS9HS: 'amazon.es' + +# Product Requests (translated, not tested) +requests = + + # Requests the operational status of the Products API section. + GetServiceStatus: class extends mws.Request + constructor: (init) -> + super MWS_PRODUCTS, 'GetServiceStatus', [], {}, null, init + + # Returns a list of products and their attributes, ordered by relevancy, + # based on a search query that you specify + ListMatchingProducts: class extends mws.Request + constructor: (init) -> + super MWS_PRODUCTS, 'ListMatchingProducts', [ + new mws.Param('MarketplaceId', 'Id', true), + new mws.Param('Query', true), + new mws.Param('QueryContextId', false), + ], {}, null, init + + # Returns a list of products and their attributes, + # based on a list of ASIN values that you specify + GetMatchingProduct: class extends mws.Request + constructor: (init) -> + super MWS_PRODUCTS, 'GetMatchingProduct', [ + new mws.Param('MarketplaceId', true), + new mws.ParamList('ASINList','ASIN'), + ], {}, null, init + + # Returns a list of products and their attributes, + # based on a list of ID values that you specify + # Id values can be : ASIN, SellerSKU, UPC, EAN, ISBN, and JAN. + GetMatchingProductForId: class extends mws.Request + constructor: (init) -> + super MWS_PRODUCTS, 'GetMatchingProductForId', [ + new mws.Param('MarketplaceId', true), + new mws.Param('IdType', true), + new mws.ParamList('IdList','Id'), + ], {}, null, init + + # Returns the current competitive pricing of a product, + # based on the SellerSKU and MarketplaceId that you specify + GetCompetitivePricingForSKU: class extends mws.Request + constructor: (init) -> + super MWS_PRODUCTS, 'GetCompetitivePricingForSKU', [ + new mws.Param('MarketplaceId', 'Id', true), + new mws.ParamList('SellerSKUList', 'SellerSKU', true), + ], {}, null, init + + # Same as above, except that it uses a MarketplaceId and an ASIN to uniquely + # identify a product, and it does not return the SKUIdentifier element + GetCompetitivePricingForASIN: class extends mws.Request + constructor: (init) -> + super MWS_PRODUCTS, 'GetCompetitivePricingForASIN', [ + new mws.Param('MarketplaceId', 'Id', true), + new mws.ParamList('ASINList','ASIN'), + ], {}, null, init + + # Returns the lowest price offer listings for a specific product by item condition. + GetLowestOfferListingsForSKU: class extends mws.Request + constructor: (init) -> + super MWS_PRODUCTS, 'GetLowestOfferListingsForSKU', [ + new mws.Param('MarketplaceId', 'Id', true), + new mws.ParamList('SellerSKUList', 'SellerSKU', true), + new enums.ItemCondition('ItemCondition'), + ], {}, null, init + + # Same as above but by a list of ASIN's you provide + GetLowestOfferListingsForASIN: class extends mws.Request + constructor: (init) -> + super MWS_PRODUCTS, 'GetLowestOfferListingsForASIN', [ + new mws.Param('MarketplaceId', 'Id', true), + new enums.ItemCondition('ItemCondition'), + new mws.ParamList('ASINList','ASIN'), + ], {}, null, init + + GetMyPriceForSKU: class extends mws.Request + constructor: (init) -> + super MWS_PRODUCTS, 'GetMyPriceForSKU', [ + new mws.Param('MarketplaceId', 'Id', true), + new mws.ParamList('SellerSKUList', 'SellerSKU', true), + new enums.ItemCondition('ItemCondition') + ], {}, null, init + + GetMyPriceForASIN: class extends mws.Request + constructor: (init) -> + super MWS_PRODUCTS, 'GetMyPriceForASIN', [ + new mws.Param('MarketplaceId', 'Id', true), + new enums.ItemCondition('ItemCondition'), + new mws.ParamList('ASINList', 'ASIN') + ], {}, null, init + + # Returns the product categories that a product belongs to, + # including parent categories back to the root for the marketplace + GetProductCategoriesForSKU: class extends mws.Request + constructor: (init) -> + super MWS_PRODUCTS, 'GetProductCategoriesForSKU', [ + new mws.Param('MarketplaceId', 'Id', true), + new mws.Param('SellerSKU', true), + ], {}, null, init + + # Same as above, except that it uses a MarketplaceId and an ASIN to + # uniquely identify a product. + GetProductCategoriesForASIN: class extends mws.Request + constructor: (init) -> + super MWS_PRODUCTS, 'GetProductCategoriesForASIN', [ + new mws.Param('MarketplaceId', 'Id', true), + new mws.Param('ASIN', true), + ], {}, null, init + + +# The products client notably supports an optional number of marketplaceIds for every +# query (except service status of course), which will default to @marketplaceIds (non-standard) +# or @marketplaceID (standard) before eventually throwing an error for missing required field +# It's easiest to set when calling constructor, me thinks. +class ProductsClient extends mws.Client + constructor: -> + super + + getServiceStatus: (cb) -> + @invoke new requests.GetServiceStatus(), {}, (res) => + status = res.result?.Status ? null + cb status, res + + listMatchingProducts: (query, context, cb) -> + req = new requests.ListMatchingProducts + MarketplaceId: @marketplaceId + Query: query + QueryContextId: context ? undefined + @invoke req, {}, (res) => + cb res + + getMatchingProduct: (asins, cb) -> + req = new requests.GetMatchingProduct + MarketplaceId: @marketplaceId + ASINList: asins ? [] + @invoke req, {}, (res) => + cb res + + getMatchingProductForId: (idType, ids , cb) -> + req = new requests.GetMatchingProductForId + MarketplaceId: @marketplaceId + IdType: idType + IdList: ids + @invoke req, {}, (res) => + cb res + + getCompetitivePricingForSKU: (skus, cb) -> + req = new requests.GetCompetitivePricingForSKU + MarketplaceId: @marketplaceId + SellerSKUList: skus ? [] + @invoke req, {}, (res) => + cb res + + getCompetitivePricingForASIN: (asins, cb) -> + req = new requests.GetCompetitivePricingForASIN + MarketplaceId: @marketplaceId + ASINList: asins ? [] + @invoke req, {}, (res) => + cb res + + getLowestOfferListingsForSKU: (skus, condition, cb) -> + req = new requests.GetLowestOfferListingsForSKU + MarketplaceId: @marketplaceId + SellerSKUList: skus ? [] + ItemCondition: condition ? undefined + @invoke req, {}, (res) => + cb res + + getLowestOfferListingsForASIN: (asins, condition, cb) -> + req = new requests.GetLowestOfferListingsForASIN + MarketplaceId: @marketplaceId + ASINList: asins ? [] + ItemCondition: condition ? undefined + @invoke req, {}, (res) => + cb res + + getMyPriceForSKU: (skus, condition, cb) -> + req = new requests.GetMyPriceForSKU + MarketplaceId: this.marketplaceId + SellerSKUList: skus ? [] + ItemCondition: condition ? undefined + @invoke req, {}, (res) => + cb res + + getMyPriceForASIN: (asins, condition, cb) -> + req = new requests.GetMyPriceForASIN + MarketplaceId: this.marketplaceId + ASINList: asins ? [] + ItemCondition: condition ? undefined + @invoke req, {}, (res) => + cb res + + getProductCategoriesForSKU: (sku, cb) -> + req = new requests.GetProductCategoriesForSKU + MarketplaceId: @marketplaceId + SellerSKU: sku + @invoke req, {}, (res) => + cb res + + getProductCategoriesForASIN: (asin, cb) -> + req = new requests.GetProductCategoriesForASIN + MarketplaceId: @marketplaceId + ASIN: asin + @invoke req, {}, (res) => + cb res + +module.exports = + service: MWS_PRODUCTS + enums: enums + requests: requests + Client: ProductsClient \ No newline at end of file diff --git a/src/reports.coffee b/src/reports.coffee new file mode 100644 index 0000000..e2b8ac2 --- /dev/null +++ b/src/reports.coffee @@ -0,0 +1,390 @@ +# ---------------------------------------------------------- +# mws-js • reports.coffee • by robbie saunders [eibbors.com] +# ---------------------------------------------------------- +# Description Soon +# ---------------------------------------------------------- + +mws = require "./core" + +MWS_REPORTS = new mws.Service + name: "Reports" + group: "Reports & Report Scheduling" + path: "/" + version: "2009-01-01" + legacy: true + +# Report types +reportTypes = + # Listing Reports + '_GET_FLAT_FILE_OPEN_LISTINGS_DATA_': + title: 'Inventory Report' + group: 'Listings' + format: 'flat' + request: true + '_GET_MERCHANT_LISTINGS_DATA_BACK_COMPAT_': + title: 'Open Listings Report' + group: 'Listings' + format: 'flat' + request: true + '_GET_MERCHANT_LISTINGS_DATA_': + title: 'Merchant Listings Report' + group: 'Listings' + format: 'flat' + request: true + '_GET_MERCHANT_LISTINGS_DATA_LITE_': + title: 'Merchant Listings Report - Lite' + group: 'Listings' + format: 'flat' + request: true + '_GET_MERCHANT_LISTINGS_DATA_LITER_': + title: 'Merchant Listings Report - Liter' + group: 'Listings' + format: 'flat' + request: true + '_GET_CONVERGED_FLAT_FILE_SOLD_LISTINGS_DATA': + title: 'Sold Listings Report' + group: 'Listings' + format: 'flat' + request: true + '_GET_MERCHANT_CANCELLED_LISTINGS_DATA_': + title: 'Canceled Listings Report' + group: 'Listings' + format: 'flat' + request: true + '_GET_MERCHANT_LISTINGS_DEFECT_DATA_': + title: 'Quality Listing Report' + group: 'Listings' + format: 'flat' + request: true + # General Order Reports + '_GET_FLAT_FILE_ACTIONABLE_ORDER_DATA_': + title: 'Unshipped Orders Report' + group: 'Orders' + format: 'flat' + request: true + '_GET_ORDERS_DATA_': + title: 'Scheduled XML Order Report' + group: 'Orders' + format: 'xml' + schedule: true + '_GET_FLAT_FILE_ORDER_REPORT_DATA_': + title: 'Flat File Order Report' + group: 'Orders' + format: 'flat' + request: true + '_GET_FLAT_FILE_ORDERS_DATA_': + title: 'Requested or Scheduled Flat File Order Report' + group: 'Orders' + format: 'flat' + schedule: true + request: true + '_GET_CONVERGED_FLAT_FILE_ORDER_REPORT_DATA_': + title: 'Flat File Order Report' + group: 'Orders' + format: 'flat' + schedule: true + request: true + # Order Tracking Reports + '_GET_FLAT_FILE_ALL_ORDERS_DATA_BY_LAST_UPDATE_': + title: 'Flat File Orders By Last Update Report' + group: 'Orders' + format: 'flat' + request: true + '_GET_FLAT_FILE_ALL_ORDERS_DATA_BY_ORDER_DATE_': + title: 'Flat File Orders By Order Date' + group: 'Orders' + format: 'flat' + request: true + '_GET_XML_ALL_ORDERS_DATA_BY_LAST_UPDATE_': + title: 'XML Orders By Last Update Report' + group: 'Orders' + format: 'xml' + request: true + '_GET_XML_ALL_ORDERS_DATA_BY_ORDER_DATE_': + title: 'XML Orders By Order Date' + group: 'Orders' + format: 'xml' + request: true + # Pending Order Reports + '_GET_FLAT_FILE_PENDING_ORDERS_DATA_': + title: 'Flat File Pending Orders Report' + group: 'Orders' + format: 'flat' + schedule: true + request: true + '_GET_PENDING_ORDERS_DATA_': + title: 'XML Pending Orders Report' + format: 'xml' + schedule: true + request: true + '_GET_CONVERGED_FLAT_FILE_PENDING_ORDERS_DATA_': + title: 'Converged Flat File Pending Orders Report' + group: 'Orders' + format: 'flat' + schedule: true + request: true + # Performance reports + '_GET_SELLER_FEEDBACK_DATA_': + title: 'Flat File Feedback' + group: 'Performance' + format: 'flat' + request: true + '_GET_AFN_INVENTORY_DATA_': + title: 'FBA Inventory Report' + group: 'Fulfillment' + format: 'flat' + request: true + +### +Ojects to represent enum collections used by some request(s) +@type {Object} +### +enums = + Schedule: class extends mws.Enum + constructor: -> + super("Schedule", ["_15_MINUTES_", "_30_MINUTES_", "_1_HOUR_", "_2_HOURS_", "_4_HOURS_", "_8_HOURS_", "_12_HOURS_", "_72_HOURS_", "_1_DAY_", "_2_DAYS_", "_7_DAYS_", "_14_DAYS_", "_15_DAYS_", "_30_DAYS_", "_NEVER_"], true) + + ReportProcessingStatusList: class extends mws.EnumList + constructor: -> + super("ReportTypeList","Status",["_SUBMITTED_", "_IN_PROGRESS_", "_CANCELLED_", "_DONE_", "_DONE_NO_DATA_"], false) + + ReportOptions: class extends mws.Enum + constructor: -> + super("ReportOptions", ["ShowSalesChannel=true", "ShowSalesChannel=false"], false) + + RequestableReportType: class extends mws.Enum + constructor: -> + reqReportsTypes = ( k for k,v of reportTypes when v.request ) + super("ReportType", reqReportsTypes, true) + + SchedulableReportType: class extends mws.Enum + constructor: -> + schedReportsTypes = ( k for k,v of reportTypes when v.schedule ) + super("ReportType", schedReportsTypes, true) + + ReportTypeList: class extends mws.EnumList + constructor: -> + reportTypesList = ( k for k,v of reportTypes when v.schedule ) + super("ReportTypeList", "Type", reportTypesList, false) + +### +A collection of currently supported request constructors. Once created and +configured, the returned requests can be passed to an mws client `invoke` call +@type {Object} +### +requests = + RequestReport: class extends mws.Request + constructor: (init) -> + super MWS_REPORTS , 'RequestReport', [ + new enums.RequestableReportType(), + new mws.Timestamp('StartDate'), + new mws.Timestamp('EndDate'), + new enums.ReportOptions(), + new mws.ParamList('MarketplaceIdList', 'Id'), + ], {}, null, init + + GetReportRequestList: class extends mws.Request + constructor: (init) -> + super MWS_REPORTS , 'GetReportRequestList', [ + new mws.ParamList('ReportRequestIdList', 'Id'), + new enums.ReportTypeList(), + new enums.ReportProcessingStatusList(), + new mws.Param('MaxCount'), + new mws.Timestamp('RequestedFromDate') + new mws.Timestamp('RequestedToDate') + ], {}, null, init + + GetReportRequestListByNextToken: class extends mws.Request + constructor: (init) -> + super MWS_REPORTS , 'GetReportRequestListByNextToken', [ + new mws.Param('NextToken', true), + ], {}, null, init + + GetReportRequestCount: class extends mws.Request + constructor: (init) -> + super MWS_REPORTS , 'GetReportRequestCount', [ + new enums.ReportTypeList(), + new enums.ReportProcessingStatusList(), + new mws.Timestamp('RequestedFromDate') + new mws.Timestamp('RequestedToDate') + ], {}, null, init + + CancelReportRequests: class extends mws.Request + constructor: (init) -> + super MWS_REPORTS , 'CancelReportRequests', [ + new mws.ParamList('ReportRequestIdList', 'Id'), + new enums.ReportTypeList(), + new enums.ReportProcessingStatusList(), + new mws.Timestamp('RequestedFromDate') + new mws.Timestamp('RequestedToDate') + ], {}, null, init + + GetReportList: class extends mws.Request + constructor: (init) -> + super MWS_REPORTS , 'GetReportList', [ + new mws.Param('MaxCount'), + new enums.ReportTypeList(), + new mws.Bool('Acknowledged'), + new mws.Timestamp('AvailableFromDate') + new mws.Timestamp('AvailableToDate') + new mws.ParamList('ReportRequestIdList', 'Id'), + ], {}, null, init + + GetReportListByNextToken: class extends mws.Request + constructor: (init) -> + super MWS_REPORTS , 'GetReportListByNextToken', [ + new mws.Param('NextToken', true), + ], {}, null, init + + GetReportCount: class extends mws.Request + constructor: (init) -> + super MWS_REPORTS , 'GetReportCount', [ + new enums.ReportTypeList(), + new mws.Bool('Acknowledged'), + new mws.Timestamp('AvailableFromDate') + new mws.Timestamp('AvailableToDate') + ], {}, null, init + + GetReport: class extends mws.Request + constructor: (init) -> + super MWS_REPORTS , 'GetReport', [ + new mws.Param('ReportId', true) + ], {}, null, init + + ManageReportSchedule: class extends mws.Request + constructor: (init) -> + super MWS_REPORTS , 'ManageReportSchedule', [ + new enums.SchedulableReportType(), + new enums.Schedule(), + new mws.Timestamp('ScheduledDate') + ], {}, null, init + + GetReportScheduleList: class extends mws.Request + constructor: (init) -> + super MWS_REPORTS , 'GetReportScheduleList', [ + new enums.ReportTypeList(), + ], {}, null, init + + GetReportScheduleListByNextToken: class extends mws.Request + constructor: (init) -> + super MWS_REPORTS , 'GetReportScheduleListByNextToken', [ + new mws.Param('NextToken', true), + ], {}, null, init + + GetReportScheduleCount: class extends mws.Request + constructor: (init) -> + super MWS_REPORTS , 'GetReportScheduleCount', [ + new enums.ReportTypeList(), + ], {}, null, init + + UpdateReportAcknowledgements: class extends mws.Request + constructor: (init) -> + super MWS_REPORTS , 'UpdateReportAcknowledgements', [ + new mws.ParamList('ReportIdList', 'Id', true), + new mws.Bool('Acknowledged'), + ], {}, null, init + +# New client class providing more convenient access to service via camelCased +# versions of the request as methods. +class ReportsClient extends mws.Client + # callback gets (reportReqInfo, res) + requestReport: (options, cb)-> + req = new requests.RequestReport options + @invoke req, {}, (res) => + reportReqInfo = res.result?.ReportRequestInfo ? null + cb reportReqInfo , res + + # callback gets (reportReqInfoList, res) + getReportRequestList: (options, cb)-> + req = new requests.GetReportRequestList options + @invoke req, { nextTokenCall: requests.GetReportRequestListByNextToken, nextTokenCallUseHasNext: true }, (res) => + reportReqInfoList = res.result?.ReportRequestInfo ? null + cb reportReqInfoList, res + + # callback gets (reportReqInfoList, res) + getReportRequestListByNextToken: (token, cb)-> + req = new requests.GetReportRequestListByNextToken {NextToken: token} + @invoke req, { nextTokenCall: requests.GetReportRequestListByNextToken, nextTokenCallUseHasNext: true }, (res) => + reportReqInfoList = res.result?.ReportRequestInfo ? null + cb reportReqInfoList, res + + # Callback function should be (count, res) -> + getReportRequestCount: (options, cb)-> + req = new requests.GetReportRequestCount options + @invoke req, {}, (res) => + count = res.result?.Count ? null + cb count, res + + # callback gets (canceledReportReqInfoList, res) + cancelReportRequests: (options, cb)-> + req = new requests.CancelReportRequests options + @invoke req, {}, (res) => + canceledReportReqInfoList = res.result?.ReportRequestInfo ? null + cb canceledReportReqInfoList, res + + # callback gets (reportInfo, res) + getReportList: (options, cb)-> + req = new requests.GetReportList options + @invoke req, { nextTokenCall: requests.GetReportListByNextToken, nextTokenCallUseHasNext: true }, (res) => + reportInfo = res.result?.ReportInfo ? null + cb reportInfo, res + + getReportListByNextToken: (token, cb)-> + req = new requests.GetReportListByNextToken {NextToken: token} + @invoke req, { nextTokenCall: requests.GetReportListByNextToken, nextTokenCallUseHasNext: true }, (res) => + reportInfo = res.result?.ReportInfo ? null + cb reportInfo, res + + # Callback function should be (count, res) -> + getReportCount: (options, cb)-> + req = new requests.GetReportCount options + @invoke req, {}, (res) => + count = res.result?.Count ? null + cb count, res + + # Callback function should be (report, res) -> + getReport: (options, cb)-> + req = new requests.GetReport options + @invoke req, { allowedContentTypes: [ 'application/octet-stream' ] }, (res) => + report = res.response + cb report, res + + # Callback function should be (reportSchedules, res) -> + manageReportSchedule: (options, cb)-> + req = new requests.ManageReportSchedule options + @invoke req, {}, (res) => + reportSchedules = res.result?.ReportSchedule ? null + cb reportSchedules , res + + # Callback function should be (reportSchedule, res) -> + getReportScheduleList: (options, cb)-> + req = new requests.GetReportScheduleList options + @invoke req, { nextTokenCall: requests.GetReportScheduleListByNextToken }, (res) => + reportSchedule = res.result?.ReportSchedule ? null + cb reportSchedule, res + + getReportScheduleListByNextToken: (token, cb)-> + req = new requests.GetReportScheduleListByNextToken {NextToken: token} + @invoke req, { nextTokenCall: requests.GetReportScheduleListByNextToken }, (res) => + reportSchedule = res.result?.ReportSchedule ? null + cb reportSchedule, res + + # Callback function should be (count, res) -> + getReportScheduleCount: (options, cb)-> + req = new requests.GetReportScheduleCount options + @invoke req, {}, (res) => + count = res.result?.Count ? null + cb count, res + + # Callback function should be (reportInfo, res) -> + updateReportAcknowledgements: (options, cb)-> + req = new requests.UpdateReportAcknowledgements options + @invoke req, {}, (res) => + reportInfo = res.result?.ReportInfo ? null + cb reportInfo , res + +module.exports = + service: MWS_REPORTS + enums: enums + requests: requests + Client: ReportsClient \ No newline at end of file diff --git a/src/sellers.coffee b/src/sellers.coffee new file mode 100644 index 0000000..0b661d6 --- /dev/null +++ b/src/sellers.coffee @@ -0,0 +1,66 @@ +# ---------------------------------------------------------- +# mws-js • sellers.coffee • by robbie saunders [eibbors.com] +# ---------------------------------------------------------- +# Dead simple merchant (seller) query module. Lists marketplaces +# and participations per your account. Das ist all at the moment +# ---------------------------------------------------------- + +mws = require './core' + +# MWS API Group configuration for Order Retrieval +MWS_SELLERS = new mws.Service + name: "Sellers" + group: "Sellers Retrieval" + path: "/Sellers/2011-07-01" + version: "2011-07-01" + legacy: false + +# Simple types +types = + ServiceStatus: mws.types.ServiceStatus + +requests = + + GetServiceStatus: class extends mws.Request + constructor: (init) -> + super MWS_SELLERS, 'GetServiceStatus', [], {}, null, init + + ListMarketplaceParticipations: class extends mws.Request + constructor: (init) -> + super MWS_SELLERS, 'ListMarketplaceParticipations', [], {}, null, init + + ListMarketplaceParticipationsByNextToken: class extends mws.Request + constructor: (init) -> + super MWS_SELLERS, 'ListMarketplaceParticipationsByNextToken', [new mws.Param('NextToken', true)], {}, null, init + +# Sellers API Client +class SellersClient extends mws.Client + + # The standard mws GetServiceStatus request. Callback function should be of the form + # (status, response) -> # ... + getServiceStatus: (cb) -> + @invoke new requests.GetServiceStatus(), {}, (res) => + status = res.result?.Status ? null + cb status, res + + listMarketplaceParticipations: (cb) -> + opt = { nextTokenCall: requests.ListMarketplaceParticipationsByNextToken } + req = new requests.ListMarketplaceParticipations() + @invoke req, opt, (res) => + markets = res?.ListMarketplaces?.Marketplace ? null + partips = res?.ListParticipations?.Participation ? null + cb {marketplaces: markets, participations: partips }, res + + listMarketplaceParticipationsByNextToken: (token, cb) -> + opt = { nextTokenCall: requests.ListMarketplaceParticipationsByNextToken } + req = new requests.ListMarketplaceParticipationsByNextToken(NextToken: token) + @invoke req, opt, (res) => + markets = res?.ListMarketplaces?.Marketplace ? null + partips = res?.ListParticipations?.Participation ? null + cb {marketplaces: markets, participations: partips }, res + +module.exports = + service: MWS_SELLERS + types: types + requests: requests + Client: SellersClient \ No newline at end of file diff --git a/test/.gitignore b/test/.gitignore new file mode 100644 index 0000000..57ab303 --- /dev/null +++ b/test/.gitignore @@ -0,0 +1 @@ +cfg.coffee diff --git a/test/cfg.coffee.sample b/test/cfg.coffee.sample new file mode 100644 index 0000000..cc8e77c --- /dev/null +++ b/test/cfg.coffee.sample @@ -0,0 +1,9 @@ +module.exports = + loginInfo: + locale: 'DE' + merchantId: 'XXXXXXX' + marketplaceId: 'XXXXXXX' + accessKeyId: 'XXXXXXX' + secretAccessKey: 'XXXXX' + dump: console.dir + print: console.log diff --git a/test/fba.coffee b/test/fba.coffee new file mode 100644 index 0000000..143e0fd --- /dev/null +++ b/test/fba.coffee @@ -0,0 +1,31 @@ +fba = require '../src/fba' +core = require '../src/core' +# { locales } = require '../src/core' +{ loginInfo, dump, print } = require './cfg' + +# client = new fba.inbound.Client(loginInfo) +# p = +# id: new core.Param('DisplayableOrderId', true) +# dateTime: new core.Timestamp('DisplayableOrderDateTime', false) +# comment: new core.Param('DisplayableOrderComment', false) + +# cx = new core.ComplexParam('DisplayableOrder',p, true) +dor = new fba.complex.DisplayableOrder( undefined, true, { id: '15555afafaf5555', comment: 'test comment' }) +dump dor.get('ASD') +dump dor.render() +# address = fba.complex +# console.log fba.complex.DisplayableOrder + +# dorder = new fba.complex.DisplayableOrder() +# print 'address', address + +# # Simple service status check +# client.getServiceStatus (status, res) => +# print "Products service status", status +# # Quick verification of optimum service status +# unless status in ['GREEN', 'GREEN_I'] +# throw 'Products service is having issues, aborting...' + +# # client.listMarketplaceParticipations (goodies, res) => +# # print "The good stuff", goodies +# # dump res \ No newline at end of file diff --git a/test/feeds.coffee b/test/feeds.coffee new file mode 100644 index 0000000..1db26c3 --- /dev/null +++ b/test/feeds.coffee @@ -0,0 +1,32 @@ +util = require 'util' +feeds = require '../src/feeds' +{ loginInfo, dump, print } = require './cfg' + +client = new feeds.Client(loginInfo) + + +# Simple service status check +client.getServiceStatus (status, res) => + print "Feeds service status", status + # Quick verification of optimum service status + unless status in ['GREEN', 'GREEN_I'] + throw 'Feeds service is having issues, aborting...' + + client.getFeedSubmissionList { + 'MaxCount': 3 + 'FeedProcessingStatusList': {'_DONE_': true} + 'SubmittedFromDate': '2013-01-01' + 'SubmittedToDate': '2013-12-31' + # 'FeedTypeList': {'_POST_PRODUCT_PRICING_DATA_': true} + }, (res) => + if res.error + console.error res.error + else if res.result + console.log util.inspect(res.result,false,10) + res.result.FeedSubmissionInfo = [res.result.FeedSubmissionInfo] unless Array.isArray res.result.FeedSubmissionInfo + for i,info of res.result.FeedSubmissionInfo when info + client.getFeedSubmissionResult info.FeedSubmissionId, (res) => + if res.error + console.error res.error + else if res.response + console.log util.inspect(res.response,false,10) diff --git a/test/orders.coffee b/test/orders.coffee new file mode 100644 index 0000000..4872718 --- /dev/null +++ b/test/orders.coffee @@ -0,0 +1,58 @@ +orders = require '../src/orders' +{ loginInfo, dump, print } = require './cfg' + +client = new orders.Client(loginInfo) + +# You can uncomment these to log / dump client data as triggered by +# the event system. +# client.on 'request', dump +# client.on 'response', dump +# client.on 'error', console.log + +# Start out by checking the orders service status +client.getServiceStatus (status, res) => + print "Orders Service Status", status + if status isnt 'GREEN' + print "Abnormal ServiceStatus response", res + return console.log "aborting..." + + # List orders created after 10-01-2011 which will almost definitely return more than + # the max number per request. Change this to an older date, if not + client.listOrders { CreatedAfter: '10-01-2011' }, (orders, res) => + if orders + if Array.isArray(orders) + order = orders[0] + size = orders.length + else + order = orders + size = 1 + print "First order of #{size} returned", order + else + print "Invalid or empty ListOrders response", res + + # Sample of requesting more results using NextToken + if res.nextToken? + print "Requesting additional orders using formal NextToken request", res.nextToken + + # The formal method is more clear to those reading your code, but... (see callback) + client.listOrdersByNextToken res.nextToken, (orders, res) => + if orders then console.log "Retrieved #{orders.length ? 1} order(s)" + else print "NextToken response with no orders", res + + # You can also call getNext on any response with NextToken support + if res.nextToken? + res.getNext (orders, res) => + "Retrieved #{orders.length ? 1} order(s)" + + # Using the orders from above to issue GetOrder request + client.getOrder order.AmazonOrderId, (o, res) => + print "Order returned by GetOrder", o + print "Matches order from before", order.AmazonOrderId is o.AmazonOrderId + + # Demonstrate the listing of single order's item details + client.listOrderItems orders[5].AmazonOrderId, (items, res) => + print "Order items for #{orders[5].AmazonOrderId} (fifth result from before)", items + # I don't have any sample data able to trigger this, but the same concept as + # above should apply here, as well. + if res.nextToken? + res.getNext dump diff --git a/test/products.coffee b/test/products.coffee new file mode 100644 index 0000000..5cba7ef --- /dev/null +++ b/test/products.coffee @@ -0,0 +1,20 @@ +util = require 'util' +products = require '../src/products' +{ loginInfo, dump, print } = require './cfg' + +client = new products.Client(loginInfo) + + +# Simple service status check +client.getServiceStatus (status, res) => + print "Products service status", status + # Quick verification of optimum service status + unless status in ['GREEN', 'GREEN_I'] + throw 'Products service is having issues, aborting...' + + client.getMatchingProductForId 'ASIN', 'B00BY7IZQE' , (res) => + if res.error + console.error res.error + else if res.result + console.log util.inspect(res.result,false,10) + \ No newline at end of file diff --git a/test/reports.coffee b/test/reports.coffee new file mode 100644 index 0000000..f0d138a --- /dev/null +++ b/test/reports.coffee @@ -0,0 +1,84 @@ +reports= require '../src/reports' +# { locales } = require '../src/core' +{ loginInfo, dump, print } = require './cfg' +fs = require 'fs' + +client = new reports.Client(loginInfo) +# +# Fetch all reports in files +# +client.getReportList {}, (reportInfoList,res)-> + for reportInfo in reportInfoList + print "Fetching report: #{ reportInfo.ReportId } with type: #{ reportInfo.ReportType }" + do (reportInfo) -> + client.getReport {ReportId : reportInfo.ReportId }, (report, res)-> + id = reportInfo.ReportId + file = "report-#{ id }.txt" + if res?.responseType is 'Error' + print "failed to fetch report with id : #{ id }" + print res?.error + #print res?.responseWithInvalidMD5 + else + print "Writing #{ report.length } bytes to #{ file }" + fs.writeFileSync(file, report) + if res.nextToken? + res.getNext() + + +# +# Some example calls +# +# #Get report count +# client.getReportCount {}, (count, res)-> +# console.log "Count :" + count + +# # List all reports 4 result per call , uses NextToken +# client.getReportList {MaxCount : 4}, (reportInfo,res)-> +# console.log "====================================" +# console.log reportInfo +# if res.nextToken? +# res.getNext() + +# # List all reports Schedules +# client.getReportScheduleList {}, (reportSchedule,res)-> +# console.log "====================================" +# console.log reportSchedule +# if res.nextToken? +# res.getNext() + +# #Get report schedule count +# client.getReportScheduleCount {}, (count, res)-> +# console.log "Count: " + count + +# # Get report data +# client.getReport {ReportId : '16038618804'}, (report, res)-> +# file = 'report.txt' +# console.log "Writing #{ report.length } bytes to #{ file }" +# require('fs').writeFileSync(file, report) + +# # Request report +# client.requestReport {ReportType: '_GET_FLAT_FILE_OPEN_LISTINGS_DATA_', StartDate: '2013-01-01'}, (repReqInfo,res)-> +# console.log repReqInfo + +# # List all reports requests 4 result per call , uses NextToken +# client.getReportRequestList {MaxCount: 4}, (repReqList,res)-> +# console.log "====================================" +# console.log repReqList +# if res.nextToken? +# res.getNext() + +# # Get report requests count +# client.getReportRequestCount {}, (count, res)-> +# console.log "Count: " +count + +# # Cancel all requests +# client.cancelReportRequests {}, (canceledReportReqInfoList, res)-> +# console.log "Canceled: " , canceledReportReqInfoList + +# # Set report as aknowledged +# client.updateReportAcknowledgements {ReportIdList: '16038618804', Acknowledged: true}, (updatedReportInfoList, res)-> +# console.log "Updated: " , updatedReportInfoList + +# #Schedule a report to be generated every day +# client.manageReportSchedule {ReportType: '_GET_ORDERS_DATA_', Schedule: '_1_DAY_'}, (reportSchedules, res)-> +# console.log "Scheduled: " , reportSchedules diff --git a/test/sellers.coffee b/test/sellers.coffee new file mode 100644 index 0000000..11b90ce --- /dev/null +++ b/test/sellers.coffee @@ -0,0 +1,17 @@ +sellers = require '../src/sellers' +{ loginInfo, dump, print } = require './cfg' + +client = new sellers.Client(loginInfo) + +# print 'Sellers Client', client + +# Simple service status check +client.getServiceStatus (status, res) => + print "Sellers service status", status + # Quick verification of optimum service status + unless status in ['GREEN', 'GREEN_I'] + throw 'Seller service is having issues, aborting...' + + client.listMarketplaceParticipations (goodies, res) => + print "The good stuff", goodies + dump res \ No newline at end of file