Commit caf027f7 by 3rd-Eden

[init] Initial bindings to the FullContact API

parents
node_modules
60671
\ No newline at end of file
'use strict';
function Name(api) {
this.api = api;
this.endpoint = 'https://api.fullcontact.com/v2/name/';
this.send = api.process.bind(api, this);
}
/**
* Normalize a name.
*
* ```js
* fullcontact.name.normalize('John Smith', [casing], fn);
* ```
*
* @returns {Name}
* @api public
*/
Name.prototype.normalize = function normalize() {
var args = this.api.args(arguments, 'casing');
//
// Add a custom endpoint
//
args.endpoint = this.endpoint +'normalizer.json';
this.send({ q: args.value }, args);
return this;
};
/**
* Name deducing.
*
* ```js
* fullcontact.name.deducer({ email: 'opensource@observe.it' }, [casing], fn);
* fullcontact.name.deducer({ username: '3rdEden' }, [casing], fn);
* ```
*
* @returns {Name}
* @api public
*/
Name.prototype.deducer = function deducer() {
var args = this.api.args(arguments, 'casing');
//
// Add a custom endpoint
//
args.endpoint = this.endpoint +'deducer.json';
this.send(args.value, args);
return this;
};
/**
* Check the similairity of between two names.
*
* ```js
* fullcontact.name.similarity('john', 'johnny', [casing], fn);
* ```
*
* @returns {Name}
* @api public
*/
Name.prototype.similarity = function similarity() {
var args = this.api.args(arguments, 'q2', 'casing');
//
// Add a custom endpoint
//
args.endpoint = this.endpoint +'similarity.json';
this.send({ q1: args.value, q2: args.q2 }, args);
return this;
};
/**
* Retrieve some statistics about the name.
*
* ```js
* fullcontact.name.stats({ name: 'john' }, [casing], fn);
* fullcontact.name.stats({ givenName: 'john' }, [casing], fn);
* fullcontact.name.stats({ familyName: 'smith' }, [casing], fn);
* fullcontact.name.stats({ givenName: 'john', familyName: 'smith' }, [casing], fn);
* ```
*
* @returns {Name}
* @api public
*/
Name.prototype.stats = function stats() {
var args = this.api.args(arguments, 'casing');
//
// Add a custom endpoint
//
args.endpoint = this.endpoint +'stats.json';
this.send(args.value, args);
return this;
};
/**
* Parses the name to determin the likelyhoot that this is really a name.
*
* ```js
* fullcontact.name.parser('john smith', [casing], fn);
* ```
*
* @returns {Name}
* @api public
*/
Name.prototype.parser = function parser() {
var args = this.api.args(arguments, 'casing');
//
// Add a custom endpoint
//
args.endpoint = this.endpoint +'parser.json';
this.send({ q: args.value }, args);
return this;
};
//
// Expose the Name endpoint.
//
module.exports = Name;
'use strict';
var crypto = require('crypto');
/**
* Retrieve personal / contact information.
*
* @constructor
* @param {FullContact} api
* @api private
*/
function Person(api) {
this.api = api;
this.endpoint = 'https://api.fullcontact.com/v2/person.json';
this.send = api.process.bind(api, this);
}
/**
* Retrieve contact information by e-mail.
*
* ```js
* fullcontact.person.email('opensource@observe.it', [queue], fn);
* ```
*
* @returns {Person}
* @api public
*/
Person.prototype.email = function email() {
var args = this.api.args(arguments, 'queue')
, md5 = crypto.createHash('md5').update(args.value).digest('hex');
this.send({ emailMD5: md5 }, args);
return this;
};
/**
* Retrieve contact information by Twitter handle.
*
* ```js
* fullcontact.person.twitter('@3rdEden', [queue], fn);
* ```
*
* @returns {Person}
* @api public
*/
Person.prototype.twitter = function twitter() {
var args = this.api.args(arguments, 'queue');
this.send({ twitter: args.value }, args);
return this;
};
/**
* Retrieve contact information by Facebook username.
*
* ```js
* fullcontact.person.facebook('arnout.kazemier', [queue], fn);
* ```
*
* @returns {Person}
* @api public
*/
Person.prototype.facebook = function facebook() {
var args = this.api.args(arguments, 'queue');
this.send({ facebookUsername: args.value }, args);
return this;
};
/**
* Retrieve contact information by phone number.
*
* ```js
* fullcontact.person.phone('98470947', [queue], fn);
* ```
*
* @returns {Person}
* @api public
*/
Person.prototype.phone = function phone() {
var args = this.api.args(arguments, 'queue');
this.send({ phone: args.value }, args);
return this;
};
//
// Expose the Person endpoint.
//
module.exports = Person;
'use strict';
var request = require('request')
, qs = require('qs');
var slice = Array.prototype.slice;
/**
* Create new FullContact instance.
*
* @constructor
* @param {String} api The API key for the Full Contact service.
* @api public
*/
function FullContact(api) {
if (!(this instanceof FullContact)) return new FullContact(api);
this.key = api; // API key
this.remaining = 0; // How many API calls are remaining
this.ratelimit = 0; // The amount of API calls allowed
this.ratereset = 0; // In how many seconds is the rate limit reset
this.queueing = false; // Should we be queueing requests
this.requests = []; // Stores all queued commands.
}
/**
* Process the requests before sending, queueing, or what evering
*
* @param {Mixed} api Reference to the Person/WhatEver API.
* @param {Object} query Query string object that should be send.
* @param {Object} args Arguments.
* @api private
*/
FullContact.prototype.process = function req(api, query, args) {
query.apiKey = query.apiKey || this.key;
//
// Add some addition properties
//
if (args.queue) query.queue = args.queue;
if (args.casing) query.casing = args.casing;
//
// The packet that is send to the server or queued when we are in queuing
// mode.
//
var packet = {
method: 'GET',
uri: args.endpoint || api.endpoint,
qs: query
};
if (this.queueing) return this.queue(packet, args);
return this.request(packet, args);
};
/**
* Send a GET request to the FullContact servers using given packet.
*
* @param {Object} packet Request packet.
* @param {Object} args API arguments.
* @api private
*/
FullContact.prototype.request = function req(packet, args) {
var fn = args.fn
, self = this;
request(packet, function requested(err, res, body) {
self.ratereset = +res.headers['X-Rate-Limit-Reset'];
self.ratelimit = +res.headers['X-Rate-Limit-Limit'];
self.remaining = +res.headers['X-Rate-Limit-Remaining'];
if (err) return fn(err);
//
// Parse response to JSON.
//
if ('string' === typeof body) {
try { body = JSON.parse(body); }
catch (e) {
return fn(new Error('Failed to parse API response ('+ e.message +')'));
}
}
//
// Handle API errors, FullContact adds a "status" key to the JSON response
// it will have a "message" property when it's a failed request so we can
// leverage that to return a nice error.
//
if (body.status !== 200) {
err = new Error(body.message);
err.status = body.status;
return fn(err);
}
});
return this;
};
/**
* Start a multi/batch request to the API.
*
* @api public
*/
FullContact.prototype.multi = function multi() {
var queued = new FullContact(this.key);
//
// Force queueing mode on the newly generated API
//
queued.queueing = true;
return queued;
};
/**
* Queue up requests so they can be send as a batch.
*
* @param {Object} packet The object that would be send using .request
* @param {Object} args The arguments;
* @api private
*/
FullContact.prototype.queue = function queue(packet, args) {
this.requests.push({
url: packet.uri +'?'+ qs.stringify(packet.qs),
fn: args.fn
});
return this;
};
/**
* Send all the batched requests to the server.
*
* @param {Function} fn The callback.
* @api public
*/
FullContact.prototype.exec = function exec(fn) {
fn = fn || function noop() {};
var requests = this.requests.splice(0);
/**
* Handle errors easily and ensure that all callbacks are called that were
* queued in the process.
*
* @param {Error} err The exception that occured
*/
function bailout(err) {
requests.forEach(function cb(data) {
if (data.fn) data.fn(err);
});
fn(err);
}
//
// We are no longer queing requests.
//
this.queueing = false;
request({
method: 'POST',
uri: 'https://api.fullcontact.com/v2/batch.json',
qs: { apiKey: this.key },
json: {
requests: requests.map(function urlsonly(data) {
return data.url;
})
}
}, function requested(err, res, body) {
if (err) return bailout(err);
fn(err, body.responses);
});
};
/**
* Parse the given arguments because we don't want to do an optional queue check
* for every single API endpoint.
*
* @param {Arguments} args Arguments
* @returns {Object}
* @api private
*/
FullContact.prototype.args = function parser(args) {
var optional = slice.call(arguments, 1);
args = slice.call(args, 0);
return optional.reduce(function optional(data, key, index) {
data[key] = args[index];
return data;
}, { value: args.shift(), fn: args.pop() });
};
/**
* Define an lazyload new API's.
*
* @param {Object} where Where should we define the property
* @param {String} name The name of the property
* @param {Function} fn The function that returns the new value
* @api private
*/
FullContact.define = function define(where, name, fn) {
Object.defineProperty(where, name, {
get: function get() {
return where[name] = fn();
},
set: function set(value) {
Object.defineProperty(where, name, {
value: value
});
}
});
};
/**
* Have a Node API compatible client interface.
*
* @param {String} api The API key for full contact
* @returns {FullContact}
* @api public
*/
FullContact.createClient = function createClient(api) {
return new FullContact(api);
};
//
// Expose the endpoints.
//
FullContact.Person = require('./endpoints/person');
FullContact.Name = require('./endpoints/name');
//
// Lazy load the various of endpoints so they only get initialized when we
// actually need them.
//
FullContact.define(FullContact.prototype, 'person', function define() {
return new FullContact.Person(this);
});
FullContact.define(FullContact.prototype, 'name', function define() {
return new FullContact.Name(this);
});
//
// Expose the FullContact API.
//
module.exports = FullContact;
{
"name": "fullcontact",
"version": "0.0.0",
"description": "Fullcontact API bindings",
"main": "index.js",
"scripts": {
"test": "NODE_ENV=testing ./node_modules/.bin/mocha $(find test -name '*.test.js')"
},
"repository": "",
"author": "Arnout Kazemier <opensource@observe.it>",
"license": "MIT",
"dependencies": {
"request": "~2.21.0",
"qs": "~0.6.4"
},
"devDependencies": {
"mocha": "~1.9.0",
"chai": "~1.6.0",
"pre-commit": "0.0.3"
}
}
describe('FullContact', function () {
'use strict';
var FullContact = require('../')
, chai = require('chai')
, expect = chai.expect;
//
// The API key we use for testing.
//
var key = process.env.API_KEY;
it('exposes the Person constructor', function () {
expect(FullContact.Person).to.be.a('function');
});
});
--ui bdd
--reporter spec
describe('FullContact.Person', function () {
'use strict';
var FullContact = require('../')
, chai = require('chai')
, expect = chai.expect;
//
// The API key we use for testing.
//
var key = process.env.API_KEY;
});
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment