spatialreference
Version:
A helper library for translating spatial reference systems
140 lines (125 loc) • 3.78 kB
JavaScript
var request = require('request')
var fixWkt = require('./fixwkt')
var esriCodes = require('@esri/proj-codes')
/**
* Define the SpatialReference class
*/
var SpatialReference = function SpatialReference (options) {
// If a db was passed in, ensure it has required methods, then add to instance
if (options.db && options.db.getWKT && options.db.insertWKT) {
this.db = options.db
} else if (options.db) {
throw new Error('Passed in db does not support getWKT or insertWKT')
}
// Add optional logger to instance
this.logger = options.logger
};
/**
* Convert a wkid to a wkt, by 1) looking in db, 2) check ESRI lookups, 3) asking epsg.io
* @param {integer} wkid
* @param {function} callback
*/
SpatialReference.prototype.wkidToWkt = function wkidToWkt (wkid, callback) {
var this$1 = this;
// If a db used, check there first
if (this.db) {
getFromDB.call(this, wkid)
.then(function (wkt) {
if (wkt) {
return callback(null, fixWkt(wkt))
}
// If wkt was not found in db, check Esri lookup
wkt = getWktFromEsri(wkid)
if (wkt) { return wkt }
// If wkt was not found in Esri lookup, check EPSG
return getFromApi(wkid)
})
.then(function (wkt) {
// If the wkt
if (!wkt) { return }
// Insert into DB
return this$1.db.insertWKT(wkid, wkt, function (err) {
if (err) { log.call(this$1, 'error', 'Failed to insert WKT into database: ' + wkid + ' ' + wkt + ', ' + err.message) }
// Log DB insertion error, but pass on wkt to callback
callback(null, fixWkt(wkt))
})
})
.catch(function (err) {
log(this$1, 'error', err.message)
return callback(err)
})
} else {
// No db, look in Esri first
var wkt = getWktFromEsri(wkid)
// If wkt found in Esri, execute callback and end here
if (wkt) { return callback(null, fixWkt(wkt)) }
// If not found in Esri, look in EPSG
getFromApi(wkid)
.then(function (wkt) {
return callback(null, fixWkt(wkt))
})
.catch(function (err) {
log(this$1, 'error', err.message)
return callback(err)
})
}
};
/**
* Wrapper around ESRI lookup
* @param {integer} wkid
* @param {function} callback
*/
SpatialReference.prototype.esriLookup = function esriLookup (wkid, callback) {
var wkt = getWktFromEsri(wkid)
if (!wkt) {
log.call(this, 'error', 'WKT not found for WKID: ' + wkid)
return callback(new Error('WKT not found'))
}
callback(null, wkt)
};
/**
* Check the DB to see if it already contains the wkid
* @param {integer} wkid
*/
function getFromDB (wkid) {
var this$1 = this;
return new Promise(function (resolve, reject) {
this$1.db.getWKT(wkid, function (err, wkt) {
if (err) { reject(err) }
if (!wkt) { resolve() }
resolve(wkt)
})
})
}
/**
* Request WKT for a wkid from epsg.io
* @param {integer} wkid
*/
function getFromApi (wkid) {
var url = 'http://epsg.io/' + wkid + '.wkt'
return new Promise(function (resolve, reject) {
request.get(url, function (err, res, body) {
if (err) { reject(err) }
if (res.statusCode >= 400) { reject(new Error(("Request to " + url + " returned with status " + (res.statusCode) + "."))) }
resolve(body)
})
})
}
/**
* Look in current and deprecated ESRI projection codes
* @param {integer} wkid
*/
function getWktFromEsri (wkid) {
var result = esriCodes.lookup(wkid)
if (result) { return result.wkt }
}
/**
* Log messages
* @param {string} level
* @param {string} message
*/
function log (level, message) {
if (!this.logger) { return console.error(message) }
this.logger.log(level, message)
}
module.exports = SpatialReference