@egodigital/egoose
Version:
Helper classes and functions for Node.js 10 or later.
139 lines • 5.11 kB
JavaScript
;
/**
* This file is part of the @egodigital/egoose distribution.
* Copyright (c) e.GO Digital GmbH, Aachen, Germany (https://www.e-go-digital.com/)
*
* @egodigital/egoose is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation, version 3.
*
* @egodigital/egoose is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
Object.defineProperty(exports, "__esModule", { value: true });
const http_1 = require("../http");
const index_1 = require("../index");
const _ = require("lodash");
const geocoder = require("node-geocoder");
const geodist = require('geodist');
const polyline = require('@mapbox/polyline');
/**
* Tries to detect geo coordinates from address data.
*
* @param {string|AddressToGeoCoordinatesOptions} queryOrOpts The query string or the options.
* @param {boolean} [throwOnError] Throw an exception on error or return (false). Default: (false)
*
* @return {GeoCoordinates|false} The location or (false) if not found.
*/
async function addressToGeoCoordinates(queryOrOpts, throwOnError) {
let query;
if (_.isObjectLike(queryOrOpts)) {
const OPTS = queryOrOpts;
query = `${index_1.toStringSafe(OPTS.street)} ${index_1.toStringSafe(OPTS.zipCode)} ${index_1.toStringSafe(OPTS.city)}`;
}
else {
query = index_1.toStringSafe(queryOrOpts);
}
const ADDR_STR = index_1.normalizeString(query)
.split(' ')
.map(x => x.trim())
.filter(x => '' !== x)
.join(' ');
if ('' !== ADDR_STR) {
try {
const CLIENT_OPTS = {
provider: 'google',
httpAdapter: 'https',
apiKey: index_1.toStringSafe(process.env.GOOGLE_API_KEY).trim(),
formatter: null,
};
const CLIENT = geocoder(CLIENT_OPTS);
const RESULT = await CLIENT.geocode(ADDR_STR);
if (RESULT && RESULT.length) {
const ENTRY = RESULT[0];
if (ENTRY) {
const COORDINATES = {
lat: parseFloat(index_1.toStringSafe(ENTRY.latitude).trim()),
lng: parseFloat(index_1.toStringSafe(ENTRY.longitude).trim()),
};
if (!isNaN(COORDINATES.lat) && !isNaN(COORDINATES.lng)) {
return COORDINATES;
}
}
}
}
catch (e) {
if (index_1.toBooleanSafe(throwOnError)) {
throw e; /// re-throw
}
}
}
return false;
}
exports.addressToGeoCoordinates = addressToGeoCoordinates;
/**
* Calculates the distance between 2 geo points.
*
* @param {number} lat1 The latitude of the first point.
* @param {number} lon1 The longitude of the first point.
* @param {number} lat2 The latitude of the second point.
* @param {number} lon2 The longitude of the second point.
* @param {string} [unit] The custom unit to use.
*
* @return {number} The distance in meters.
*/
function calcDistance(lat1, lon1, lat2, lon2, unit = 'meters') {
return geodist({
lat: lat1, lon: lon1
}, {
lat: lat2, lon: lon2
}, {
exact: true,
unit: unit,
});
}
exports.calcDistance = calcDistance;
/**
* Calculates a route via a service, like MapBox.
*
* @param {GeoCoordinates} from The start location.
* @param {GeoCoordinates} to The end location.
*
* @return {Promise<contracts.GeoCoordinates[]>} The promise with the route.
*/
async function calcRoute(from, to) {
const RESPONSE = await http_1.POST('https://api.mapbox.com/directions/v5/mapbox/driving?access_token=' + encodeURIComponent(process.env.MAPBOX_API_TOKEN), {
body: Buffer.from(`coordinates=${from.lng},${from.lat};${to.lng},${from.lat}&steps=true&waypoints=0;1&waypoint_names=Home;Work&banner_instructions=true`, 'utf8'),
headers: {
'Content-type': 'application/x-www-form-urlencoded',
}
});
if (200 !== RESPONSE.code) {
throw new Error(`Unexpected response: [${RESPONSE.code}] '${RESPONSE.status}'`);
}
const RESULT = JSON.parse((await RESPONSE.readBody())
.toString('utf8'));
if ('ok' !== index_1.normalizeString(RESULT.code)) {
throw new Error(`Routing failed!`);
}
const ROUTE = [];
const WAYPOINTS = polyline.decode(RESULT.routes[0].geometry);
for (const WP of WAYPOINTS) {
ROUTE.push({
lat: WP[0],
lng: WP[1],
});
}
// prepend 'from'
ROUTE.unshift(from);
// append 'to'
ROUTE.push(to);
return ROUTE;
}
exports.calcRoute = calcRoute;
//# sourceMappingURL=index.js.map