Skip to content

Commit

Permalink
Various improvements
Browse files Browse the repository at this point in the history
  • Loading branch information
merlinND committed Jun 10, 2014
1 parent 66f387e commit 2b1b584
Show file tree
Hide file tree
Showing 3 changed files with 60 additions and 37 deletions.
2 changes: 1 addition & 1 deletion config/configuration.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,5 @@ module.exports = {
aliases: require('../config/json/aliases.json'),
documentRelatedEndpoints: require('../config/json/document-related-endpoints.json'),

apiHost: 'https://api.anyfetch.com'
apiHost: process.env.API_HOST || 'https://api.anyfetch.com'
};
16 changes: 12 additions & 4 deletions config/json/document-related-endpoints.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,14 @@
{
"getSimilar": { "endpoint": "/documents/{id}/similar" },
"getRelated": { "endpoint": "/documents/{id}/related" },
"getRaw": { "endpoint": "/documents/{id}/raw" },
"getFile": { "endpoint": "/documents/{id}/file" }
"getSimilar": {
"endpoint": "/documents/{id}/similar"
},
"getRelated": {
"endpoint": "/documents/{id}/related"
},
"getRaw": {
"endpoint": "/documents/{id}/raw"
},
"getFile": {
"endpoint": "/documents/{id}/file"
}
}
79 changes: 47 additions & 32 deletions lib/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,15 @@ var accessToken = process.env.ACCESS_TOKEN;

var anyfetchRequest = request(configuration.apiHost);

/**
* Determine if `f` is a function
*/
var isFunction = function(f) {
return !!(f && f.constructor && f.call && f.apply);
};

/**
* Will be used to automatically generate the simplest mapping functions
* @see api.anyfetch.com/config/routes.js
*/
var generateMapping = function(config, name) {
// `config` extends the default descriptor
Expand All @@ -37,13 +43,8 @@ var generateMapping = function(config, name) {
* apiMapping(params, cb)
*/
return function apiMapping() {
var argErrorMessage = 'Argument error in ' + name + ':';

// Convert arguments to an array
var args = [];
for (var i in arguments) {
args.push(arguments[i]);
}
var args = Array.prototype.slice.call(arguments);

// We must support quite a lot of different call syntaxes
var params = {};
Expand All @@ -52,16 +53,16 @@ var generateMapping = function(config, name) {
// cb is always the last argument
var cb = args.pop();
// cb must be a function
if (!(cb && cb.constructor && cb.call && cb.apply)) {
throw new Error(argErrorMessage + ' the last argument must be a function (callback)');
if (!isFunction(cb)) {
throw new Error('Argument error in ' + name + ':' + ' the last argument must be a function (callback)');
}

if (config.body) {
body = args.pop() || {};
// Make sure that every field of the body is accepted
for(var key in body) {
if(config.body.indexOf(key) === -1) {
return cb(new Error(argErrorMessage + ' the key ' + key + ' is not allowed in this request\'s body'));
return cb(new Error('Argument error in ' + name + ':' + ' the key ' + key + ' is not allowed in this request\'s body'));
}
}
}
Expand All @@ -71,7 +72,7 @@ var generateMapping = function(config, name) {
// Make sure that every GET parameter is accepted
for(var key in params) {
if(config.params.indexOf(key) === -1) {
return cb(new Error(argErrorMessage + ' the key ' + key + ' is not allowed in this request\'s GET parameters'));
return cb(new Error('Argument error in ' + name + ':' + ' the key ' + key + ' is not allowed in this request\'s GET parameters'));
}
}
}
Expand All @@ -80,7 +81,7 @@ var generateMapping = function(config, name) {
if(config.requireId) {
var id = args.pop();
if(isNaN(id)) {
return cb(new Error('Argument error, the first parameter must be a numeric id'));
return cb(new Error('Argument error in ' + name + ':' + ' the first parameter must be a numeric id'));
}

// Substitute id parameter in endpoint string
Expand Down Expand Up @@ -141,38 +142,52 @@ var generateAliases = function(mappingFunctions) {
var generateAdvancedMappings = function(mappingFunctions) {
// ----- Documents
var getDocumentByIdCb = mappingFunctions.getDocumentById;
mappingFunctions.getDocumentById = function() {
// Invalid call syntax
if (arguments.length > 2 || isNaN(arguments[0])) {
// We assume the last argument is a callback
arguments[arguments.length - 1](new Error('Invalid call syntax'));
}
var id = arguments[0];

/**
* Support two call syntaxes:
* - Single step: getDocumentById(123, cb)
* - Two steps: getDocumentById(123).getRelated(cb)
*/
mappingFunctions.getDocumentById = function(id, cb) {

// Single-step call syntax
// getDocumentById(123, cb)
if (arguments.length === 2) {
if (isFunction(cb)) {
if (isNaN(id)) {
return cb(new Error('Argument error in getDocumentById: the first argument must be a numeric id'));
}
return getDocumentByIdCb(id, arguments[1]);
}

// Two-step call syntax
// getDocumentById(123).getRelated(cb)
var secondStep = {};
for (var name in configuration.documentRelatedEndpoints) {
var opt = {
endpoint: configuration.documentRelatedEndpoints[name].endpoint.replace('{id}', id)
var opt = configuration.documentRelatedEndpoints[name];
// Trick: "hardcode" id parameter in endpoint and proceed as usual
opt.endpoint = opt.endpoint.replace('{id}', id);

secondStep[name] = function(){
if (isNaN(id)) {
// We assume the last parameter is a callback
var cb = arguments[arguments.length - 1];
return cb(new Error('Argument error in getDocumentById: the first argument must be a numeric id'));
}

generateMapping(opt, name).apply(this, arguments);
};
secondStep[name] = generateMapping(opt, name);
}

/**
* Add a file to a previously uploaded document
*
* @param {Object} Must at least contain a `file` key, which can either be a stream (e.g. `fs.createReadStream`) or a Buffer object. Can also contains a `contentType` key (for MIME type), and a `filename`.
* @param {Function} cb Callback with error if any.
* @Warning: unfortunately, due to the variety of Stream, we can't type-check, so unexpected errors will occur if you specify weird file parameters.
*/
/**
* Add a file to a previously uploaded document
*
* @param {Object} Must at least contain a `file` key, which can either be a stream (e.g. `fs.createReadStream`) or a Buffer object. Can also contains a `contentType` key (for MIME type), and a `filename`.
* @param {Function} cb Callback with error if any.
* @Warning: unfortunately, due to the variety of Stream, we can't type-check, so unexpected errors will occur if you specify weird file parameters.
*/
secondStep.postFile = function(config, cb) {
if (isNaN(id)) {
return cb(new Error('Argument error in getDocumentById: the first argument must be a numeric id'));
}

if(typeof(config) === 'function') {
config = config();
}
Expand Down

0 comments on commit 2b1b584

Please sign in to comment.