Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

geokit

Package Overview
Dependencies
Maintainers
1
Versions
15
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

geokit - npm Package Compare versions

Comparing version 1.0.1 to 1.1.0

dist/functions/validate-coordinates.d.ts

10

CHANGELOG.md

@@ -0,1 +1,11 @@

### 1.1.0 (2020-06-22)
##### New Features
* **validateCoordinates:** add function to validate `LatLngLiteral` ([43039bfb](https://github.com/MichaelSolati/geokit/commit/43039bfba5828f8c4bfe66e922e126df22c7e17c))
##### Bug Fixes
* **hash:** rewrite `hash` function to address coordinates of 0, 0 ([52ab31ad](https://github.com/MichaelSolati/geokit/commit/52ab31ad8272c56af3c4e88c39b522d39b9c2af7))
#### 1.0.1 (2020-06-21)

@@ -2,0 +12,0 @@

2

dist/geokit.js

@@ -1,1 +0,1 @@

!function(t,n){"object"==typeof exports&&"undefined"!=typeof module?n(exports):"function"==typeof define&&define.amd?define(["exports"],n):n((t=t||self).Geokit={})}(this,(function(t){"use strict";const n="0123456789bcdefghjkmnpqrstuvwxyz";function e(t,n){return(n[0]+n[1])/2>t?0:1}function o(t){return t*Math.PI/180}function r(t){const n=[];if(t.lat>90&&n.push("Your latitude is greater than 90°"),t.lat<-90&&n.push("Your latitude is less than -90°"),t.lng>180&&n.push("Your longitude is greater than 180°"),t.lng<-180&&n.push("Your longitude is less than -180°"),0!==n.length)return new Error(n.join(" "))}function s(t,e=!1){let o;if("string"!=typeof t)o="geohash must be a string";else if(0===t.length)o="geohash cannot be the empty string";else for(const e of t)-1===n.indexOf(e)&&(o="geohash cannot contain '"+e+"'");if(void 0===o||e)return!o;throw new Error("Invalid geohash '"+t+"': "+o)}t.decodeHash=function(t){s(t);let n=!0;const e=[-90,90],o=[-180,180],r=t.split("");for(;r.length;){const t=(a=r.shift(),"0123456789bcdefghjkmnpqrstuvwxyz".indexOf(a.toLowerCase()));for(let r=0;r<5;r++){const s=[16,8,4,2,1][r],a=n?o:e,i=(a[0]+a[1])/2;a[t&s?0:1]=i,n=!n}}var a;return{lat:(e[0]+e[1])/2,lng:(o[0]+o[1])/2}},t.distance=function(t,n,e="km"){const s=r(t);if(s instanceof Error)throw new Error("Start coordinates: "+s.message);const a=r(n);if(a instanceof Error)throw new Error("End coordinates: "+a.message);const i="miles"===e.toLowerCase()?3963:6371,h=o(n.lat-t.lat),f=o(n.lng-t.lng),l=o(t.lat),c=o(n.lat),u=Math.sin(h/2)*Math.sin(h/2)+Math.sin(f/2)*Math.sin(f/2)*Math.cos(l)*Math.cos(c);return i*(2*Math.atan2(Math.sqrt(u),Math.sqrt(1-u)))},t.hash=function(t,o=10){const s=r(t);if(s instanceof Error)throw s;let a="";const i=[-90,90],h=[-180,180];for(;a.length<o;){let o=0;for(let n=0;n<5;n++){const r=(5*a.length+n)%2==0,s=r?t.lng:t.lat,f=r?h:i,l=(f[0]+f[1])/2;o=(o<<1)+e(s,f),s>l?f[0]=l:f[1]=l}a+=n.charAt(o)}return a},t.validateHash=s,Object.defineProperty(t,"__esModule",{value:!0})}));
!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports):"function"==typeof define&&define.amd?define(["exports"],e):e((t=t||self).Geokit={})}(this,(function(t){"use strict";const e="0123456789bcdefghjkmnpqrstuvwxyz";function n(t){return t*Math.PI/180}function o(t,n=!1){let o;if("string"!=typeof t)o="geohash must be a string";else if(0===t.length)o="geohash cannot be the empty string";else for(const n of t)-1===e.indexOf(n)&&(o="geohash cannot contain '"+n+"'");if(void 0===o||n)return!o;throw new Error("Invalid geohash '"+t+"': "+o)}function s(t,e=!1){const n=[];if(t)if(void 0===t.lat)n.push("Latitude must exist on coordinates");else if(void 0===t.lng)n.push("Longitude must exist on coordinates");else{const e=t.lat,o=t.lng;"number"!=typeof e||isNaN(e)?n.push("Latitude must be a number."):e<-90||e>90?n.push("Latitude must be within the range [-90, 90]."):"number"!=typeof o||isNaN(o)?n.push("Longitude must be a number"):(o<-180||o>180)&&n.push("Longitude must be within the range [-180, 180]")}else n.push("Coordinates must exist.");if(n.length>0&&!e)throw new Error("Invalid coordinates: "+n.join(" "));return!n}t.decodeHash=function(t){o(t);let e=!0;const n=[-90,90],s=[-180,180],i=t.split("");for(;i.length;){const t=(r=i.shift(),"0123456789bcdefghjkmnpqrstuvwxyz".indexOf(r.toLowerCase()));for(let o=0;o<5;o++){const i=[16,8,4,2,1][o],r=e?s:n,a=(r[0]+r[1])/2;r[t&i?0:1]=a,e=!e}}var r;return{lat:(n[0]+n[1])/2,lng:(s[0]+s[1])/2}},t.distance=function(t,e,o="km"){s(t),s(e);const i="miles"===o.toLowerCase()?3963:6371,r=n(e.lat-t.lat),a=n(e.lng-t.lng),u=n(t.lat),h=n(e.lat),f=Math.sin(r/2)*Math.sin(r/2)+Math.sin(a/2)*Math.sin(a/2)*Math.cos(u)*Math.cos(h);return i*(2*Math.atan2(Math.sqrt(f),Math.sqrt(1-f)))},t.hash=function(t,n=10){if(s(t),"number"!=typeof n||isNaN(n))throw new Error("Precision must be a number");if(n<=0)throw new Error("Precision must be greater than 0");if(n>22)throw new Error("Precision cannot be greater than 22");if(Math.round(n)!==n)throw new Error("Precision must be an integer");const o=[-90,90],i=[-180,180];let r="",a=0,u=0,h=1;for(;r.length<n;){const n=h?t.lng:t.lat,s=h?i:o,f=(s[0]+s[1])/2;n>f?(a=1+(a<<1),s[0]=f):(a=0+(a<<1),s[1]=f),h=!h,u<4?u++:(u=0,r+=e.charAt(a),a=0)}return r},t.validateCoordinates=s,t.validateHash=o,Object.defineProperty(t,"__esModule",{value:!0})}));

@@ -12,27 +12,5 @@ 'use strict';

}
function getBit(point, range) {
const middle = (range[0] + range[1]) / 2;
return middle > point ? 0 : 1;
}
function toRad(degrees) {
return (degrees * Math.PI) / 180;
}
function validateCoordinates(coordinates) {
const error = [];
if (coordinates.lat > 90) {
error.push('Your latitude is greater than 90°');
}
if (coordinates.lat < -90) {
error.push('Your latitude is less than -90°');
}
if (coordinates.lng > 180) {
error.push('Your longitude is greater than 180°');
}
if (coordinates.lng < -180) {
error.push('Your longitude is less than -180°');
}
if (error.length !== 0) {
return new Error(error.join(' '));
}
}

@@ -81,11 +59,40 @@ function validateHash(geohash, flag = false) {

function distance(start, end, unit = 'km') {
const startValid = validateCoordinates(start);
if (startValid instanceof Error) {
throw new Error('Start coordinates: ' + startValid.message);
function validateCoordinates(coordinates, flag = false) {
const error = [];
if (!coordinates) {
error.push('Coordinates must exist.');
}
const endValid = validateCoordinates(end);
if (endValid instanceof Error) {
throw new Error('End coordinates: ' + endValid.message);
else if (typeof coordinates.lat === 'undefined') {
error.push('Latitude must exist on coordinates');
}
else if (typeof coordinates.lng === 'undefined') {
error.push('Longitude must exist on coordinates');
}
else {
const latitude = coordinates.lat;
const longitude = coordinates.lng;
if (typeof latitude !== 'number' || isNaN(latitude)) {
error.push('Latitude must be a number.');
}
else if (latitude < -90 || latitude > 90) {
error.push('Latitude must be within the range [-90, 90].');
}
else if (typeof longitude !== 'number' || isNaN(longitude)) {
error.push('Longitude must be a number');
}
else if (longitude < -180 || longitude > 180) {
error.push('Longitude must be within the range [-180, 180]');
}
}
if (error.length > 0 && !flag) {
throw new Error('Invalid coordinates: ' + error.join(' '));
}
else {
return !error;
}
}
function distance(start, end, unit = 'km') {
validateCoordinates(start);
validateCoordinates(end);
const radius = unit.toLowerCase() === 'miles' ? 3963 : 6371;

@@ -103,20 +110,44 @@ const dLat = toRad(end.lat - start.lat);

function hash(coordinates, precision = 10) {
const valid = validateCoordinates(coordinates);
if (valid instanceof Error) {
throw valid;
validateCoordinates(coordinates);
if (typeof precision === 'number' && !isNaN(precision)) {
if (precision <= 0) {
throw new Error('Precision must be greater than 0');
}
else if (precision > 22) {
throw new Error('Precision cannot be greater than 22');
}
else if (Math.round(precision) !== precision) {
throw new Error('Precision must be an integer');
}
}
let hash = '';
else {
throw new Error('Precision must be a number');
}
const latRng = [-90, 90];
const lngRng = [-180, 180];
let hash = '';
let hashVal = 0;
let bits = 0;
let even = 1;
while (hash.length < precision) {
let temp = 0;
for (let i = 0; i < 5; i++) {
const even = (hash.length * 5 + i) % 2 === 0;
const coord = even ? coordinates.lng : coordinates.lat;
const range = even ? lngRng : latRng;
const middle = (range[0] + range[1]) / 2;
temp = (temp << 1) + getBit(coord, range);
coord > middle ? (range[0] = middle) : (range[1] = middle);
const val = even ? coordinates.lng : coordinates.lat;
const range = even ? lngRng : latRng;
const mid = (range[0] + range[1]) / 2;
if (val > mid) {
hashVal = (hashVal << 1) + 1;
range[0] = mid;
}
hash += base32(temp);
else {
hashVal = (hashVal << 1) + 0;
range[1] = mid;
}
even = !even;
if (bits < 4) {
bits++;
}
else {
bits = 0;
hash += base32(hashVal);
hashVal = 0;
}
}

@@ -129,2 +160,3 @@ return hash;

exports.hash = hash;
exports.validateCoordinates = validateCoordinates;
exports.validateHash = validateHash;

@@ -5,2 +5,3 @@ export * from './definitions';

export * from './functions/hash';
export * from './functions/validate-coordinates';
export * from './functions/validate-hash';

@@ -8,27 +8,5 @@ const BASE32 = '0123456789bcdefghjkmnpqrstuvwxyz';

}
function getBit(point, range) {
const middle = (range[0] + range[1]) / 2;
return middle > point ? 0 : 1;
}
function toRad(degrees) {
return (degrees * Math.PI) / 180;
}
function validateCoordinates(coordinates) {
const error = [];
if (coordinates.lat > 90) {
error.push('Your latitude is greater than 90°');
}
if (coordinates.lat < -90) {
error.push('Your latitude is less than -90°');
}
if (coordinates.lng > 180) {
error.push('Your longitude is greater than 180°');
}
if (coordinates.lng < -180) {
error.push('Your longitude is less than -180°');
}
if (error.length !== 0) {
return new Error(error.join(' '));
}
}

@@ -77,11 +55,40 @@ function validateHash(geohash, flag = false) {

function distance(start, end, unit = 'km') {
const startValid = validateCoordinates(start);
if (startValid instanceof Error) {
throw new Error('Start coordinates: ' + startValid.message);
function validateCoordinates(coordinates, flag = false) {
const error = [];
if (!coordinates) {
error.push('Coordinates must exist.');
}
const endValid = validateCoordinates(end);
if (endValid instanceof Error) {
throw new Error('End coordinates: ' + endValid.message);
else if (typeof coordinates.lat === 'undefined') {
error.push('Latitude must exist on coordinates');
}
else if (typeof coordinates.lng === 'undefined') {
error.push('Longitude must exist on coordinates');
}
else {
const latitude = coordinates.lat;
const longitude = coordinates.lng;
if (typeof latitude !== 'number' || isNaN(latitude)) {
error.push('Latitude must be a number.');
}
else if (latitude < -90 || latitude > 90) {
error.push('Latitude must be within the range [-90, 90].');
}
else if (typeof longitude !== 'number' || isNaN(longitude)) {
error.push('Longitude must be a number');
}
else if (longitude < -180 || longitude > 180) {
error.push('Longitude must be within the range [-180, 180]');
}
}
if (error.length > 0 && !flag) {
throw new Error('Invalid coordinates: ' + error.join(' '));
}
else {
return !error;
}
}
function distance(start, end, unit = 'km') {
validateCoordinates(start);
validateCoordinates(end);
const radius = unit.toLowerCase() === 'miles' ? 3963 : 6371;

@@ -99,20 +106,44 @@ const dLat = toRad(end.lat - start.lat);

function hash(coordinates, precision = 10) {
const valid = validateCoordinates(coordinates);
if (valid instanceof Error) {
throw valid;
validateCoordinates(coordinates);
if (typeof precision === 'number' && !isNaN(precision)) {
if (precision <= 0) {
throw new Error('Precision must be greater than 0');
}
else if (precision > 22) {
throw new Error('Precision cannot be greater than 22');
}
else if (Math.round(precision) !== precision) {
throw new Error('Precision must be an integer');
}
}
let hash = '';
else {
throw new Error('Precision must be a number');
}
const latRng = [-90, 90];
const lngRng = [-180, 180];
let hash = '';
let hashVal = 0;
let bits = 0;
let even = 1;
while (hash.length < precision) {
let temp = 0;
for (let i = 0; i < 5; i++) {
const even = (hash.length * 5 + i) % 2 === 0;
const coord = even ? coordinates.lng : coordinates.lat;
const range = even ? lngRng : latRng;
const middle = (range[0] + range[1]) / 2;
temp = (temp << 1) + getBit(coord, range);
coord > middle ? (range[0] = middle) : (range[1] = middle);
const val = even ? coordinates.lng : coordinates.lat;
const range = even ? lngRng : latRng;
const mid = (range[0] + range[1]) / 2;
if (val > mid) {
hashVal = (hashVal << 1) + 1;
range[0] = mid;
}
hash += base32(temp);
else {
hashVal = (hashVal << 1) + 0;
range[1] = mid;
}
even = !even;
if (bits < 4) {
bits++;
}
else {
bits = 0;
hash += base32(hashVal);
hashVal = 0;
}
}

@@ -122,2 +153,2 @@ return hash;

export { decodeHash, distance, hash, validateHash };
export { decodeHash, distance, hash, validateCoordinates, validateHash };

@@ -1,7 +0,4 @@

import { LatLngLiteral } from './definitions';
export declare const BASE32 = "0123456789bcdefghjkmnpqrstuvwxyz";
export declare function base32(value: number): string;
export declare function decimalChunk(value: string): number;
export declare function getBit(point: number, range: number[]): number;
export declare function toRad(degrees: number): number;
export declare function validateCoordinates(coordinates: LatLngLiteral): Error | void;
{
"name": "geokit",
"version": "1.0.1",
"version": "1.1.0",
"description": "An assortment of geolocation related tools, all packaged in one easy to use kit.",

@@ -5,0 +5,0 @@ "scripts": {

@@ -52,2 +52,16 @@ # geokit

### `validateCoordinates(coordinates: LatLngLiteral): boolean`
Validates coordinates and returns a boolean if valid, or throws an error if invalid.
`coordinates` must be LatLngLiterals `{ lat: 0, lng: 0 }`.
```TypeScript
import * as geokit from 'geokit';
const coordinates = {lat: 41.3083, lng: -72.9279};
const isValid = geokit.validateCoordinates(coordinates); // true
```
### `validateHash(hash: string): LatLngLiteral`

@@ -54,0 +68,0 @@

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc