UNPKG

geo.what3words

Version:

Turns WGS84 coordinates into three words or OneWords and vice-versa using what3words.com HTTP API

287 lines (240 loc) 7.69 kB
var request = require('request'), _ = require('lodash'); /** * What3Words API wrapper for the API version 2.0. * * @param apiKey The API key to access the What3Words API with * @param options Configuration options * @return Instance of {@link What3Words} */ function What3Words (apiKey, options) { if (!options) { options = {}; } if (!apiKey) { throw new Error('API Key not set'); } this.version = '1.0'; this.apiKey = apiKey; this.endpoint = options.endpoint || 'https://api.what3words.com/v2/'; this.language = options.language || 'en'; this.userAgent = options.userAgent || 'JS Geo::What3Words'; } module.exports = What3Words; /** * Convert GPS co-ordinates into 3 words. * @param {[object]} options Can contain the following properties: * * lang: alternative language, default will be usef if this is not declared. * * coords: a string containing lat,long */ What3Words.prototype.reverse = function (options) { options.lang = options.lang || this.language; options.coords = options.position || options.coords; // backwards compatibility return new Promise(_.bind(function(resolve, reject) { if(!this.validateLatLng(options.coords)) { reject({error: 301, message: "Invalid or non-existent coordinates."}); } this.execute('reverse', options) .then(function(res) { if(!options.full || options.format.toLowerCase() === 'json') { resolve(res.words); } else { resolve(res); } }) .catch(function(err) { reject(err); }); }, this)); }; // Backwards compatibility What3Words.prototype.positionToWords = function (options) { return this.reverse(options); }; /** * Convert 3 words or a OneWord into GPS coordinates * @param {[object]} options Can contain the following properties: * * lang: alternative language, default will be usef if this is not declared. * * addr: a string containing 3 dot separated words */ What3Words.prototype.forward = function (options) { options.lang = options.lang || this.language; options.addr = options.words || options.addr; // backwards compatibility return new Promise(_.bind(function(resolve, reject) { if(!this.validateWord(options.addr)){ reject({ error: 300, message: "Invalid or non-existent 3 word address."}); } this.execute('forward', options) .then(function(res) { if(!options.full || options.format.toLowerCase() === 'json') { resolve(res.geometry.lat + ',' + res.geometry.lng); } else { resolve(res); } }) .catch(function(err) { reject(err); }); }, this)); }; // Backwards compatibility What3Words.prototype.wordsToPosition = function (options) { return this.forward(options); }; /** * Returns a list of 3 word addresses based on user input and other parameters. * @param {[object]} options Can contain the following properties: * * lang: alternative language, default will be usef if this is not declared. * * addr: a string containing 3 dot separated words */ What3Words.prototype.autosuggest = function (options) { options.lang = options.lang || this.language; return new Promise(_.bind(function(resolve, reject) { if(!options.addr) { reject({ code: 400, msg: "\/autosuggest: missing required parameter" }); } this.execute('autosuggest', options) .then(function(res) { resolve(res); }) .catch(function(err) { reject(err); }); }, this)); }; /** * Returns a blend of the three most relevant 3 word address candidates for a given location, * based on a full or partial 3 word address. * @param {[object]} options Can contain the following properties: * * lang: alternative language, default will be usef if this is not declared. * * addr: a string containing 3 dot separated words */ What3Words.prototype.standardBlend = function (options) { options.lang = options.lang || this.language; return new Promise(_.bind(function(resolve, reject) { if(!options.addr) { reject({ code: 400, msg: "\/autosuggest: missing required parameter" }); } this.execute('standardblend', options) .then(function(res) { resolve(res); }) .catch(function(err) { reject(err); }); }, this)); }; /** * Returns a section of the 3m x 3m what3words grid for a given area. * @param {[object]} options Can contain the following properties: * * lang: alternative language, default will be usef if this is not declared. * * addr: a string containing 3 dot separated words */ What3Words.prototype.grid = function (options) { options.lang = options.lang || this.language; return new Promise(_.bind(function(resolve, reject) { if(!options.bbox) { reject({ code: 400, msg: "\/autosuggest: missing required parameter" }); } this.execute('grid', options) .then(function(res) { resolve(res); }) .catch(function(err) { reject(err); }); }, this)); }; /** * Returns a list of the W3W available languages * @param {[object]} options Can contain the following properties: * * full: Return the full response */ What3Words.prototype.getLanguages = function (options) { return new Promise(_.bind(function(resolve, reject) { this.execute('languages', options) .then(function(res) { if (options.full) { resolve(res); } else { resolve(_.pluck(res.languages, 'code')); } }) .catch(function(err) { reject(err); }); }, this)); }; /** * Validations */ What3Words.prototype.validateWord = function (word) { return word.match(/^\w+\.\w+\.\w+$/); }; What3Words.prototype.validateLatLng = function (latlng) { var coordinates = latlng.split(','); if(coordinates.length === 2) { var lat = Number(coordinates[0]), lng = Number(coordinates[1]); if((lng > -180 && lng < 180) && (lat > -90 && lat < 90)) { return true; } } return; }; /** * Getters */ What3Words.prototype.getLanguage = function () { return this.language; }; What3Words.prototype.getUserAgent = function () { return this.userAgent; }; What3Words.prototype.getEndpoint = function () { return this.endpoint; }; /** * Sends a given request as a JSON object to the W3W API and returns * a promise which if resolved will contain the resulting JSON object. * * @param {[type]} method W3W API method to call * @param {[type]} params Object containg parameters to call the API with * @param {Function} Promise */ What3Words.prototype.execute = function (method, params) { return new Promise(_.bind(function(resolve, reject) { var finalParams = _.extend({ key: this.apiKey }, params); options = { url: this.endpoint + method, qs: finalParams }; request.get(options, function (error, response, body) { if(error) { reject({code: 404, msg: error}); } else { if(response.statusCode !== 200) { reject({code: response.statusCode, msg: 'Unable to connect to the API endpoint ' + options.url}); } else if (response.body.error) { reject(response.body); } if(body){ if(params.format && params.format.toLowerCase() !== 'json') { resolve(response.body); } else { resolve(JSON.parse(response.body)); } } } }); }, this)); };