Skip to content

Commit

Permalink
Remove dependency on underscore
Browse files Browse the repository at this point in the history
  • Loading branch information
hakanensari committed Feb 6, 2012
1 parent 7d81786 commit 4493de4
Show file tree
Hide file tree
Showing 10 changed files with 306 additions and 118 deletions.
6 changes: 4 additions & 2 deletions lib/vacuum/index.js
@@ -1,3 +1,5 @@
require('coffee-script');
(function() {

module.exports = require('./request');
module.exports = require('./request');

}).call(this);
115 changes: 115 additions & 0 deletions lib/vacuum/request.js
@@ -0,0 +1,115 @@
(function() {
var Request, Response, crypto, http;

crypto = require('crypto');

http = require('http');

Response = require('./response');

Request = (function() {
var CURRENT_API_VERSION, HOSTS;

CURRENT_API_VERSION = '2011-08-01';

HOSTS = {
ca: 'ecs.amazonaws.ca',
cn: 'webservices.amazon.cn',
de: 'ecs.amazonaws.de',
es: 'webservices.amazon.es',
fr: 'ecs.amazonaws.fr',
it: 'webservices.amazon.it',
jp: 'ecs.amazonaws.jp',
uk: 'ecs.amazonaws.co.uk',
us: 'ecs.amazonaws.com'
};

function Request(options) {
var locale;
locale = options.locale || 'us';
this._key = options.key || (function() {
throw 'Missing key';
})();
this._secret = options.secret || (function() {
throw 'Missing secret';
})();
this._tag = options.tag || (function() {
throw 'Missing associate tag';
})();
this._host = HOSTS[locale] || (function() {
throw 'Bad locale';
})();
this.reset();
}

Request.prototype.add = function(params) {
var key, val;
for (key in params) {
val = params[key];
if (val.constructor === Array) val = val.join(',');
key = key[0].toUpperCase() + key.slice(1);
this._params[key] = val;
}
return this;
};

Request.prototype.get = function(callback, errback) {
var options;
if (errback == null) errback = function() {};
options = {
host: this._host,
path: "/onca/xml?" + (this._query())
};
return http.get(options, function(res) {
var data;
data = '';
return res.on('data', function(chunk) {
return data += chunk;
}).on('end', function() {
return callback(new Response(data, res.statusCode));
}).on('error', function(e) {
return errback(e);
});
});
};

Request.prototype.reset = function() {
this._params = {
AWSAccessKeyId: this._key,
AssociateTag: this._tag,
Service: 'AWSECommerceService',
Timestamp: new Date().toISOString(),
Version: CURRENT_API_VERSION
};
return this;
};

Request.prototype._query = function() {
var hmac, key, query, signature, val;
query = ((function() {
var _ref, _results;
_ref = this._params;
_results = [];
for (key in _ref) {
val = _ref[key];
_results.push([key, val]);
}
return _results;
}).call(this)).sort(function(self, other) {
return self[0] > other[0];
}).map(function(tuple) {
return "" + tuple[0] + "=" + (encodeURIComponent(tuple[1]));
}).join('&');
hmac = crypto.createHmac('sha256', this._secret);
hmac.update(['GET', this._host, '/onca/xml', query].join("\n"));
signature = hmac.digest('base64');
return "" + query + "&Signature=" + (encodeURIComponent(signature));
};

return Request;

})();

module.exports = Request;

}).call(this);
40 changes: 0 additions & 40 deletions lib/vacuum/response.coffee

This file was deleted.

67 changes: 67 additions & 0 deletions lib/vacuum/response.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 1 addition & 3 deletions package.json
Expand Up @@ -17,12 +17,10 @@
"url":"git://github.com/hakanensari/vacuum.git"
},
"dependencies":{
"coffee-script":"*",
"crypto":"*",
"libxmljs":"*",
"underscore":"*"
},
"devDependencies":{
"coffee-script":"*",
"jasmine-node":"*"
},
"engines":{
Expand Down
20 changes: 9 additions & 11 deletions spec/vacuum/request_spec.coffee
@@ -1,4 +1,4 @@
Request = require '../../lib/vacuum/request'
Request = require '../../src/vacuum/request'

describe 'Request', ->
beforeEach ->
Expand Down Expand Up @@ -29,17 +29,8 @@ describe 'Request', ->
secret: 'bar'
.toThrow 'Missing associate tag'

it 'requires a valid locale', ->
expect ->
new Request
key: 'foo'
secret: 'bar'
tag: 'secret'
locale: 'invalid'
.toThrow 'Bad Locale'

it 'defaults locale to the US', ->
expect(@req._host).toMatch /\.com/
expect(@req.locale).toBe 'us'

it 'sets up the parameters with default values', ->
expect(@req._params.Timestamp).toBeDefined()
Expand All @@ -62,6 +53,13 @@ describe 'Request', ->
runs ->
expect(@res.constructor).toMatch /Response/

describe '#host', ->
it 'requires a valid locale', ->
@req.locale = 'invalid'
expect =>
@req.host()
.toThrow 'Bad locale'

describe '#reset', ->
it 'resets the parameters to default values', ->
expect(@req.add(foo: 1).reset.foo).toBeUndefined()
Expand Down
52 changes: 24 additions & 28 deletions spec/vacuum/response_spec.coffee
@@ -1,38 +1,34 @@
fs = require 'fs'
libxmljs = require 'libxmljs'
Response = require '../../lib/vacuum/response'
Response = require '../../src/vacuum/response'

describe 'Response', ->
beforeEach ->
data = fs.readFileSync("#{__dirname}/../fixtures/response", 'utf8')
@res = new Response data, 200

describe '#find', ->
it 'returns an array of matches', ->
expect(@res.find('Item').constructor).toBe Array
expect(@res.find('Item')[0]['ASIN'].constructor).toBe String

describe '#_xmlToObject', ->
beforeEach ->
data = '<?xml version="1.0" ?>' +
'<Item>' +
'<Title>A Title</Title>' +
'<Author>An Author</Author>' +
'<Author>Another Author</Author>' +
'<Creator Role="Translator">A Translator</Creator>' +
'</Item>'
doc = libxmljs.parseXmlString(data)
@obj = @res._xmlToObject doc.root()

it 'returns an object', ->
expect(@obj.constructor).toBe Object

it 'handles children with no siblings', ->
expect(@obj['Title']).toBe 'A Title'

it 'handles children with siblings', ->
expect(@obj['Author'].constructor).toBe Array

it 'handles attributes', ->
expect(@obj['Creator']['Role']).toBe 'Translator'
expect(@obj['Creator']['__content__']).toBe 'A Translator'
@items = @res.find('Item')

it 'returns matches to a given query', ->
expect(@items.length).toBeGreaterThan 0

it 'returns an empty array if there are no matches', ->
expect(@res.find('foo-bar-baz').length).toBe 0

it 'parses nodes with no siblings', ->
expect(@items[0]['ASIN']).toBeDefined()

it 'parses nodes with siblings', ->
itemLinks = @items[0]['ItemLinks']['ItemLink']
expect(itemLinks.length).toBeGreaterThan 0

it 'parses nodes with attributes', ->
creator = @items[0]['ItemAttributes']['Creator']
expect(creator['Role']).toBeDefined()
expect(creator['__content']).toBeDefined()

describe '#toObject', ->
it 'returns entire response as an object', ->
expect(@res.toObject().constructor).toBe Object
1 change: 1 addition & 0 deletions src/vacuum/index.coffee
@@ -0,0 +1 @@
module.exports = require './request'

0 comments on commit 4493de4

Please sign in to comment.