UNPKG

spatialreference

Version:

A helper library for translating spatial reference systems

138 lines (125 loc) 3.66 kB
const request = require('request') const fixWkt = require('./fixwkt') const esriCodes = require('@esri/proj-codes') /** * Define the SpatialReference class */ class SpatialReference { constructor (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 */ wkidToWkt (wkid, callback) { // If a db used, check there first if (this.db) { getFromDB.call(this, wkid) .then(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(wkt => { // If the wkt if (!wkt) return // Insert into DB return this.db.insertWKT(wkid, wkt, (err) => { if (err) log.call(this, '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(err => { log(this, 'error', err.message) return callback(err) }) } else { // No db, look in Esri first const 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(wkt => { return callback(null, fixWkt(wkt)) }) .catch(err => { log(this, 'error', err.message) return callback(err) }) } } /** * Wrapper around ESRI lookup * @param {integer} wkid * @param {function} callback */ esriLookup (wkid, callback) { const 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) { return new Promise((resolve, reject) => { this.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) { const url = 'http://epsg.io/' + wkid + '.wkt' return new Promise((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) { const 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