haversine-geolocation 2.0.0-alpha.1 → 2.0.0-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -11,22 +11,32 @@ A small JavaScript/TypeScript geospatial library built around spherical Haversin
11
11
 
12
12
  ## Release status
13
13
 
14
- There are currently two important lines to distinguish:
14
+ There are currently two public release lines:
15
15
 
16
- - **npm stable:** `haversine-geolocation@1.6.0` — the historical V1 API;
17
- - **repository `master`:** the unreleased V2 development line.
16
+ - **npm stable / `latest`:** `haversine-geolocation@1.6.0` — the historical V1 API;
17
+ - **npm prerelease / `next`:** `haversine-geolocation@2.0.0-alpha.1` — the first public V2 alpha.
18
18
 
19
- The V2 code, package exports and examples below are already implemented on `master`, but **V2 has not yet been published to npm**.
20
-
21
- If you run:
19
+ A normal install still receives stable V1:
22
20
 
23
21
  ```bash
24
22
  npm install haversine-geolocation
25
23
  ```
26
24
 
27
- today, you receive the published V1 package.
25
+ To test V2 explicitly:
26
+
27
+ ```bash
28
+ npm install haversine-geolocation@2.0.0-alpha.1
29
+ ```
30
+
31
+ or:
32
+
33
+ ```bash
34
+ npm install haversine-geolocation@next
35
+ ```
36
+
37
+ V2 is public, but remains prerelease until stable `2.0.0`.
28
38
 
29
- See [Migrating from V1 to V2](docs/migration/v1-to-v2.md) for the planned upgrade path.
39
+ See [Migrating from V1 to V2](docs/migration/v1-to-v2.md) for the upgrade path and the [Changelog](CHANGELOG.md) for release history.
30
40
 
31
41
  ## Published V1 usage
32
42
 
@@ -94,9 +104,9 @@ V1 couples browser geolocation to the historical singleton. That package design
94
104
 
95
105
  ---
96
106
 
97
- ## V2 preview — unreleased
107
+ ## V2 alpha — public prerelease
98
108
 
99
- The canonical V2 API is functional and uses named exports.
109
+ The canonical V2 API is available in the public `2.0.0-alpha.1` prerelease and uses named exports.
100
110
 
101
111
  ### Distance
102
112
 
@@ -224,7 +234,7 @@ The legacy facade preserves historical V1 behavior where compatibility matters,
224
234
 
225
235
  ## V2 package architecture
226
236
 
227
- The unreleased V2 package on `master` is designed around explicit entry points:
237
+ The V2 package is designed around explicit entry points:
228
238
 
229
239
  ```text
230
240
  haversine-geolocation
@@ -278,8 +288,9 @@ d = R * c
278
288
 
279
289
  The V2 contract is documented in the accepted ADRs under [docs/architecture](docs/architecture/README.md).
280
290
 
281
- The detailed migration and release guides are:
291
+ The detailed API, migration and release guides are:
282
292
 
293
+ - [V2 API Reference](docs/api-reference.md)
283
294
  - [Migrating from Haversine V1 to V2](docs/migration/v1-to-v2.md)
284
295
  - [Haversine V2 release runbook](docs/release/v2-release-runbook.md)
285
296
 
@@ -292,8 +303,8 @@ Historical behavior and compatibility findings are preserved in:
292
303
  The repository currently validates:
293
304
 
294
305
  - TypeScript source typechecking;
295
- - browser-based tests;
296
- - production builds;
306
+ - Vitest unit and characterization tests;
307
+ - production builds through Vite library mode;
297
308
  - Node runtime smoke tests;
298
309
  - CommonJS and ESM package consumers;
299
310
  - npm tarball contents;
package/dist/browser.cjs CHANGED
@@ -1,2 +1,2 @@
1
- Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});var e=()=>{if(typeof navigator<`u`)return navigator.geolocation},t=()=>e()!==void 0,n=t=>new Promise((n,r)=>{let i=e();i===void 0?r(Error(`Geolocation API is not available in this environment`)):i.getCurrentPosition(n,r,t)});exports.getCurrentPosition=n,exports.isGeolocationSupported=t;
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});var e=()=>{if(typeof navigator>`u`)return;let e=navigator.geolocation;return typeof e?.getCurrentPosition==`function`?e:void 0},t=()=>e()!==void 0,n=t=>new Promise((n,r)=>{let i=e();i===void 0?r(Error(`Geolocation API is not available in this environment`)):i.getCurrentPosition(n,r,t)});exports.getCurrentPosition=n,exports.isGeolocationSupported=t;
2
2
  //# sourceMappingURL=browser.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"browser.cjs","names":["getGeolocation","isGeolocationSupported","getCurrentPosition","geolocation","reject","resolve","options"],"sources":["../src/v2/browser.ts"],"sourcesContent":["const getGeolocation = (): Geolocation | undefined => {\n if (typeof navigator === 'undefined') {\n return undefined;\n }\n\n return navigator.geolocation;\n};\n\nexport const isGeolocationSupported = (): boolean =>\n getGeolocation() !== undefined;\n\nexport const getCurrentPosition = (\n options?: PositionOptions,\n): Promise<GeolocationPosition> =>\n new Promise((resolve, reject) => {\n const geolocation = getGeolocation();\n\n if (geolocation === undefined) {\n reject(new Error('Geolocation API is not available in this environment'));\n return;\n }\n\n geolocation.getCurrentPosition(\n resolve,\n reject,\n options,\n );\n });\n"],"mappings":"mEAAA,IAAMA,MAAgD,CAClD,GAAI,OAAO,UAAc,IAIzB,OAAO,UAAU,WACrB,EAEaC,MACTD,EAAe,IAAM,IAAA,GAEZE,EACT,GAEA,IAAI,SAAS,EAAS,IAAW,CAC7B,IAAMC,EAAcH,EAAe,EAE/BG,IAAgB,IAAA,GAChBC,EAAW,MAAM,sDAAsD,CAAC,EAI5ED,EAAY,mBACRE,EACAD,EACAE,CACJ,CACJ,CAAC"}
1
+ {"version":3,"file":"browser.cjs","names":["getGeolocation","geolocation","isGeolocationSupported","getCurrentPosition","reject","resolve","options"],"sources":["../src/v2/browser.ts"],"sourcesContent":["const getGeolocation = (): Geolocation | undefined => {\n if (typeof navigator === 'undefined') {\n return undefined;\n }\n\n const geolocation = navigator.geolocation;\n return typeof geolocation?.getCurrentPosition === 'function' ? geolocation : undefined;\n};\n\nexport const isGeolocationSupported = (): boolean => getGeolocation() !== undefined;\n\nexport const getCurrentPosition = (options?: PositionOptions): Promise<GeolocationPosition> =>\n new Promise((resolve, reject) => {\n const geolocation = getGeolocation();\n\n if (geolocation === undefined) {\n reject(new Error('Geolocation API is not available in this environment'));\n return;\n }\n\n geolocation.getCurrentPosition(resolve, reject, options);\n });\n"],"mappings":"mEAAA,IAAMA,MAAgD,CAClD,GAAI,OAAO,UAAc,IACrB,OAGJ,IAAMC,EAAc,UAAU,YAC9B,OAAO,OAAOA,GAAa,oBAAuB,WAAaA,EAAc,IAAA,EACjF,EAEaC,MAAwCF,EAAe,IAAM,IAAA,GAE7DG,EAAsB,GAC/B,IAAI,SAAS,EAAS,IAAW,CAC7B,IAAMF,EAAcD,EAAe,EAE/BC,IAAgB,IAAA,GAChBG,EAAW,MAAM,sDAAsD,CAAC,EAI5EH,EAAY,mBAAmBI,EAASD,EAAQE,CAAO,CAC3D,CAAC"}
package/dist/browser.mjs CHANGED
@@ -1,6 +1,8 @@
1
1
  //#region src/v2/browser.ts
2
2
  var e = () => {
3
- if (typeof navigator < "u") return navigator.geolocation;
3
+ if (typeof navigator > "u") return;
4
+ let e = navigator.geolocation;
5
+ return typeof e?.getCurrentPosition == "function" ? e : void 0;
4
6
  }, t = () => e() !== void 0, n = (t) => new Promise((n, r) => {
5
7
  let i = e();
6
8
  i === void 0 ? r(/* @__PURE__ */ Error("Geolocation API is not available in this environment")) : i.getCurrentPosition(n, r, t);
@@ -1 +1 @@
1
- {"version":3,"file":"browser.mjs","names":["getGeolocation","isGeolocationSupported","getCurrentPosition","geolocation","reject","resolve","options"],"sources":["../src/v2/browser.ts"],"sourcesContent":["const getGeolocation = (): Geolocation | undefined => {\n if (typeof navigator === 'undefined') {\n return undefined;\n }\n\n return navigator.geolocation;\n};\n\nexport const isGeolocationSupported = (): boolean =>\n getGeolocation() !== undefined;\n\nexport const getCurrentPosition = (\n options?: PositionOptions,\n): Promise<GeolocationPosition> =>\n new Promise((resolve, reject) => {\n const geolocation = getGeolocation();\n\n if (geolocation === undefined) {\n reject(new Error('Geolocation API is not available in this environment'));\n return;\n }\n\n geolocation.getCurrentPosition(\n resolve,\n reject,\n options,\n );\n });\n"],"mappings":";AAAA,IAAMA,UAAgD;CAClD,IAAI,OAAO,YAAc,KAIzB,OAAO,UAAU;AACrB,GAEaC,UACTD,EAAe,MAAM,KAAA,GAEZE,KACT,MAEA,IAAI,SAAS,GAAS,MAAW;CAC7B,IAAMC,IAAcH,EAAe;CAEnC,AAAIG,MAAgB,KAAA,IAChBC,EAAO,gBAAI,MAAM,sDAAsD,CAAC,IAI5ED,EAAY,mBACRE,GACAD,GACAE,CACJ;AACJ,CAAC"}
1
+ {"version":3,"file":"browser.mjs","names":["getGeolocation","geolocation","isGeolocationSupported","getCurrentPosition","reject","resolve","options"],"sources":["../src/v2/browser.ts"],"sourcesContent":["const getGeolocation = (): Geolocation | undefined => {\n if (typeof navigator === 'undefined') {\n return undefined;\n }\n\n const geolocation = navigator.geolocation;\n return typeof geolocation?.getCurrentPosition === 'function' ? geolocation : undefined;\n};\n\nexport const isGeolocationSupported = (): boolean => getGeolocation() !== undefined;\n\nexport const getCurrentPosition = (options?: PositionOptions): Promise<GeolocationPosition> =>\n new Promise((resolve, reject) => {\n const geolocation = getGeolocation();\n\n if (geolocation === undefined) {\n reject(new Error('Geolocation API is not available in this environment'));\n return;\n }\n\n geolocation.getCurrentPosition(resolve, reject, options);\n });\n"],"mappings":";AAAA,IAAMA,UAAgD;CAClD,IAAI,OAAO,YAAc,KACrB;CAGJ,IAAMC,IAAc,UAAU;CAC9B,OAAO,OAAOA,GAAa,sBAAuB,aAAaA,IAAc,KAAA;AACjF,GAEaC,UAAwCF,EAAe,MAAM,KAAA,GAE7DG,KAAsB,MAC/B,IAAI,SAAS,GAAS,MAAW;CAC7B,IAAMF,IAAcD,EAAe;CAEnC,AAAIC,MAAgB,KAAA,IAChBG,EAAO,gBAAI,MAAM,sDAAsD,CAAC,IAI5EH,EAAY,mBAAmBI,GAASD,GAAQE,CAAO;AAC3D,CAAC"}
package/dist/build.js CHANGED
@@ -1,2 +1,2 @@
1
- (function(e,t){typeof exports==`object`&&typeof module<`u`?t(exports):typeof define==`function`&&define.amd?define([`exports`],t):(e=typeof globalThis<`u`?globalThis:e||self,t(e.HaversineGeolocation={}))})(this,function(e){Object.defineProperties(e,{__esModule:{value:!0},[Symbol.toStringTag]:{value:`Module`}});var t=new class{_convertMeasurements(e,t=`km`){let n=``;switch(t.toLowerCase()){case`mi`:n=(e*.62137).toFixed(1);break;case`km`:n=e.toFixed(1);break;case`m`:n=(e*1e3).toFixed();break;default:n=e.toFixed(1)}return parseFloat(n)}_haversine(...e){let t=e.map(e=>e/180*Math.PI),n=t[0],r=t[1],i=t[2],a=t[3],o=i-n,s=a-r,c=Math.sin(o/2)*Math.sin(o/2)+Math.sin(s/2)*Math.sin(s/2)*Math.cos(n)*Math.cos(i);return 2*Math.asin(Math.sqrt(Math.min(1,Math.max(0,c))))*6372.8}isGeolocationAvailable(){return new Promise((e,t)=>{`geolocation`in navigator?navigator.geolocation.getCurrentPosition(t=>{e(t)},e=>{switch(e.code){case e.PERMISSION_DENIED:t(Error(`Error: Permission denied`));break;case e.POSITION_UNAVAILABLE:t(Error(`Error: Position unavailable`));break;case e.TIMEOUT:t(Error(`Error: Timeout`))}}):t(Error(`Error: Geolocation disabled in your browser`))})}getDistanceBetween(e,t,n){if(e.hasOwnProperty(`latitude`)&&e.hasOwnProperty(`longitude`)&&t.hasOwnProperty(`latitude`)&&t.hasOwnProperty(`longitude`)){let r=this._haversine(e.latitude,e.longitude,t.latitude,t.longitude);return this._convertMeasurements(r,n)}throw Error(`Error: Position latitude or longitude is not correct`)}getClosestPosition(e,t,n){let r=t.map(t=>this.getDistanceBetween(e,t,n)),i=r.indexOf(Math.min(...r));return{...t[i],haversine:{distance:r[i],measurement:n,accuracy:e.accuracy}}}},n=e=>typeof e==`number`&&Number.isFinite(e),r=e=>typeof e==`object`&&!!e&&`latitude`in e&&`longitude`in e;function i(e){if(!r(e))throw TypeError(`Coordinate must provide latitude and longitude`);if(!n(e.latitude)||!n(e.longitude))throw TypeError(`Coordinate latitude and longitude must be finite numbers`);if(e.latitude<-90||e.latitude>90)throw RangeError(`Coordinate latitude must be between -90 and 90`);if(e.longitude<-180||e.longitude>180)throw RangeError(`Coordinate longitude must be between -180 and 180`)}var a=e=>{try{return i(e),!0}catch{return!1}},o={m:1,km:1e3,mi:1609.344};function s(e){if(e!==`m`&&e!==`km`&&e!==`mi`)throw TypeError(`Distance unit must be one of: m, km, mi`)}var c=(e,t,n)=>{if(!Number.isFinite(e))throw TypeError(`Distance value must be a finite number`);return s(t),s(n),e*o[t]/o[n]},l=6371008.8,u=e=>e*Math.PI/180,d=e=>{if(!Number.isFinite(e))throw TypeError(`Radius must be a finite number`);if(e<=0)throw RangeError(`Radius must be greater than zero`)},f=(e,t,n={})=>{i(e),i(t);let r=n.unit??`km`,a=n.radius??6371008.8;d(a);let o=u(e.latitude),s=u(e.longitude),l=u(t.latitude),f=u(t.longitude),p=l-o,m=f-s,h=Math.sin(p/2),g=Math.sin(m/2),_=h*h+g*g*Math.cos(o)*Math.cos(l);return c(2*Math.asin(Math.sqrt(Math.min(1,Math.max(0,_))))*a,`m`,r)};e.EARTH_MEAN_RADIUS_M=l,e.assertCoordinate=i,e.assertDistanceUnit=s,e.convertDistance=c,e.default=t,e.distance=f,e.isCoordinate=a,e.nearest=(e,t,n={})=>{let r,i=1/0;for(let a of t){let t=f(e,a,n);t<i&&(r=a,i=t)}if(r!==void 0)return{point:r,distance:i}}});
1
+ (function(e,t){typeof exports==`object`&&typeof module<`u`?t(exports):typeof define==`function`&&define.amd?define([`exports`],t):(e=typeof globalThis<`u`?globalThis:e||self,t(e.HaversineGeolocation={}))})(this,function(e){Object.defineProperties(e,{__esModule:{value:!0},[Symbol.toStringTag]:{value:`Module`}});var t=new class{_convertMeasurements(e,t=`km`){let n=``;switch(t.toLowerCase()){case`mi`:n=(e*.62137).toFixed(1);break;case`km`:n=e.toFixed(1);break;case`m`:n=(e*1e3).toFixed();break;default:n=e.toFixed(1)}return parseFloat(n)}_haversine(...e){let t=e.map(e=>e/180*Math.PI),n=t[0],r=t[1],i=t[2],a=t[3],o=i-n,s=a-r,c=Math.sin(o/2)*Math.sin(o/2)+Math.sin(s/2)*Math.sin(s/2)*Math.cos(n)*Math.cos(i);return 2*Math.asin(Math.sqrt(Math.min(1,Math.max(0,c))))*6372.8}isGeolocationAvailable(){return new Promise((e,t)=>{`geolocation`in navigator?navigator.geolocation.getCurrentPosition(t=>{e(t)},e=>{switch(e.code){case e.PERMISSION_DENIED:t(Error(`Error: Permission denied`));break;case e.POSITION_UNAVAILABLE:t(Error(`Error: Position unavailable`));break;case e.TIMEOUT:t(Error(`Error: Timeout`))}}):t(Error(`Error: Geolocation disabled in your browser`))})}getDistanceBetween(e,t,n){if(Object.prototype.hasOwnProperty.call(e,`latitude`)&&Object.prototype.hasOwnProperty.call(e,`longitude`)&&Object.prototype.hasOwnProperty.call(t,`latitude`)&&Object.prototype.hasOwnProperty.call(t,`longitude`)){let r=this._haversine(e.latitude,e.longitude,t.latitude,t.longitude);return this._convertMeasurements(r,n)}throw Error(`Error: Position latitude or longitude is not correct`)}getClosestPosition(e,t,n){let r=t.map(t=>this.getDistanceBetween(e,t,n)),i=r.indexOf(Math.min(...r));return{...t[i],haversine:{distance:r[i],measurement:n,accuracy:e.accuracy}}}},n=e=>typeof e==`number`&&Number.isFinite(e),r=e=>typeof e==`object`&&!!e&&`latitude`in e&&`longitude`in e;function i(e){if(!r(e))throw TypeError(`Coordinate must provide latitude and longitude`);if(!n(e.latitude)||!n(e.longitude))throw TypeError(`Coordinate latitude and longitude must be finite numbers`);if(e.latitude<-90||e.latitude>90)throw RangeError(`Coordinate latitude must be between -90 and 90`);if(e.longitude<-180||e.longitude>180)throw RangeError(`Coordinate longitude must be between -180 and 180`)}var a=e=>{try{return i(e),!0}catch{return!1}},o={m:1,km:1e3,mi:1609.344};function s(e){if(e!==`m`&&e!==`km`&&e!==`mi`)throw TypeError(`Distance unit must be one of: m, km, mi`)}var c=(e,t,n)=>{if(!Number.isFinite(e))throw TypeError(`Distance value must be a finite number`);return s(t),s(n),e*o[t]/o[n]},l=6371008.8,u=e=>e*Math.PI/180,d=e=>{if(!Number.isFinite(e))throw TypeError(`Radius must be a finite number`);if(e<=0)throw RangeError(`Radius must be greater than zero`)},f=(e={})=>{d(e.radius??6371008.8),s(e.unit??`km`)},p=(e,t,n={})=>{i(e),i(t);let r=n.unit??`km`,a=n.radius??6371008.8;d(a);let o=u(e.latitude),s=u(e.longitude),l=u(t.latitude),f=u(t.longitude),p=l-o,m=f-s,h=Math.sin(p/2),g=Math.sin(m/2),_=h*h+g*g*Math.cos(o)*Math.cos(l);return c(2*Math.asin(Math.sqrt(Math.min(1,Math.max(0,_))))*a,`m`,r)};e.EARTH_MEAN_RADIUS_M=l,e.assertCoordinate=i,e.assertDistanceUnit=s,e.convertDistance=c,e.default=t,e.distance=p,e.isCoordinate=a,e.nearest=(e,t,n={})=>{if(i(e),t.length===0){f(n);return}let r,a=1/0;for(let i of t){let t=p(e,i,n);t<a&&(r=i,a=t)}if(r!==void 0)return{point:r,distance:a}}});
2
2
  //# sourceMappingURL=build.js.map
package/dist/build.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"build.js","names":["factory","global","exports","legacy_default","rawValue","measurement","distance","args","rad","deg","lat1","lon1","lat2","lon2","dLat","dLon","a","resolve","data","error","reject","p1","p2","distances","otherPoints","current","value","indexOfSmallest","isFiniteNumber","hasCoordinateShape","assertCoordinate","isCoordinate","METRES_PER_UNIT","assertDistanceUnit","convertDistance","from","to","EARTH_MEAN_RADIUS_M","degreesToRadians","degrees","assertRadius","radius","unit","options","latitude1","longitude1","latitude2","longitude2","latitudeDelta","longitudeDelta","latitudeHaversine","longitudeHaversine","closestPoint","closestDistance","candidate","candidates","candidateDistance","origin"],"sources":["../src/legacy.ts","../src/v2/coordinate.ts","../src/v2/units.ts","../src/v2/distance.ts","../src/v2/nearest.ts"],"sourcesContent":["import type { ILocationPoint } from \"./interfaces/ILocationPoint.js\";\n\nclass HaversineGeolocation {\n _convertMeasurements(distance: number, measurement: string = 'km'): number {\n let rawValue: string = '';\n switch (measurement.toLowerCase()) {\n case 'mi' :\n rawValue = (distance * 0.62137).toFixed(1);\n break;\n case 'km' :\n rawValue = distance.toFixed(1);\n break;\n case 'm' :\n rawValue = (distance * 1000).toFixed();\n break;\n default :\n rawValue = distance.toFixed(1);\n }\n return parseFloat(rawValue);\n }\n\n _haversine(...args: number[]): number {\n const rad: number[] = args.map((deg: number) => deg / 180.0 * Math.PI);\n const lat1: number = rad[0];\n const lon1: number = rad[1];\n const lat2: number = rad[2];\n const lon2: number = rad[3];\n const R: number = 6372.8;\n const dLat: number = lat2 - lat1;\n const dLon: number = lon2 - lon1;\n\n const a: number = Math.sin(dLat / 2) *\n Math.sin(dLat / 2) +\n Math.sin(dLon / 2) *\n Math.sin(dLon / 2) *\n Math.cos(lat1) *\n Math.cos(lat2);\n\n const safeA: number = Math.min(1, Math.max(0, a));\n const c: number = 2 * Math.asin(Math.sqrt(safeA));\n\n return R * c;\n };\n\n isGeolocationAvailable(): Promise<GeolocationPosition> {\n return new Promise((resolve, reject) => {\n if ('geolocation' in navigator) {\n navigator.geolocation.getCurrentPosition((data: GeolocationPosition) => {\n resolve(data);\n }, (error: GeolocationPositionError) => {\n switch (error.code) {\n case error.PERMISSION_DENIED:\n reject(new Error(\"Error: Permission denied\"));\n break;\n case error.POSITION_UNAVAILABLE:\n reject(new Error(\"Error: Position unavailable\"));\n break;\n case error.TIMEOUT:\n reject(new Error(\"Error: Timeout\"));\n break;\n }\n });\n } else {\n reject(new Error(\"Error: Geolocation disabled in your browser\"));\n }\n });\n };\n\n getDistanceBetween(p1: ILocationPoint, p2: ILocationPoint, measurement: string): number {\n if (p1.hasOwnProperty('latitude') && p1.hasOwnProperty('longitude') &&\n p2.hasOwnProperty('latitude') && p2.hasOwnProperty('longitude')) {\n const distance: number = this._haversine(\n p1.latitude,\n p1.longitude,\n p2.latitude,\n p2.longitude\n );\n\n return this._convertMeasurements(distance, measurement)\n\n } else {\n throw new Error(\"Error: Position latitude or longitude is not correct\");\n }\n }\n\n getClosestPosition(\n current: ILocationPoint,\n otherPoints: ILocationPoint[],\n measurement: string,\n ): ILocationPoint & {\n haversine: {\n distance: number;\n measurement: string;\n accuracy: number;\n };\n } {\n const distances: number[] = otherPoints.map((value: any) => this.getDistanceBetween(current, value, measurement));\n const indexOfSmallest: number = distances.indexOf(Math.min(...distances));\n\n return {\n ...otherPoints[indexOfSmallest],\n haversine: {\n distance: distances[indexOfSmallest],\n measurement,\n accuracy: current.accuracy\n },\n };\n };\n}\n\nexport default new HaversineGeolocation();\n","export interface Coordinate {\n latitude: number;\n longitude: number;\n}\n\nconst isFiniteNumber = (value: unknown): value is number =>\n typeof value === 'number' && Number.isFinite(value);\n\nconst hasCoordinateShape = (\n value: unknown,\n): value is { latitude: unknown; longitude: unknown } =>\n typeof value === 'object' &&\n value !== null &&\n 'latitude' in value &&\n 'longitude' in value;\n\nexport function assertCoordinate(\n value: unknown,\n): asserts value is Coordinate {\n if (!hasCoordinateShape(value)) {\n throw new TypeError('Coordinate must provide latitude and longitude');\n }\n\n if (!isFiniteNumber(value.latitude) || !isFiniteNumber(value.longitude)) {\n throw new TypeError('Coordinate latitude and longitude must be finite numbers');\n }\n\n if (value.latitude < -90 || value.latitude > 90) {\n throw new RangeError('Coordinate latitude must be between -90 and 90');\n }\n\n if (value.longitude < -180 || value.longitude > 180) {\n throw new RangeError('Coordinate longitude must be between -180 and 180');\n }\n}\n\nexport const isCoordinate = (value: unknown): value is Coordinate => {\n try {\n assertCoordinate(value);\n return true;\n } catch {\n return false;\n }\n};\n","export type DistanceUnit = 'm' | 'km' | 'mi';\n\nconst METRES_PER_UNIT: Record<DistanceUnit, number> = {\n m: 1,\n km: 1000,\n mi: 1609.344,\n};\n\nexport function assertDistanceUnit(\n value: unknown,\n): asserts value is DistanceUnit {\n if (value !== 'm' && value !== 'km' && value !== 'mi') {\n throw new TypeError('Distance unit must be one of: m, km, mi');\n }\n}\n\nexport const convertDistance = (\n value: number,\n from: DistanceUnit,\n to: DistanceUnit,\n): number => {\n if (!Number.isFinite(value)) {\n throw new TypeError('Distance value must be a finite number');\n }\n\n assertDistanceUnit(from);\n assertDistanceUnit(to);\n\n const metres = value * METRES_PER_UNIT[from];\n\n return metres / METRES_PER_UNIT[to];\n};\n","import { assertCoordinate } from './coordinate.js';\nimport type { Coordinate } from './coordinate.js';\nimport { convertDistance } from './units.js';\nimport type { DistanceUnit } from './units.js';\n\nexport const EARTH_MEAN_RADIUS_M = 6_371_008.8;\n\nexport interface DistanceOptions {\n unit?: DistanceUnit;\n radius?: number;\n}\n\nconst degreesToRadians = (degrees: number): number =>\n degrees * Math.PI / 180;\n\nconst assertRadius = (radius: number): void => {\n if (!Number.isFinite(radius)) {\n throw new TypeError('Radius must be a finite number');\n }\n\n if (radius <= 0) {\n throw new RangeError('Radius must be greater than zero');\n }\n};\n\nexport const distance = (\n from: Coordinate,\n to: Coordinate,\n options: DistanceOptions = {},\n): number => {\n assertCoordinate(from);\n assertCoordinate(to);\n\n const unit = options.unit ?? 'km';\n const radius = options.radius ?? EARTH_MEAN_RADIUS_M;\n\n assertRadius(radius);\n\n const latitude1 = degreesToRadians(from.latitude);\n const longitude1 = degreesToRadians(from.longitude);\n const latitude2 = degreesToRadians(to.latitude);\n const longitude2 = degreesToRadians(to.longitude);\n\n const latitudeDelta = latitude2 - latitude1;\n const longitudeDelta = longitude2 - longitude1;\n\n const latitudeHaversine = Math.sin(latitudeDelta / 2);\n const longitudeHaversine = Math.sin(longitudeDelta / 2);\n\n const a =\n latitudeHaversine * latitudeHaversine +\n longitudeHaversine * longitudeHaversine *\n Math.cos(latitude1) *\n Math.cos(latitude2);\n\n const safeA = Math.min(1, Math.max(0, a));\n const centralAngle = 2 * Math.asin(Math.sqrt(safeA));\n const metres = radius * centralAngle;\n\n return convertDistance(metres, 'm', unit);\n};\n","import type { Coordinate } from './coordinate.js';\nimport { distance } from './distance.js';\nimport type { DistanceOptions } from './distance.js';\n\nexport interface NearestResult<T> {\n point: T;\n distance: number;\n}\n\nexport const nearest = <T extends Coordinate>(\n origin: Coordinate,\n candidates: readonly T[],\n options: DistanceOptions = {},\n): NearestResult<T> | undefined => {\n let closestPoint: T | undefined;\n let closestDistance = Infinity;\n\n for (const candidate of candidates) {\n const candidateDistance = distance(origin, candidate, options);\n\n if (candidateDistance < closestDistance) {\n closestPoint = candidate;\n closestDistance = candidateDistance;\n }\n }\n\n if (closestPoint === undefined) {\n return undefined;\n }\n\n return {\n point: closestPoint,\n distance: closestDistance,\n };\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"build.js","names":["factory","global","exports","legacy_default","rawValue","measurement","distance","args","rad","deg","lat1","lon1","lat2","lon2","dLat","dLon","a","resolve","data","error","reject","p1","p2","distances","otherPoints","current","value","indexOfSmallest","isFiniteNumber","hasCoordinateShape","assertCoordinate","isCoordinate","METRES_PER_UNIT","assertDistanceUnit","convertDistance","from","to","EARTH_MEAN_RADIUS_M","degreesToRadians","degrees","assertRadius","radius","assertDistanceOptions","options","unit","latitude1","longitude1","latitude2","longitude2","latitudeDelta","longitudeDelta","latitudeHaversine","longitudeHaversine","origin","candidates","closestPoint","closestDistance","candidate","candidateDistance"],"sources":["../src/legacy.ts","../src/v2/coordinate.ts","../src/v2/units.ts","../src/v2/distance.ts","../src/v2/nearest.ts"],"sourcesContent":["import type { ILocationPoint } from './interfaces/ILocationPoint.js';\n\nclass HaversineGeolocation {\n _convertMeasurements(distance: number, measurement: string = 'km'): number {\n let rawValue: string = '';\n switch (measurement.toLowerCase()) {\n case 'mi':\n rawValue = (distance * 0.62137).toFixed(1);\n break;\n case 'km':\n rawValue = distance.toFixed(1);\n break;\n case 'm':\n rawValue = (distance * 1000).toFixed();\n break;\n default:\n rawValue = distance.toFixed(1);\n }\n return parseFloat(rawValue);\n }\n\n _haversine(...args: number[]): number {\n const rad: number[] = args.map((deg: number) => (deg / 180.0) * Math.PI);\n const lat1: number = rad[0];\n const lon1: number = rad[1];\n const lat2: number = rad[2];\n const lon2: number = rad[3];\n const R: number = 6372.8;\n const dLat: number = lat2 - lat1;\n const dLon: number = lon2 - lon1;\n\n const a: number =\n Math.sin(dLat / 2) * Math.sin(dLat / 2) +\n Math.sin(dLon / 2) * Math.sin(dLon / 2) * Math.cos(lat1) * Math.cos(lat2);\n\n const safeA: number = Math.min(1, Math.max(0, a));\n const c: number = 2 * Math.asin(Math.sqrt(safeA));\n\n return R * c;\n }\n\n isGeolocationAvailable(): Promise<GeolocationPosition> {\n return new Promise((resolve, reject) => {\n if ('geolocation' in navigator) {\n navigator.geolocation.getCurrentPosition(\n (data: GeolocationPosition) => {\n resolve(data);\n },\n (error: GeolocationPositionError) => {\n switch (error.code) {\n case error.PERMISSION_DENIED:\n reject(new Error('Error: Permission denied'));\n break;\n case error.POSITION_UNAVAILABLE:\n reject(new Error('Error: Position unavailable'));\n break;\n case error.TIMEOUT:\n reject(new Error('Error: Timeout'));\n break;\n }\n },\n );\n } else {\n reject(new Error('Error: Geolocation disabled in your browser'));\n }\n });\n }\n\n getDistanceBetween(p1: ILocationPoint, p2: ILocationPoint, measurement: string): number {\n if (\n // biome-ignore lint/suspicious/noPrototypeBuiltins: Preserve ES2020-compatible V1 own-property checks without Object.hasOwn (ES2022).\n Object.prototype.hasOwnProperty.call(p1, 'latitude') &&\n // biome-ignore lint/suspicious/noPrototypeBuiltins: Preserve ES2020-compatible V1 own-property checks without Object.hasOwn (ES2022).\n Object.prototype.hasOwnProperty.call(p1, 'longitude') &&\n // biome-ignore lint/suspicious/noPrototypeBuiltins: Preserve ES2020-compatible V1 own-property checks without Object.hasOwn (ES2022).\n Object.prototype.hasOwnProperty.call(p2, 'latitude') &&\n // biome-ignore lint/suspicious/noPrototypeBuiltins: Preserve ES2020-compatible V1 own-property checks without Object.hasOwn (ES2022).\n Object.prototype.hasOwnProperty.call(p2, 'longitude')\n ) {\n const distance: number = this._haversine(\n p1.latitude,\n p1.longitude,\n p2.latitude,\n p2.longitude,\n );\n\n return this._convertMeasurements(distance, measurement);\n } else {\n throw new Error('Error: Position latitude or longitude is not correct');\n }\n }\n\n getClosestPosition(\n current: ILocationPoint,\n otherPoints: ILocationPoint[],\n measurement: string,\n ): ILocationPoint & {\n haversine: {\n distance: number;\n measurement: string;\n accuracy: number;\n };\n } {\n const distances: number[] = otherPoints.map((value) =>\n this.getDistanceBetween(current, value, measurement),\n );\n const indexOfSmallest: number = distances.indexOf(Math.min(...distances));\n\n return {\n ...otherPoints[indexOfSmallest],\n haversine: {\n distance: distances[indexOfSmallest],\n measurement,\n accuracy: current.accuracy,\n },\n };\n }\n}\n\nexport default new HaversineGeolocation();\n","export interface Coordinate {\n latitude: number;\n longitude: number;\n}\n\nconst isFiniteNumber = (value: unknown): value is number =>\n typeof value === 'number' && Number.isFinite(value);\n\nconst hasCoordinateShape = (value: unknown): value is { latitude: unknown; longitude: unknown } =>\n typeof value === 'object' && value !== null && 'latitude' in value && 'longitude' in value;\n\nexport function assertCoordinate(value: unknown): asserts value is Coordinate {\n if (!hasCoordinateShape(value)) {\n throw new TypeError('Coordinate must provide latitude and longitude');\n }\n\n if (!isFiniteNumber(value.latitude) || !isFiniteNumber(value.longitude)) {\n throw new TypeError('Coordinate latitude and longitude must be finite numbers');\n }\n\n if (value.latitude < -90 || value.latitude > 90) {\n throw new RangeError('Coordinate latitude must be between -90 and 90');\n }\n\n if (value.longitude < -180 || value.longitude > 180) {\n throw new RangeError('Coordinate longitude must be between -180 and 180');\n }\n}\n\nexport const isCoordinate = (value: unknown): value is Coordinate => {\n try {\n assertCoordinate(value);\n return true;\n } catch {\n return false;\n }\n};\n","export type DistanceUnit = 'm' | 'km' | 'mi';\n\nconst METRES_PER_UNIT: Record<DistanceUnit, number> = {\n m: 1,\n km: 1000,\n mi: 1609.344,\n};\n\nexport function assertDistanceUnit(value: unknown): asserts value is DistanceUnit {\n if (value !== 'm' && value !== 'km' && value !== 'mi') {\n throw new TypeError('Distance unit must be one of: m, km, mi');\n }\n}\n\nexport const convertDistance = (value: number, from: DistanceUnit, to: DistanceUnit): number => {\n if (!Number.isFinite(value)) {\n throw new TypeError('Distance value must be a finite number');\n }\n\n assertDistanceUnit(from);\n assertDistanceUnit(to);\n\n const metres = value * METRES_PER_UNIT[from];\n\n return metres / METRES_PER_UNIT[to];\n};\n","import { assertCoordinate } from './coordinate.js';\nimport type { Coordinate } from './coordinate.js';\nimport { assertDistanceUnit, convertDistance } from './units.js';\nimport type { DistanceUnit } from './units.js';\n\nexport const EARTH_MEAN_RADIUS_M = 6_371_008.8;\n\nexport interface DistanceOptions {\n unit?: DistanceUnit;\n radius?: number;\n}\n\nconst degreesToRadians = (degrees: number): number => (degrees * Math.PI) / 180;\n\nconst assertRadius = (radius: number): void => {\n if (!Number.isFinite(radius)) {\n throw new TypeError('Radius must be a finite number');\n }\n\n if (radius <= 0) {\n throw new RangeError('Radius must be greater than zero');\n }\n};\n\n// Validate options even when nearest() receives no candidates to measure.\nexport const assertDistanceOptions = (options: DistanceOptions = {}): void => {\n assertRadius(options.radius ?? EARTH_MEAN_RADIUS_M);\n assertDistanceUnit(options.unit ?? 'km');\n};\n\nexport const distance = (\n from: Coordinate,\n to: Coordinate,\n options: DistanceOptions = {},\n): number => {\n assertCoordinate(from);\n assertCoordinate(to);\n\n const unit = options.unit ?? 'km';\n const radius = options.radius ?? EARTH_MEAN_RADIUS_M;\n\n assertRadius(radius);\n\n const latitude1 = degreesToRadians(from.latitude);\n const longitude1 = degreesToRadians(from.longitude);\n const latitude2 = degreesToRadians(to.latitude);\n const longitude2 = degreesToRadians(to.longitude);\n\n const latitudeDelta = latitude2 - latitude1;\n const longitudeDelta = longitude2 - longitude1;\n\n const latitudeHaversine = Math.sin(latitudeDelta / 2);\n const longitudeHaversine = Math.sin(longitudeDelta / 2);\n\n const a =\n latitudeHaversine * latitudeHaversine +\n longitudeHaversine * longitudeHaversine * Math.cos(latitude1) * Math.cos(latitude2);\n\n const safeA = Math.min(1, Math.max(0, a));\n const centralAngle = 2 * Math.asin(Math.sqrt(safeA));\n const metres = radius * centralAngle;\n\n return convertDistance(metres, 'm', unit);\n};\n","import { assertCoordinate } from './coordinate.js';\nimport type { Coordinate } from './coordinate.js';\nimport { assertDistanceOptions, distance } from './distance.js';\nimport type { DistanceOptions } from './distance.js';\n\nexport interface NearestResult<T> {\n point: T;\n distance: number;\n}\n\nexport const nearest = <T extends Coordinate>(\n origin: Coordinate,\n candidates: readonly T[],\n options: DistanceOptions = {},\n): NearestResult<T> | undefined => {\n assertCoordinate(origin);\n\n if (candidates.length === 0) {\n assertDistanceOptions(options);\n return undefined;\n }\n\n let closestPoint: T | undefined;\n let closestDistance = Infinity;\n\n for (const candidate of candidates) {\n const candidateDistance = distance(origin, candidate, options);\n\n if (candidateDistance < closestDistance) {\n closestPoint = candidate;\n closestDistance = candidateDistance;\n }\n }\n\n if (closestPoint === undefined) {\n return undefined;\n }\n\n return {\n point: closestPoint,\n distance: closestDistance,\n };\n};\n"],"mappings":"wTAuHA,IAAAG,EAAe,IAAI,KArHQ,CACvB,qBAAqB,EAAkB,EAAsB,KAAc,CACvE,IAAIC,EAAmB,GACvB,OAAQC,EAAY,YAAY,EAAhC,CACI,IAAK,KACD,GAAYC,EAAW,OAAA,CAAS,QAAQ,CAAC,EACzC,MACJ,IAAK,KACD,EAAWA,EAAS,QAAQ,CAAC,EAC7B,MACJ,IAAK,IACD,GAAYA,EAAW,IAAA,CAAM,QAAQ,EACrC,MACJ,QACI,EAAWA,EAAS,QAAQ,CAAC,CACrC,CACA,OAAO,WAAWF,CAAQ,CAC9B,CAEA,WAAW,GAAGG,EAAwB,CAClC,IAAMC,EAAgBD,EAAK,IAAK,GAAiBE,EAAM,IAAS,KAAK,EAAE,EACjEC,EAAeF,EAAI,GACnBG,EAAeH,EAAI,GACnBI,EAAeJ,EAAI,GACnBK,EAAeL,EAAI,GAEnBM,EAAeF,EAAOF,EACtBK,EAAeF,EAAOF,EAEtBK,EACF,KAAK,IAAIF,EAAO,CAAC,EAAI,KAAK,IAAIA,EAAO,CAAC,EACtC,KAAK,IAAIC,EAAO,CAAC,EAAI,KAAK,IAAIA,EAAO,CAAC,EAAI,KAAK,IAAIL,CAAI,EAAI,KAAK,IAAIE,CAAI,EAK5E,MAFkB,GAAI,KAAK,KAAK,KAAK,KADf,KAAK,IAAI,EAAG,KAAK,IAAI,EAAGI,CAAC,CACL,CAAK,CAAC,EAEzC,MACX,CAEA,wBAAuD,CACnD,OAAO,IAAI,SAAS,EAAS,IAAW,CAChC,gBAAiB,UACjB,UAAU,YAAY,mBACjB,GAA8B,CAC3BC,EAAQC,CAAI,CAChB,EACC,GAAoC,CACjC,OAAQC,EAAM,KAAd,CACI,KAAKA,EAAM,kBACPC,EAAW,MAAM,0BAA0B,CAAC,EAC5C,MACJ,KAAKD,EAAM,qBACPC,EAAW,MAAM,6BAA6B,CAAC,EAC/C,MACJ,KAAKD,EAAM,QACPC,EAAW,MAAM,gBAAgB,CAAC,CAE1C,CACJ,CACJ,EAEAA,EAAW,MAAM,6CAA6C,CAAC,CAEvE,CAAC,CACL,CAEA,mBAAmB,EAAoB,EAAoB,EAA6B,CACpF,GAEI,OAAO,UAAU,eAAe,KAAKC,EAAI,UAAU,GAEnD,OAAO,UAAU,eAAe,KAAKA,EAAI,WAAW,GAEpD,OAAO,UAAU,eAAe,KAAKC,EAAI,UAAU,GAEnD,OAAO,UAAU,eAAe,KAAKA,EAAI,WAAW,EACtD,CACE,IAAMhB,EAAmB,KAAK,WAC1Be,EAAG,SACHA,EAAG,UACHC,EAAG,SACHA,EAAG,SACP,EAEA,OAAO,KAAK,qBAAqBhB,EAAUD,CAAW,CAC1D,CACI,MAAU,MAAM,sDAAsD,CAE9E,CAEA,mBACI,EACA,EACA,EAOF,CACE,IAAMkB,EAAsBC,EAAY,IAAK,GACzC,KAAK,mBAAmBC,EAASC,EAAOrB,CAAW,CACvD,EACMsB,EAA0BJ,EAAU,QAAQ,KAAK,IAAI,GAAGA,CAAS,CAAC,EAExE,MAAO,CACH,GAAGC,EAAYG,GACf,UAAW,CACP,SAAUJ,EAAUI,GACpB,cACA,SAAUF,EAAQ,QACtB,CACJ,CACJ,CACJ,EChHMG,EAAkB,GACpB,OAAOF,GAAU,UAAY,OAAO,SAASA,CAAK,EAEhDG,EAAsB,GACxB,OAAOH,GAAU,YAAYA,GAAkB,aAAcA,GAAS,cAAeA,EAEzF,SAAgBI,EAAiB,EAA6C,CAC1E,GAAI,CAACD,EAAmBH,CAAK,EACzB,MAAU,UAAU,gDAAgD,EAGxE,GAAI,CAACE,EAAeF,EAAM,QAAQ,GAAK,CAACE,EAAeF,EAAM,SAAS,EAClE,MAAU,UAAU,0DAA0D,EAGlF,GAAIA,EAAM,SAAW,KAAOA,EAAM,SAAW,GACzC,MAAU,WAAW,gDAAgD,EAGzE,GAAIA,EAAM,UAAY,MAAQA,EAAM,UAAY,IAC5C,MAAU,WAAW,mDAAmD,CAEhF,CAEA,IAAaK,EAAgB,GAAwC,CACjE,GAAI,CAEA,OADAD,EAAiBJ,CAAK,EACf,EACX,MAAQ,CACJ,MAAO,EACX,CACJ,EClCMM,EAAgD,CAClD,EAAG,EACH,GAAI,IACJ,GAAI,QACR,EAEA,SAAgBC,EAAmB,EAA+C,CAC9E,GAAIP,IAAU,KAAOA,IAAU,MAAQA,IAAU,KAC7C,MAAU,UAAU,yCAAyC,CAErE,CAEA,IAAaQ,GAAmB,EAAe,EAAoB,IAA6B,CAC5F,GAAI,CAAC,OAAO,SAASR,CAAK,EACtB,MAAU,UAAU,wCAAwC,EAQhE,OALAO,EAAmBE,CAAI,EACvBF,EAAmBG,CAAE,EAENV,EAAQM,EAAgBG,GAEvBH,EAAgBI,EACpC,ECpBaC,EAAsB,UAO7BC,EAAoB,GAA6BC,EAAU,KAAK,GAAM,IAEtEC,EAAgB,GAAyB,CAC3C,GAAI,CAAC,OAAO,SAASC,CAAM,EACvB,MAAU,UAAU,gCAAgC,EAGxD,GAAIA,GAAU,EACV,MAAU,WAAW,kCAAkC,CAE/D,EAGaC,GAAyB,EAA2B,CAAC,IAAY,CAC1EF,EAAaG,EAAQ,QAAA,SAA6B,EAClDV,EAAmBU,EAAQ,MAAQ,IAAI,CAC3C,EAEarC,GACT,EACA,EACA,EAA2B,CAAC,IACnB,CACTwB,EAAiBK,CAAI,EACrBL,EAAiBM,CAAE,EAEnB,IAAMQ,EAAOD,EAAQ,MAAQ,KACvBF,EAASE,EAAQ,QAAA,UAEvBH,EAAaC,CAAM,EAEnB,IAAMI,EAAYP,EAAiBH,EAAK,QAAQ,EAC1CW,EAAaR,EAAiBH,EAAK,SAAS,EAC5CY,EAAYT,EAAiBF,EAAG,QAAQ,EACxCY,EAAaV,EAAiBF,EAAG,SAAS,EAE1Ca,EAAgBF,EAAYF,EAC5BK,EAAiBF,EAAaF,EAE9BK,EAAoB,KAAK,IAAIF,EAAgB,CAAC,EAC9CG,EAAqB,KAAK,IAAIF,EAAiB,CAAC,EAEhDlC,EACFmC,EAAoBA,EACpBC,EAAqBA,EAAqB,KAAK,IAAIP,CAAS,EAAI,KAAK,IAAIE,CAAS,EAMtF,OAAOb,EAHc,EAAI,KAAK,KAAK,KAAK,KAD1B,KAAK,IAAI,EAAG,KAAK,IAAI,EAAGlB,CAAC,CACM,CAAK,CAAC,EACpCyB,EAEgB,IAAKG,CAAI,CAC5C,+ICpDI,EACA,EACA,EAA2B,CAAC,IACG,CAG/B,GAFAd,EAAiBuB,CAAM,EAEnBC,EAAW,SAAW,EAAG,CACzBZ,EAAsBC,CAAO,EAC7B,MACJ,CAEA,IAAIY,EACAC,EAAkB,IAEtB,IAAK,IAAMC,KAAaH,EAAY,CAChC,IAAMI,EAAoBpD,EAAS+C,EAAQI,EAAWd,CAAO,EAEzDe,EAAoBF,IACpB,EAAeC,EACf,EAAkBC,EAE1B,CAEA,GAAIH,IAAiB,IAAA,GAIrB,MAAO,CACH,MAAOA,EACP,SAAUC,CACd,CACJ"}
package/dist/index.cjs CHANGED
@@ -1,2 +1,2 @@
1
- Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:`Module`}});const e=require("./legacy.cjs");var t=e=>typeof e==`number`&&Number.isFinite(e),n=e=>typeof e==`object`&&!!e&&`latitude`in e&&`longitude`in e;function r(e){if(!n(e))throw TypeError(`Coordinate must provide latitude and longitude`);if(!t(e.latitude)||!t(e.longitude))throw TypeError(`Coordinate latitude and longitude must be finite numbers`);if(e.latitude<-90||e.latitude>90)throw RangeError(`Coordinate latitude must be between -90 and 90`);if(e.longitude<-180||e.longitude>180)throw RangeError(`Coordinate longitude must be between -180 and 180`)}var i=e=>{try{return r(e),!0}catch{return!1}},a={m:1,km:1e3,mi:1609.344};function o(e){if(e!==`m`&&e!==`km`&&e!==`mi`)throw TypeError(`Distance unit must be one of: m, km, mi`)}var s=(e,t,n)=>{if(!Number.isFinite(e))throw TypeError(`Distance value must be a finite number`);return o(t),o(n),e*a[t]/a[n]},c=6371008.8,l=e=>e*Math.PI/180,u=e=>{if(!Number.isFinite(e))throw TypeError(`Radius must be a finite number`);if(e<=0)throw RangeError(`Radius must be greater than zero`)},d=(e,t,n={})=>{r(e),r(t);let i=n.unit??`km`,a=n.radius??6371008.8;u(a);let o=l(e.latitude),c=l(e.longitude),d=l(t.latitude),f=l(t.longitude),p=d-o,m=f-c,h=Math.sin(p/2),g=Math.sin(m/2),_=h*h+g*g*Math.cos(o)*Math.cos(d);return s(2*Math.asin(Math.sqrt(Math.min(1,Math.max(0,_))))*a,`m`,i)},f=(e,t,n={})=>{let r,i=1/0;for(let a of t){let t=d(e,a,n);t<i&&(r=a,i=t)}if(r!==void 0)return{point:r,distance:i}};exports.EARTH_MEAN_RADIUS_M=c,exports.assertCoordinate=r,exports.assertDistanceUnit=o,exports.convertDistance=s,exports.default=e.default,exports.distance=d,exports.isCoordinate=i,exports.nearest=f;
1
+ Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:`Module`}});const e=require("./legacy.cjs");var t=e=>typeof e==`number`&&Number.isFinite(e),n=e=>typeof e==`object`&&!!e&&`latitude`in e&&`longitude`in e;function r(e){if(!n(e))throw TypeError(`Coordinate must provide latitude and longitude`);if(!t(e.latitude)||!t(e.longitude))throw TypeError(`Coordinate latitude and longitude must be finite numbers`);if(e.latitude<-90||e.latitude>90)throw RangeError(`Coordinate latitude must be between -90 and 90`);if(e.longitude<-180||e.longitude>180)throw RangeError(`Coordinate longitude must be between -180 and 180`)}var i=e=>{try{return r(e),!0}catch{return!1}},a={m:1,km:1e3,mi:1609.344};function o(e){if(e!==`m`&&e!==`km`&&e!==`mi`)throw TypeError(`Distance unit must be one of: m, km, mi`)}var s=(e,t,n)=>{if(!Number.isFinite(e))throw TypeError(`Distance value must be a finite number`);return o(t),o(n),e*a[t]/a[n]},c=6371008.8,l=e=>e*Math.PI/180,u=e=>{if(!Number.isFinite(e))throw TypeError(`Radius must be a finite number`);if(e<=0)throw RangeError(`Radius must be greater than zero`)},d=(e={})=>{u(e.radius??6371008.8),o(e.unit??`km`)},f=(e,t,n={})=>{r(e),r(t);let i=n.unit??`km`,a=n.radius??6371008.8;u(a);let o=l(e.latitude),c=l(e.longitude),d=l(t.latitude),f=l(t.longitude),p=d-o,m=f-c,h=Math.sin(p/2),g=Math.sin(m/2),_=h*h+g*g*Math.cos(o)*Math.cos(d);return s(2*Math.asin(Math.sqrt(Math.min(1,Math.max(0,_))))*a,`m`,i)},p=(e,t,n={})=>{if(r(e),t.length===0){d(n);return}let i,a=1/0;for(let r of t){let t=f(e,r,n);t<a&&(i=r,a=t)}if(i!==void 0)return{point:i,distance:a}};exports.EARTH_MEAN_RADIUS_M=c,exports.assertCoordinate=r,exports.assertDistanceUnit=o,exports.convertDistance=s,exports.default=e.default,exports.distance=f,exports.isCoordinate=i,exports.nearest=p;
2
2
  //# sourceMappingURL=index.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","names":["require_legacy","isFiniteNumber","value","hasCoordinateShape","assertCoordinate","isCoordinate","METRES_PER_UNIT","assertDistanceUnit","convertDistance","from","to","EARTH_MEAN_RADIUS_M","degreesToRadians","degrees","assertRadius","radius","distance","unit","options","latitude1","longitude1","latitude2","longitude2","latitudeDelta","longitudeDelta","latitudeHaversine","longitudeHaversine","a","nearest","closestPoint","closestDistance","candidate","candidates","candidateDistance","origin"],"sources":["../src/v2/coordinate.ts","../src/v2/units.ts","../src/v2/distance.ts","../src/v2/nearest.ts"],"sourcesContent":["export interface Coordinate {\n latitude: number;\n longitude: number;\n}\n\nconst isFiniteNumber = (value: unknown): value is number =>\n typeof value === 'number' && Number.isFinite(value);\n\nconst hasCoordinateShape = (\n value: unknown,\n): value is { latitude: unknown; longitude: unknown } =>\n typeof value === 'object' &&\n value !== null &&\n 'latitude' in value &&\n 'longitude' in value;\n\nexport function assertCoordinate(\n value: unknown,\n): asserts value is Coordinate {\n if (!hasCoordinateShape(value)) {\n throw new TypeError('Coordinate must provide latitude and longitude');\n }\n\n if (!isFiniteNumber(value.latitude) || !isFiniteNumber(value.longitude)) {\n throw new TypeError('Coordinate latitude and longitude must be finite numbers');\n }\n\n if (value.latitude < -90 || value.latitude > 90) {\n throw new RangeError('Coordinate latitude must be between -90 and 90');\n }\n\n if (value.longitude < -180 || value.longitude > 180) {\n throw new RangeError('Coordinate longitude must be between -180 and 180');\n }\n}\n\nexport const isCoordinate = (value: unknown): value is Coordinate => {\n try {\n assertCoordinate(value);\n return true;\n } catch {\n return false;\n }\n};\n","export type DistanceUnit = 'm' | 'km' | 'mi';\n\nconst METRES_PER_UNIT: Record<DistanceUnit, number> = {\n m: 1,\n km: 1000,\n mi: 1609.344,\n};\n\nexport function assertDistanceUnit(\n value: unknown,\n): asserts value is DistanceUnit {\n if (value !== 'm' && value !== 'km' && value !== 'mi') {\n throw new TypeError('Distance unit must be one of: m, km, mi');\n }\n}\n\nexport const convertDistance = (\n value: number,\n from: DistanceUnit,\n to: DistanceUnit,\n): number => {\n if (!Number.isFinite(value)) {\n throw new TypeError('Distance value must be a finite number');\n }\n\n assertDistanceUnit(from);\n assertDistanceUnit(to);\n\n const metres = value * METRES_PER_UNIT[from];\n\n return metres / METRES_PER_UNIT[to];\n};\n","import { assertCoordinate } from './coordinate.js';\nimport type { Coordinate } from './coordinate.js';\nimport { convertDistance } from './units.js';\nimport type { DistanceUnit } from './units.js';\n\nexport const EARTH_MEAN_RADIUS_M = 6_371_008.8;\n\nexport interface DistanceOptions {\n unit?: DistanceUnit;\n radius?: number;\n}\n\nconst degreesToRadians = (degrees: number): number =>\n degrees * Math.PI / 180;\n\nconst assertRadius = (radius: number): void => {\n if (!Number.isFinite(radius)) {\n throw new TypeError('Radius must be a finite number');\n }\n\n if (radius <= 0) {\n throw new RangeError('Radius must be greater than zero');\n }\n};\n\nexport const distance = (\n from: Coordinate,\n to: Coordinate,\n options: DistanceOptions = {},\n): number => {\n assertCoordinate(from);\n assertCoordinate(to);\n\n const unit = options.unit ?? 'km';\n const radius = options.radius ?? EARTH_MEAN_RADIUS_M;\n\n assertRadius(radius);\n\n const latitude1 = degreesToRadians(from.latitude);\n const longitude1 = degreesToRadians(from.longitude);\n const latitude2 = degreesToRadians(to.latitude);\n const longitude2 = degreesToRadians(to.longitude);\n\n const latitudeDelta = latitude2 - latitude1;\n const longitudeDelta = longitude2 - longitude1;\n\n const latitudeHaversine = Math.sin(latitudeDelta / 2);\n const longitudeHaversine = Math.sin(longitudeDelta / 2);\n\n const a =\n latitudeHaversine * latitudeHaversine +\n longitudeHaversine * longitudeHaversine *\n Math.cos(latitude1) *\n Math.cos(latitude2);\n\n const safeA = Math.min(1, Math.max(0, a));\n const centralAngle = 2 * Math.asin(Math.sqrt(safeA));\n const metres = radius * centralAngle;\n\n return convertDistance(metres, 'm', unit);\n};\n","import type { Coordinate } from './coordinate.js';\nimport { distance } from './distance.js';\nimport type { DistanceOptions } from './distance.js';\n\nexport interface NearestResult<T> {\n point: T;\n distance: number;\n}\n\nexport const nearest = <T extends Coordinate>(\n origin: Coordinate,\n candidates: readonly T[],\n options: DistanceOptions = {},\n): NearestResult<T> | undefined => {\n let closestPoint: T | undefined;\n let closestDistance = Infinity;\n\n for (const candidate of candidates) {\n const candidateDistance = distance(origin, candidate, options);\n\n if (candidateDistance < closestDistance) {\n closestPoint = candidate;\n closestDistance = candidateDistance;\n }\n }\n\n if (closestPoint === undefined) {\n return undefined;\n }\n\n return {\n point: closestPoint,\n distance: closestDistance,\n };\n};\n"],"mappings":"+HAKA,IAAMC,EAAkB,GACpB,OAAOC,GAAU,UAAY,OAAO,SAASA,CAAK,EAEhDC,EACF,GAEA,OAAOD,GAAU,YACjBA,GACA,aAAcA,GACd,cAAeA,EAEnB,SAAgBE,EACZ,EAC2B,CAC3B,GAAI,CAACD,EAAmBD,CAAK,EACzB,MAAU,UAAU,gDAAgD,EAGxE,GAAI,CAACD,EAAeC,EAAM,QAAQ,GAAK,CAACD,EAAeC,EAAM,SAAS,EAClE,MAAU,UAAU,0DAA0D,EAGlF,GAAIA,EAAM,SAAW,KAAOA,EAAM,SAAW,GACzC,MAAU,WAAW,gDAAgD,EAGzE,GAAIA,EAAM,UAAY,MAAQA,EAAM,UAAY,IAC5C,MAAU,WAAW,mDAAmD,CAEhF,CAEA,IAAaG,EAAgB,GAAwC,CACjE,GAAI,CAEA,OADAD,EAAiBF,CAAK,EACf,EACX,MAAQ,CACJ,MAAO,EACX,CACJ,ECzCMI,EAAgD,CAClD,EAAG,EACH,GAAI,IACJ,GAAI,QACR,EAEA,SAAgBC,EACZ,EAC6B,CAC7B,GAAIL,IAAU,KAAOA,IAAU,MAAQA,IAAU,KAC7C,MAAU,UAAU,yCAAyC,CAErE,CAEA,IAAaM,GACT,EACA,EACA,IACS,CACT,GAAI,CAAC,OAAO,SAASN,CAAK,EACtB,MAAU,UAAU,wCAAwC,EAQhE,OALAK,EAAmBE,CAAI,EACvBF,EAAmBG,CAAE,EAENR,EAAQI,EAAgBG,GAEvBH,EAAgBI,EACpC,EC1BaC,EAAsB,UAO7BC,EAAoB,GACtBC,EAAU,KAAK,GAAK,IAElBC,EAAgB,GAAyB,CAC3C,GAAI,CAAC,OAAO,SAASC,CAAM,EACvB,MAAU,UAAU,gCAAgC,EAGxD,GAAIA,GAAU,EACV,MAAU,WAAW,kCAAkC,CAE/D,EAEaC,GACT,EACA,EACA,EAA2B,CAAC,IACnB,CACTZ,EAAiBK,CAAI,EACrBL,EAAiBM,CAAE,EAEnB,IAAMO,EAAOC,EAAQ,MAAQ,KACvBH,EAASG,EAAQ,QAAA,UAEvBJ,EAAaC,CAAM,EAEnB,IAAMI,EAAYP,EAAiBH,EAAK,QAAQ,EAC1CW,EAAaR,EAAiBH,EAAK,SAAS,EAC5CY,EAAYT,EAAiBF,EAAG,QAAQ,EACxCY,EAAaV,EAAiBF,EAAG,SAAS,EAE1Ca,EAAgBF,EAAYF,EAC5BK,EAAiBF,EAAaF,EAE9BK,EAAoB,KAAK,IAAIF,EAAgB,CAAC,EAC9CG,EAAqB,KAAK,IAAIF,EAAiB,CAAC,EAEhDG,EACFF,EAAoBA,EACpBC,EAAqBA,EACrB,KAAK,IAAIP,CAAS,EAClB,KAAK,IAAIE,CAAS,EAMtB,OAAOb,EAHc,EAAI,KAAK,KAAK,KAAK,KAD1B,KAAK,IAAI,EAAG,KAAK,IAAI,EAAGmB,CAAC,CACM,CAAK,CAAC,EACpCZ,EAEgB,IAAKE,CAAI,CAC5C,ECnDaW,GACT,EACA,EACA,EAA2B,CAAC,IACG,CAC/B,IAAIC,EACAC,EAAkB,IAEtB,IAAK,IAAMC,KAAaC,EAAY,CAChC,IAAMC,EAAoBjB,EAASkB,EAAQH,EAAWb,CAAO,EAEzDe,EAAoBH,IACpB,EAAeC,EACf,EAAkBE,EAE1B,CAEA,GAAIJ,IAAiB,IAAA,GAIrB,MAAO,CACH,MAAOA,EACP,SAAUC,CACd,CACJ"}
1
+ {"version":3,"file":"index.cjs","names":["require_legacy","isFiniteNumber","value","hasCoordinateShape","assertCoordinate","isCoordinate","METRES_PER_UNIT","assertDistanceUnit","convertDistance","from","to","EARTH_MEAN_RADIUS_M","degreesToRadians","degrees","assertRadius","radius","assertDistanceOptions","options","distance","unit","latitude1","longitude1","latitude2","longitude2","latitudeDelta","longitudeDelta","latitudeHaversine","longitudeHaversine","a","nearest","origin","candidates","closestPoint","closestDistance","candidate","candidateDistance"],"sources":["../src/v2/coordinate.ts","../src/v2/units.ts","../src/v2/distance.ts","../src/v2/nearest.ts"],"sourcesContent":["export interface Coordinate {\n latitude: number;\n longitude: number;\n}\n\nconst isFiniteNumber = (value: unknown): value is number =>\n typeof value === 'number' && Number.isFinite(value);\n\nconst hasCoordinateShape = (value: unknown): value is { latitude: unknown; longitude: unknown } =>\n typeof value === 'object' && value !== null && 'latitude' in value && 'longitude' in value;\n\nexport function assertCoordinate(value: unknown): asserts value is Coordinate {\n if (!hasCoordinateShape(value)) {\n throw new TypeError('Coordinate must provide latitude and longitude');\n }\n\n if (!isFiniteNumber(value.latitude) || !isFiniteNumber(value.longitude)) {\n throw new TypeError('Coordinate latitude and longitude must be finite numbers');\n }\n\n if (value.latitude < -90 || value.latitude > 90) {\n throw new RangeError('Coordinate latitude must be between -90 and 90');\n }\n\n if (value.longitude < -180 || value.longitude > 180) {\n throw new RangeError('Coordinate longitude must be between -180 and 180');\n }\n}\n\nexport const isCoordinate = (value: unknown): value is Coordinate => {\n try {\n assertCoordinate(value);\n return true;\n } catch {\n return false;\n }\n};\n","export type DistanceUnit = 'm' | 'km' | 'mi';\n\nconst METRES_PER_UNIT: Record<DistanceUnit, number> = {\n m: 1,\n km: 1000,\n mi: 1609.344,\n};\n\nexport function assertDistanceUnit(value: unknown): asserts value is DistanceUnit {\n if (value !== 'm' && value !== 'km' && value !== 'mi') {\n throw new TypeError('Distance unit must be one of: m, km, mi');\n }\n}\n\nexport const convertDistance = (value: number, from: DistanceUnit, to: DistanceUnit): number => {\n if (!Number.isFinite(value)) {\n throw new TypeError('Distance value must be a finite number');\n }\n\n assertDistanceUnit(from);\n assertDistanceUnit(to);\n\n const metres = value * METRES_PER_UNIT[from];\n\n return metres / METRES_PER_UNIT[to];\n};\n","import { assertCoordinate } from './coordinate.js';\nimport type { Coordinate } from './coordinate.js';\nimport { assertDistanceUnit, convertDistance } from './units.js';\nimport type { DistanceUnit } from './units.js';\n\nexport const EARTH_MEAN_RADIUS_M = 6_371_008.8;\n\nexport interface DistanceOptions {\n unit?: DistanceUnit;\n radius?: number;\n}\n\nconst degreesToRadians = (degrees: number): number => (degrees * Math.PI) / 180;\n\nconst assertRadius = (radius: number): void => {\n if (!Number.isFinite(radius)) {\n throw new TypeError('Radius must be a finite number');\n }\n\n if (radius <= 0) {\n throw new RangeError('Radius must be greater than zero');\n }\n};\n\n// Validate options even when nearest() receives no candidates to measure.\nexport const assertDistanceOptions = (options: DistanceOptions = {}): void => {\n assertRadius(options.radius ?? EARTH_MEAN_RADIUS_M);\n assertDistanceUnit(options.unit ?? 'km');\n};\n\nexport const distance = (\n from: Coordinate,\n to: Coordinate,\n options: DistanceOptions = {},\n): number => {\n assertCoordinate(from);\n assertCoordinate(to);\n\n const unit = options.unit ?? 'km';\n const radius = options.radius ?? EARTH_MEAN_RADIUS_M;\n\n assertRadius(radius);\n\n const latitude1 = degreesToRadians(from.latitude);\n const longitude1 = degreesToRadians(from.longitude);\n const latitude2 = degreesToRadians(to.latitude);\n const longitude2 = degreesToRadians(to.longitude);\n\n const latitudeDelta = latitude2 - latitude1;\n const longitudeDelta = longitude2 - longitude1;\n\n const latitudeHaversine = Math.sin(latitudeDelta / 2);\n const longitudeHaversine = Math.sin(longitudeDelta / 2);\n\n const a =\n latitudeHaversine * latitudeHaversine +\n longitudeHaversine * longitudeHaversine * Math.cos(latitude1) * Math.cos(latitude2);\n\n const safeA = Math.min(1, Math.max(0, a));\n const centralAngle = 2 * Math.asin(Math.sqrt(safeA));\n const metres = radius * centralAngle;\n\n return convertDistance(metres, 'm', unit);\n};\n","import { assertCoordinate } from './coordinate.js';\nimport type { Coordinate } from './coordinate.js';\nimport { assertDistanceOptions, distance } from './distance.js';\nimport type { DistanceOptions } from './distance.js';\n\nexport interface NearestResult<T> {\n point: T;\n distance: number;\n}\n\nexport const nearest = <T extends Coordinate>(\n origin: Coordinate,\n candidates: readonly T[],\n options: DistanceOptions = {},\n): NearestResult<T> | undefined => {\n assertCoordinate(origin);\n\n if (candidates.length === 0) {\n assertDistanceOptions(options);\n return undefined;\n }\n\n let closestPoint: T | undefined;\n let closestDistance = Infinity;\n\n for (const candidate of candidates) {\n const candidateDistance = distance(origin, candidate, options);\n\n if (candidateDistance < closestDistance) {\n closestPoint = candidate;\n closestDistance = candidateDistance;\n }\n }\n\n if (closestPoint === undefined) {\n return undefined;\n }\n\n return {\n point: closestPoint,\n distance: closestDistance,\n };\n};\n"],"mappings":"+HAKA,IAAMC,EAAkB,GACpB,OAAOC,GAAU,UAAY,OAAO,SAASA,CAAK,EAEhDC,EAAsB,GACxB,OAAOD,GAAU,YAAYA,GAAkB,aAAcA,GAAS,cAAeA,EAEzF,SAAgBE,EAAiB,EAA6C,CAC1E,GAAI,CAACD,EAAmBD,CAAK,EACzB,MAAU,UAAU,gDAAgD,EAGxE,GAAI,CAACD,EAAeC,EAAM,QAAQ,GAAK,CAACD,EAAeC,EAAM,SAAS,EAClE,MAAU,UAAU,0DAA0D,EAGlF,GAAIA,EAAM,SAAW,KAAOA,EAAM,SAAW,GACzC,MAAU,WAAW,gDAAgD,EAGzE,GAAIA,EAAM,UAAY,MAAQA,EAAM,UAAY,IAC5C,MAAU,WAAW,mDAAmD,CAEhF,CAEA,IAAaG,EAAgB,GAAwC,CACjE,GAAI,CAEA,OADAD,EAAiBF,CAAK,EACf,EACX,MAAQ,CACJ,MAAO,EACX,CACJ,EClCMI,EAAgD,CAClD,EAAG,EACH,GAAI,IACJ,GAAI,QACR,EAEA,SAAgBC,EAAmB,EAA+C,CAC9E,GAAIL,IAAU,KAAOA,IAAU,MAAQA,IAAU,KAC7C,MAAU,UAAU,yCAAyC,CAErE,CAEA,IAAaM,GAAmB,EAAe,EAAoB,IAA6B,CAC5F,GAAI,CAAC,OAAO,SAASN,CAAK,EACtB,MAAU,UAAU,wCAAwC,EAQhE,OALAK,EAAmBE,CAAI,EACvBF,EAAmBG,CAAE,EAENR,EAAQI,EAAgBG,GAEvBH,EAAgBI,EACpC,ECpBaC,EAAsB,UAO7BC,EAAoB,GAA6BC,EAAU,KAAK,GAAM,IAEtEC,EAAgB,GAAyB,CAC3C,GAAI,CAAC,OAAO,SAASC,CAAM,EACvB,MAAU,UAAU,gCAAgC,EAGxD,GAAIA,GAAU,EACV,MAAU,WAAW,kCAAkC,CAE/D,EAGaC,GAAyB,EAA2B,CAAC,IAAY,CAC1EF,EAAaG,EAAQ,QAAA,SAA6B,EAClDV,EAAmBU,EAAQ,MAAQ,IAAI,CAC3C,EAEaC,GACT,EACA,EACA,EAA2B,CAAC,IACnB,CACTd,EAAiBK,CAAI,EACrBL,EAAiBM,CAAE,EAEnB,IAAMS,EAAOF,EAAQ,MAAQ,KACvBF,EAASE,EAAQ,QAAA,UAEvBH,EAAaC,CAAM,EAEnB,IAAMK,EAAYR,EAAiBH,EAAK,QAAQ,EAC1CY,EAAaT,EAAiBH,EAAK,SAAS,EAC5Ca,EAAYV,EAAiBF,EAAG,QAAQ,EACxCa,EAAaX,EAAiBF,EAAG,SAAS,EAE1Cc,EAAgBF,EAAYF,EAC5BK,EAAiBF,EAAaF,EAE9BK,EAAoB,KAAK,IAAIF,EAAgB,CAAC,EAC9CG,EAAqB,KAAK,IAAIF,EAAiB,CAAC,EAEhDG,EACFF,EAAoBA,EACpBC,EAAqBA,EAAqB,KAAK,IAAIP,CAAS,EAAI,KAAK,IAAIE,CAAS,EAMtF,OAAOd,EAHc,EAAI,KAAK,KAAK,KAAK,KAD1B,KAAK,IAAI,EAAG,KAAK,IAAI,EAAGoB,CAAC,CACM,CAAK,CAAC,EACpCb,EAEgB,IAAKI,CAAI,CAC5C,ECrDaU,GACT,EACA,EACA,EAA2B,CAAC,IACG,CAG/B,GAFAzB,EAAiB0B,CAAM,EAEnBC,EAAW,SAAW,EAAG,CACzBf,EAAsBC,CAAO,EAC7B,MACJ,CAEA,IAAIe,EACAC,EAAkB,IAEtB,IAAK,IAAMC,KAAaH,EAAY,CAChC,IAAMI,EAAoBjB,EAASY,EAAQI,EAAWjB,CAAO,EAEzDkB,EAAoBF,IACpB,EAAeC,EACf,EAAkBC,EAE1B,CAEA,GAAIH,IAAiB,IAAA,GAIrB,MAAO,CACH,MAAOA,EACP,SAAUC,CACd,CACJ"}
package/dist/index.mjs CHANGED
@@ -27,24 +27,30 @@ var s = (e, t, n) => {
27
27
  }, c = 6371008.8, l = (e) => e * Math.PI / 180, u = (e) => {
28
28
  if (!Number.isFinite(e)) throw TypeError("Radius must be a finite number");
29
29
  if (e <= 0) throw RangeError("Radius must be greater than zero");
30
- }, d = (e, t, n = {}) => {
30
+ }, d = (e = {}) => {
31
+ u(e.radius ?? 6371008.8), o(e.unit ?? "km");
32
+ }, f = (e, t, n = {}) => {
31
33
  r(e), r(t);
32
34
  let i = n.unit ?? "km", a = n.radius ?? 6371008.8;
33
35
  u(a);
34
36
  let o = l(e.latitude), c = l(e.longitude), d = l(t.latitude), f = l(t.longitude), p = d - o, m = f - c, h = Math.sin(p / 2), g = Math.sin(m / 2), _ = h * h + g * g * Math.cos(o) * Math.cos(d);
35
37
  return s(2 * Math.asin(Math.sqrt(Math.min(1, Math.max(0, _)))) * a, "m", i);
36
- }, f = (e, t, n = {}) => {
37
- let r, i = Infinity;
38
- for (let a of t) {
39
- let t = d(e, a, n);
40
- t < i && (r = a, i = t);
38
+ }, p = (e, t, n = {}) => {
39
+ if (r(e), t.length === 0) {
40
+ d(n);
41
+ return;
42
+ }
43
+ let i, a = Infinity;
44
+ for (let r of t) {
45
+ let t = f(e, r, n);
46
+ t < a && (i = r, a = t);
41
47
  }
42
- if (r !== void 0) return {
43
- point: r,
44
- distance: i
48
+ if (i !== void 0) return {
49
+ point: i,
50
+ distance: a
45
51
  };
46
52
  };
47
53
  //#endregion
48
- export { c as EARTH_MEAN_RADIUS_M, r as assertCoordinate, o as assertDistanceUnit, s as convertDistance, e as default, d as distance, i as isCoordinate, f as nearest };
54
+ export { c as EARTH_MEAN_RADIUS_M, r as assertCoordinate, o as assertDistanceUnit, s as convertDistance, e as default, f as distance, i as isCoordinate, p as nearest };
49
55
 
50
56
  //# sourceMappingURL=index.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":["legacy_default","isFiniteNumber","value","hasCoordinateShape","assertCoordinate","isCoordinate","METRES_PER_UNIT","assertDistanceUnit","convertDistance","from","to","EARTH_MEAN_RADIUS_M","degreesToRadians","degrees","assertRadius","radius","distance","unit","options","latitude1","longitude1","latitude2","longitude2","latitudeDelta","longitudeDelta","latitudeHaversine","longitudeHaversine","a","nearest","closestPoint","closestDistance","candidate","candidates","candidateDistance","origin"],"sources":["../src/v2/coordinate.ts","../src/v2/units.ts","../src/v2/distance.ts","../src/v2/nearest.ts"],"sourcesContent":["export interface Coordinate {\n latitude: number;\n longitude: number;\n}\n\nconst isFiniteNumber = (value: unknown): value is number =>\n typeof value === 'number' && Number.isFinite(value);\n\nconst hasCoordinateShape = (\n value: unknown,\n): value is { latitude: unknown; longitude: unknown } =>\n typeof value === 'object' &&\n value !== null &&\n 'latitude' in value &&\n 'longitude' in value;\n\nexport function assertCoordinate(\n value: unknown,\n): asserts value is Coordinate {\n if (!hasCoordinateShape(value)) {\n throw new TypeError('Coordinate must provide latitude and longitude');\n }\n\n if (!isFiniteNumber(value.latitude) || !isFiniteNumber(value.longitude)) {\n throw new TypeError('Coordinate latitude and longitude must be finite numbers');\n }\n\n if (value.latitude < -90 || value.latitude > 90) {\n throw new RangeError('Coordinate latitude must be between -90 and 90');\n }\n\n if (value.longitude < -180 || value.longitude > 180) {\n throw new RangeError('Coordinate longitude must be between -180 and 180');\n }\n}\n\nexport const isCoordinate = (value: unknown): value is Coordinate => {\n try {\n assertCoordinate(value);\n return true;\n } catch {\n return false;\n }\n};\n","export type DistanceUnit = 'm' | 'km' | 'mi';\n\nconst METRES_PER_UNIT: Record<DistanceUnit, number> = {\n m: 1,\n km: 1000,\n mi: 1609.344,\n};\n\nexport function assertDistanceUnit(\n value: unknown,\n): asserts value is DistanceUnit {\n if (value !== 'm' && value !== 'km' && value !== 'mi') {\n throw new TypeError('Distance unit must be one of: m, km, mi');\n }\n}\n\nexport const convertDistance = (\n value: number,\n from: DistanceUnit,\n to: DistanceUnit,\n): number => {\n if (!Number.isFinite(value)) {\n throw new TypeError('Distance value must be a finite number');\n }\n\n assertDistanceUnit(from);\n assertDistanceUnit(to);\n\n const metres = value * METRES_PER_UNIT[from];\n\n return metres / METRES_PER_UNIT[to];\n};\n","import { assertCoordinate } from './coordinate.js';\nimport type { Coordinate } from './coordinate.js';\nimport { convertDistance } from './units.js';\nimport type { DistanceUnit } from './units.js';\n\nexport const EARTH_MEAN_RADIUS_M = 6_371_008.8;\n\nexport interface DistanceOptions {\n unit?: DistanceUnit;\n radius?: number;\n}\n\nconst degreesToRadians = (degrees: number): number =>\n degrees * Math.PI / 180;\n\nconst assertRadius = (radius: number): void => {\n if (!Number.isFinite(radius)) {\n throw new TypeError('Radius must be a finite number');\n }\n\n if (radius <= 0) {\n throw new RangeError('Radius must be greater than zero');\n }\n};\n\nexport const distance = (\n from: Coordinate,\n to: Coordinate,\n options: DistanceOptions = {},\n): number => {\n assertCoordinate(from);\n assertCoordinate(to);\n\n const unit = options.unit ?? 'km';\n const radius = options.radius ?? EARTH_MEAN_RADIUS_M;\n\n assertRadius(radius);\n\n const latitude1 = degreesToRadians(from.latitude);\n const longitude1 = degreesToRadians(from.longitude);\n const latitude2 = degreesToRadians(to.latitude);\n const longitude2 = degreesToRadians(to.longitude);\n\n const latitudeDelta = latitude2 - latitude1;\n const longitudeDelta = longitude2 - longitude1;\n\n const latitudeHaversine = Math.sin(latitudeDelta / 2);\n const longitudeHaversine = Math.sin(longitudeDelta / 2);\n\n const a =\n latitudeHaversine * latitudeHaversine +\n longitudeHaversine * longitudeHaversine *\n Math.cos(latitude1) *\n Math.cos(latitude2);\n\n const safeA = Math.min(1, Math.max(0, a));\n const centralAngle = 2 * Math.asin(Math.sqrt(safeA));\n const metres = radius * centralAngle;\n\n return convertDistance(metres, 'm', unit);\n};\n","import type { Coordinate } from './coordinate.js';\nimport { distance } from './distance.js';\nimport type { DistanceOptions } from './distance.js';\n\nexport interface NearestResult<T> {\n point: T;\n distance: number;\n}\n\nexport const nearest = <T extends Coordinate>(\n origin: Coordinate,\n candidates: readonly T[],\n options: DistanceOptions = {},\n): NearestResult<T> | undefined => {\n let closestPoint: T | undefined;\n let closestDistance = Infinity;\n\n for (const candidate of candidates) {\n const candidateDistance = distance(origin, candidate, options);\n\n if (candidateDistance < closestDistance) {\n closestPoint = candidate;\n closestDistance = candidateDistance;\n }\n }\n\n if (closestPoint === undefined) {\n return undefined;\n }\n\n return {\n point: closestPoint,\n distance: closestDistance,\n };\n};\n"],"mappings":";;AAKA,IAAMC,KAAkB,MACpB,OAAOC,KAAU,YAAY,OAAO,SAASA,CAAK,GAEhDC,KACF,MAEA,OAAOD,KAAU,cACjBA,KACA,cAAcA,KACd,eAAeA;AAEnB,SAAgBE,EACZ,GAC2B;CAC3B,IAAI,CAACD,EAAmBD,CAAK,GACzB,MAAU,UAAU,gDAAgD;CAGxE,IAAI,CAACD,EAAeC,EAAM,QAAQ,KAAK,CAACD,EAAeC,EAAM,SAAS,GAClE,MAAU,UAAU,0DAA0D;CAGlF,IAAIA,EAAM,WAAW,OAAOA,EAAM,WAAW,IACzC,MAAU,WAAW,gDAAgD;CAGzE,IAAIA,EAAM,YAAY,QAAQA,EAAM,YAAY,KAC5C,MAAU,WAAW,mDAAmD;AAEhF;AAEA,IAAaG,KAAgB,MAAwC;CACjE,IAAI;EAEA,OADAD,EAAiBF,CAAK,GACf;CACX,QAAQ;EACJ,OAAO;CACX;AACJ,GCzCMI,IAAgD;CAClD,GAAG;CACH,IAAI;CACJ,IAAI;AACR;AAEA,SAAgBC,EACZ,GAC6B;CAC7B,IAAIL,MAAU,OAAOA,MAAU,QAAQA,MAAU,MAC7C,MAAU,UAAU,yCAAyC;AAErE;AAEA,IAAaM,KACT,GACA,GACA,MACS;CACT,IAAI,CAAC,OAAO,SAASN,CAAK,GACtB,MAAU,UAAU,wCAAwC;CAQhE,OALAK,EAAmBE,CAAI,GACvBF,EAAmBG,CAAE,GAENR,IAAQI,EAAgBG,KAEvBH,EAAgBI;AACpC,GC1BaC,IAAsB,WAO7BC,KAAoB,MACtBC,IAAU,KAAK,KAAK,KAElBC,KAAgB,MAAyB;CAC3C,IAAI,CAAC,OAAO,SAASC,CAAM,GACvB,MAAU,UAAU,gCAAgC;CAGxD,IAAIA,KAAU,GACV,MAAU,WAAW,kCAAkC;AAE/D,GAEaC,KACT,GACA,GACA,IAA2B,CAAC,MACnB;CAET,AADAZ,EAAiBK,CAAI,GACrBL,EAAiBM,CAAE;CAEnB,IAAMO,IAAOC,EAAQ,QAAQ,MACvBH,IAASG,EAAQ,UAAA;CAEvB,EAAaH,CAAM;CAEnB,IAAMI,IAAYP,EAAiBH,EAAK,QAAQ,GAC1CW,IAAaR,EAAiBH,EAAK,SAAS,GAC5CY,IAAYT,EAAiBF,EAAG,QAAQ,GACxCY,IAAaV,EAAiBF,EAAG,SAAS,GAE1Ca,IAAgBF,IAAYF,GAC5BK,IAAiBF,IAAaF,GAE9BK,IAAoB,KAAK,IAAIF,IAAgB,CAAC,GAC9CG,IAAqB,KAAK,IAAIF,IAAiB,CAAC,GAEhDG,IACFF,IAAoBA,IACpBC,IAAqBA,IACrB,KAAK,IAAIP,CAAS,IAClB,KAAK,IAAIE,CAAS;CAMtB,OAAOb,EAHc,IAAI,KAAK,KAAK,KAAK,KAD1B,KAAK,IAAI,GAAG,KAAK,IAAI,GAAGmB,CAAC,CACM,CAAK,CAAC,IACpCZ,GAEgB,KAAKE,CAAI;AAC5C,GCnDaW,KACT,GACA,GACA,IAA2B,CAAC,MACG;CAC/B,IAAIC,GACAC,IAAkB;CAEtB,KAAK,IAAMC,KAAaC,GAAY;EAChC,IAAMC,IAAoBjB,EAASkB,GAAQH,GAAWb,CAAO;EAE7D,AAAIe,IAAoBH,MACpB,IAAeC,GACf,IAAkBE;CAE1B;CAEA,IAAIJ,MAAiB,KAAA,GAIrB,OAAO;EACH,OAAOA;EACP,UAAUC;CACd;AACJ"}
1
+ {"version":3,"file":"index.mjs","names":["legacy_default","isFiniteNumber","value","hasCoordinateShape","assertCoordinate","isCoordinate","METRES_PER_UNIT","assertDistanceUnit","convertDistance","from","to","EARTH_MEAN_RADIUS_M","degreesToRadians","degrees","assertRadius","radius","assertDistanceOptions","options","distance","unit","latitude1","longitude1","latitude2","longitude2","latitudeDelta","longitudeDelta","latitudeHaversine","longitudeHaversine","a","nearest","origin","candidates","closestPoint","closestDistance","candidate","candidateDistance"],"sources":["../src/v2/coordinate.ts","../src/v2/units.ts","../src/v2/distance.ts","../src/v2/nearest.ts"],"sourcesContent":["export interface Coordinate {\n latitude: number;\n longitude: number;\n}\n\nconst isFiniteNumber = (value: unknown): value is number =>\n typeof value === 'number' && Number.isFinite(value);\n\nconst hasCoordinateShape = (value: unknown): value is { latitude: unknown; longitude: unknown } =>\n typeof value === 'object' && value !== null && 'latitude' in value && 'longitude' in value;\n\nexport function assertCoordinate(value: unknown): asserts value is Coordinate {\n if (!hasCoordinateShape(value)) {\n throw new TypeError('Coordinate must provide latitude and longitude');\n }\n\n if (!isFiniteNumber(value.latitude) || !isFiniteNumber(value.longitude)) {\n throw new TypeError('Coordinate latitude and longitude must be finite numbers');\n }\n\n if (value.latitude < -90 || value.latitude > 90) {\n throw new RangeError('Coordinate latitude must be between -90 and 90');\n }\n\n if (value.longitude < -180 || value.longitude > 180) {\n throw new RangeError('Coordinate longitude must be between -180 and 180');\n }\n}\n\nexport const isCoordinate = (value: unknown): value is Coordinate => {\n try {\n assertCoordinate(value);\n return true;\n } catch {\n return false;\n }\n};\n","export type DistanceUnit = 'm' | 'km' | 'mi';\n\nconst METRES_PER_UNIT: Record<DistanceUnit, number> = {\n m: 1,\n km: 1000,\n mi: 1609.344,\n};\n\nexport function assertDistanceUnit(value: unknown): asserts value is DistanceUnit {\n if (value !== 'm' && value !== 'km' && value !== 'mi') {\n throw new TypeError('Distance unit must be one of: m, km, mi');\n }\n}\n\nexport const convertDistance = (value: number, from: DistanceUnit, to: DistanceUnit): number => {\n if (!Number.isFinite(value)) {\n throw new TypeError('Distance value must be a finite number');\n }\n\n assertDistanceUnit(from);\n assertDistanceUnit(to);\n\n const metres = value * METRES_PER_UNIT[from];\n\n return metres / METRES_PER_UNIT[to];\n};\n","import { assertCoordinate } from './coordinate.js';\nimport type { Coordinate } from './coordinate.js';\nimport { assertDistanceUnit, convertDistance } from './units.js';\nimport type { DistanceUnit } from './units.js';\n\nexport const EARTH_MEAN_RADIUS_M = 6_371_008.8;\n\nexport interface DistanceOptions {\n unit?: DistanceUnit;\n radius?: number;\n}\n\nconst degreesToRadians = (degrees: number): number => (degrees * Math.PI) / 180;\n\nconst assertRadius = (radius: number): void => {\n if (!Number.isFinite(radius)) {\n throw new TypeError('Radius must be a finite number');\n }\n\n if (radius <= 0) {\n throw new RangeError('Radius must be greater than zero');\n }\n};\n\n// Validate options even when nearest() receives no candidates to measure.\nexport const assertDistanceOptions = (options: DistanceOptions = {}): void => {\n assertRadius(options.radius ?? EARTH_MEAN_RADIUS_M);\n assertDistanceUnit(options.unit ?? 'km');\n};\n\nexport const distance = (\n from: Coordinate,\n to: Coordinate,\n options: DistanceOptions = {},\n): number => {\n assertCoordinate(from);\n assertCoordinate(to);\n\n const unit = options.unit ?? 'km';\n const radius = options.radius ?? EARTH_MEAN_RADIUS_M;\n\n assertRadius(radius);\n\n const latitude1 = degreesToRadians(from.latitude);\n const longitude1 = degreesToRadians(from.longitude);\n const latitude2 = degreesToRadians(to.latitude);\n const longitude2 = degreesToRadians(to.longitude);\n\n const latitudeDelta = latitude2 - latitude1;\n const longitudeDelta = longitude2 - longitude1;\n\n const latitudeHaversine = Math.sin(latitudeDelta / 2);\n const longitudeHaversine = Math.sin(longitudeDelta / 2);\n\n const a =\n latitudeHaversine * latitudeHaversine +\n longitudeHaversine * longitudeHaversine * Math.cos(latitude1) * Math.cos(latitude2);\n\n const safeA = Math.min(1, Math.max(0, a));\n const centralAngle = 2 * Math.asin(Math.sqrt(safeA));\n const metres = radius * centralAngle;\n\n return convertDistance(metres, 'm', unit);\n};\n","import { assertCoordinate } from './coordinate.js';\nimport type { Coordinate } from './coordinate.js';\nimport { assertDistanceOptions, distance } from './distance.js';\nimport type { DistanceOptions } from './distance.js';\n\nexport interface NearestResult<T> {\n point: T;\n distance: number;\n}\n\nexport const nearest = <T extends Coordinate>(\n origin: Coordinate,\n candidates: readonly T[],\n options: DistanceOptions = {},\n): NearestResult<T> | undefined => {\n assertCoordinate(origin);\n\n if (candidates.length === 0) {\n assertDistanceOptions(options);\n return undefined;\n }\n\n let closestPoint: T | undefined;\n let closestDistance = Infinity;\n\n for (const candidate of candidates) {\n const candidateDistance = distance(origin, candidate, options);\n\n if (candidateDistance < closestDistance) {\n closestPoint = candidate;\n closestDistance = candidateDistance;\n }\n }\n\n if (closestPoint === undefined) {\n return undefined;\n }\n\n return {\n point: closestPoint,\n distance: closestDistance,\n };\n};\n"],"mappings":";;AAKA,IAAMC,KAAkB,MACpB,OAAOC,KAAU,YAAY,OAAO,SAASA,CAAK,GAEhDC,KAAsB,MACxB,OAAOD,KAAU,cAAYA,KAAkB,cAAcA,KAAS,eAAeA;AAEzF,SAAgBE,EAAiB,GAA6C;CAC1E,IAAI,CAACD,EAAmBD,CAAK,GACzB,MAAU,UAAU,gDAAgD;CAGxE,IAAI,CAACD,EAAeC,EAAM,QAAQ,KAAK,CAACD,EAAeC,EAAM,SAAS,GAClE,MAAU,UAAU,0DAA0D;CAGlF,IAAIA,EAAM,WAAW,OAAOA,EAAM,WAAW,IACzC,MAAU,WAAW,gDAAgD;CAGzE,IAAIA,EAAM,YAAY,QAAQA,EAAM,YAAY,KAC5C,MAAU,WAAW,mDAAmD;AAEhF;AAEA,IAAaG,KAAgB,MAAwC;CACjE,IAAI;EAEA,OADAD,EAAiBF,CAAK,GACf;CACX,QAAQ;EACJ,OAAO;CACX;AACJ,GClCMI,IAAgD;CAClD,GAAG;CACH,IAAI;CACJ,IAAI;AACR;AAEA,SAAgBC,EAAmB,GAA+C;CAC9E,IAAIL,MAAU,OAAOA,MAAU,QAAQA,MAAU,MAC7C,MAAU,UAAU,yCAAyC;AAErE;AAEA,IAAaM,KAAmB,GAAe,GAAoB,MAA6B;CAC5F,IAAI,CAAC,OAAO,SAASN,CAAK,GACtB,MAAU,UAAU,wCAAwC;CAQhE,OALAK,EAAmBE,CAAI,GACvBF,EAAmBG,CAAE,GAENR,IAAQI,EAAgBG,KAEvBH,EAAgBI;AACpC,GCpBaC,IAAsB,WAO7BC,KAAoB,MAA6BC,IAAU,KAAK,KAAM,KAEtEC,KAAgB,MAAyB;CAC3C,IAAI,CAAC,OAAO,SAASC,CAAM,GACvB,MAAU,UAAU,gCAAgC;CAGxD,IAAIA,KAAU,GACV,MAAU,WAAW,kCAAkC;AAE/D,GAGaC,KAAyB,IAA2B,CAAC,MAAY;CAE1E,AADAF,EAAaG,EAAQ,UAAA,SAA6B,GAClDV,EAAmBU,EAAQ,QAAQ,IAAI;AAC3C,GAEaC,KACT,GACA,GACA,IAA2B,CAAC,MACnB;CAET,AADAd,EAAiBK,CAAI,GACrBL,EAAiBM,CAAE;CAEnB,IAAMS,IAAOF,EAAQ,QAAQ,MACvBF,IAASE,EAAQ,UAAA;CAEvB,EAAaF,CAAM;CAEnB,IAAMK,IAAYR,EAAiBH,EAAK,QAAQ,GAC1CY,IAAaT,EAAiBH,EAAK,SAAS,GAC5Ca,IAAYV,EAAiBF,EAAG,QAAQ,GACxCa,IAAaX,EAAiBF,EAAG,SAAS,GAE1Cc,IAAgBF,IAAYF,GAC5BK,IAAiBF,IAAaF,GAE9BK,IAAoB,KAAK,IAAIF,IAAgB,CAAC,GAC9CG,IAAqB,KAAK,IAAIF,IAAiB,CAAC,GAEhDG,IACFF,IAAoBA,IACpBC,IAAqBA,IAAqB,KAAK,IAAIP,CAAS,IAAI,KAAK,IAAIE,CAAS;CAMtF,OAAOd,EAHc,IAAI,KAAK,KAAK,KAAK,KAD1B,KAAK,IAAI,GAAG,KAAK,IAAI,GAAGoB,CAAC,CACM,CAAK,CAAC,IACpCb,GAEgB,KAAKI,CAAI;AAC5C,GCrDaU,KACT,GACA,GACA,IAA2B,CAAC,MACG;CAG/B,IAFAzB,EAAiB0B,CAAM,GAEnBC,EAAW,WAAW,GAAG;EACzB,EAAsBd,CAAO;EAC7B;CACJ;CAEA,IAAIe,GACAC,IAAkB;CAEtB,KAAK,IAAMC,KAAaH,GAAY;EAChC,IAAMI,IAAoBjB,EAASY,GAAQI,GAAWjB,CAAO;EAE7D,AAAIkB,IAAoBF,MACpB,IAAeC,GACf,IAAkBC;CAE1B;CAEA,IAAIH,MAAiB,KAAA,GAIrB,OAAO;EACH,OAAOA;EACP,UAAUC;CACd;AACJ"}
package/dist/legacy.cjs CHANGED
@@ -1,2 +1,2 @@
1
- Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:`Module`}});var e=new class{_convertMeasurements(e,t=`km`){let n=``;switch(t.toLowerCase()){case`mi`:n=(e*.62137).toFixed(1);break;case`km`:n=e.toFixed(1);break;case`m`:n=(e*1e3).toFixed();break;default:n=e.toFixed(1)}return parseFloat(n)}_haversine(...e){let t=e.map(e=>e/180*Math.PI),n=t[0],r=t[1],i=t[2],a=t[3],o=i-n,s=a-r,c=Math.sin(o/2)*Math.sin(o/2)+Math.sin(s/2)*Math.sin(s/2)*Math.cos(n)*Math.cos(i);return 2*Math.asin(Math.sqrt(Math.min(1,Math.max(0,c))))*6372.8}isGeolocationAvailable(){return new Promise((e,t)=>{`geolocation`in navigator?navigator.geolocation.getCurrentPosition(t=>{e(t)},e=>{switch(e.code){case e.PERMISSION_DENIED:t(Error(`Error: Permission denied`));break;case e.POSITION_UNAVAILABLE:t(Error(`Error: Position unavailable`));break;case e.TIMEOUT:t(Error(`Error: Timeout`))}}):t(Error(`Error: Geolocation disabled in your browser`))})}getDistanceBetween(e,t,n){if(e.hasOwnProperty(`latitude`)&&e.hasOwnProperty(`longitude`)&&t.hasOwnProperty(`latitude`)&&t.hasOwnProperty(`longitude`)){let r=this._haversine(e.latitude,e.longitude,t.latitude,t.longitude);return this._convertMeasurements(r,n)}throw Error(`Error: Position latitude or longitude is not correct`)}getClosestPosition(e,t,n){let r=t.map(t=>this.getDistanceBetween(e,t,n)),i=r.indexOf(Math.min(...r));return{...t[i],haversine:{distance:r[i],measurement:n,accuracy:e.accuracy}}}};exports.default=e;
1
+ Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:`Module`}});var e=new class{_convertMeasurements(e,t=`km`){let n=``;switch(t.toLowerCase()){case`mi`:n=(e*.62137).toFixed(1);break;case`km`:n=e.toFixed(1);break;case`m`:n=(e*1e3).toFixed();break;default:n=e.toFixed(1)}return parseFloat(n)}_haversine(...e){let t=e.map(e=>e/180*Math.PI),n=t[0],r=t[1],i=t[2],a=t[3],o=i-n,s=a-r,c=Math.sin(o/2)*Math.sin(o/2)+Math.sin(s/2)*Math.sin(s/2)*Math.cos(n)*Math.cos(i);return 2*Math.asin(Math.sqrt(Math.min(1,Math.max(0,c))))*6372.8}isGeolocationAvailable(){return new Promise((e,t)=>{`geolocation`in navigator?navigator.geolocation.getCurrentPosition(t=>{e(t)},e=>{switch(e.code){case e.PERMISSION_DENIED:t(Error(`Error: Permission denied`));break;case e.POSITION_UNAVAILABLE:t(Error(`Error: Position unavailable`));break;case e.TIMEOUT:t(Error(`Error: Timeout`))}}):t(Error(`Error: Geolocation disabled in your browser`))})}getDistanceBetween(e,t,n){if(Object.prototype.hasOwnProperty.call(e,`latitude`)&&Object.prototype.hasOwnProperty.call(e,`longitude`)&&Object.prototype.hasOwnProperty.call(t,`latitude`)&&Object.prototype.hasOwnProperty.call(t,`longitude`)){let r=this._haversine(e.latitude,e.longitude,t.latitude,t.longitude);return this._convertMeasurements(r,n)}throw Error(`Error: Position latitude or longitude is not correct`)}getClosestPosition(e,t,n){let r=t.map(t=>this.getDistanceBetween(e,t,n)),i=r.indexOf(Math.min(...r));return{...t[i],haversine:{distance:r[i],measurement:n,accuracy:e.accuracy}}}};exports.default=e;
2
2
  //# sourceMappingURL=legacy.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"legacy.cjs","names":["legacy_default","rawValue","measurement","distance","args","rad","deg","lat1","lon1","lat2","lon2","dLat","dLon","a","resolve","data","error","reject","p1","p2","distances","otherPoints","current","value","indexOfSmallest"],"sources":["../src/legacy.ts"],"sourcesContent":["import type { ILocationPoint } from \"./interfaces/ILocationPoint.js\";\n\nclass HaversineGeolocation {\n _convertMeasurements(distance: number, measurement: string = 'km'): number {\n let rawValue: string = '';\n switch (measurement.toLowerCase()) {\n case 'mi' :\n rawValue = (distance * 0.62137).toFixed(1);\n break;\n case 'km' :\n rawValue = distance.toFixed(1);\n break;\n case 'm' :\n rawValue = (distance * 1000).toFixed();\n break;\n default :\n rawValue = distance.toFixed(1);\n }\n return parseFloat(rawValue);\n }\n\n _haversine(...args: number[]): number {\n const rad: number[] = args.map((deg: number) => deg / 180.0 * Math.PI);\n const lat1: number = rad[0];\n const lon1: number = rad[1];\n const lat2: number = rad[2];\n const lon2: number = rad[3];\n const R: number = 6372.8;\n const dLat: number = lat2 - lat1;\n const dLon: number = lon2 - lon1;\n\n const a: number = Math.sin(dLat / 2) *\n Math.sin(dLat / 2) +\n Math.sin(dLon / 2) *\n Math.sin(dLon / 2) *\n Math.cos(lat1) *\n Math.cos(lat2);\n\n const safeA: number = Math.min(1, Math.max(0, a));\n const c: number = 2 * Math.asin(Math.sqrt(safeA));\n\n return R * c;\n };\n\n isGeolocationAvailable(): Promise<GeolocationPosition> {\n return new Promise((resolve, reject) => {\n if ('geolocation' in navigator) {\n navigator.geolocation.getCurrentPosition((data: GeolocationPosition) => {\n resolve(data);\n }, (error: GeolocationPositionError) => {\n switch (error.code) {\n case error.PERMISSION_DENIED:\n reject(new Error(\"Error: Permission denied\"));\n break;\n case error.POSITION_UNAVAILABLE:\n reject(new Error(\"Error: Position unavailable\"));\n break;\n case error.TIMEOUT:\n reject(new Error(\"Error: Timeout\"));\n break;\n }\n });\n } else {\n reject(new Error(\"Error: Geolocation disabled in your browser\"));\n }\n });\n };\n\n getDistanceBetween(p1: ILocationPoint, p2: ILocationPoint, measurement: string): number {\n if (p1.hasOwnProperty('latitude') && p1.hasOwnProperty('longitude') &&\n p2.hasOwnProperty('latitude') && p2.hasOwnProperty('longitude')) {\n const distance: number = this._haversine(\n p1.latitude,\n p1.longitude,\n p2.latitude,\n p2.longitude\n );\n\n return this._convertMeasurements(distance, measurement)\n\n } else {\n throw new Error(\"Error: Position latitude or longitude is not correct\");\n }\n }\n\n getClosestPosition(\n current: ILocationPoint,\n otherPoints: ILocationPoint[],\n measurement: string,\n ): ILocationPoint & {\n haversine: {\n distance: number;\n measurement: string;\n accuracy: number;\n };\n } {\n const distances: number[] = otherPoints.map((value: any) => this.getDistanceBetween(current, value, measurement));\n const indexOfSmallest: number = distances.indexOf(Math.min(...distances));\n\n return {\n ...otherPoints[indexOfSmallest],\n haversine: {\n distance: distances[indexOfSmallest],\n measurement,\n accuracy: current.accuracy\n },\n };\n };\n}\n\nexport default new HaversineGeolocation();\n"],"mappings":"+FA8GA,IAAAA,EAAe,IAAI,KA5GQ,CACvB,qBAAqB,EAAkB,EAAsB,KAAc,CACvE,IAAIC,EAAmB,GACvB,OAAQC,EAAY,YAAY,EAAhC,CACI,IAAK,KACD,GAAYC,EAAW,OAAA,CAAS,QAAQ,CAAC,EACzC,MACJ,IAAK,KACD,EAAWA,EAAS,QAAQ,CAAC,EAC7B,MACJ,IAAK,IACD,GAAYA,EAAW,IAAA,CAAM,QAAQ,EACrC,MACJ,QACI,EAAWA,EAAS,QAAQ,CAAC,CACrC,CACA,OAAO,WAAWF,CAAQ,CAC9B,CAEA,WAAW,GAAGG,EAAwB,CAClC,IAAMC,EAAgBD,EAAK,IAAK,GAAgBE,EAAM,IAAQ,KAAK,EAAE,EAC/DC,EAAeF,EAAI,GACnBG,EAAeH,EAAI,GACnBI,EAAeJ,EAAI,GACnBK,EAAeL,EAAI,GAEnBM,EAAeF,EAAOF,EACtBK,EAAeF,EAAOF,EAEtBK,EAAY,KAAK,IAAIF,EAAO,CAAC,EAC/B,KAAK,IAAIA,EAAO,CAAC,EACjB,KAAK,IAAIC,EAAO,CAAC,EACjB,KAAK,IAAIA,EAAO,CAAC,EACjB,KAAK,IAAIL,CAAI,EACb,KAAK,IAAIE,CAAI,EAKjB,MAFkB,GAAI,KAAK,KAAK,KAAK,KADf,KAAK,IAAI,EAAG,KAAK,IAAI,EAAGI,CAAC,CACL,CAAK,CAAC,EAEzC,MACX,CAEA,wBAAuD,CACnD,OAAO,IAAI,SAAS,EAAS,IAAW,CAChC,gBAAiB,UACjB,UAAU,YAAY,mBAAoB,GAA8B,CACpEC,EAAQC,CAAI,CAChB,EAAI,GAAoC,CACpC,OAAQC,EAAM,KAAd,CACI,KAAKA,EAAM,kBACPC,EAAW,MAAM,0BAA0B,CAAC,EAC5C,MACJ,KAAKD,EAAM,qBACPC,EAAW,MAAM,6BAA6B,CAAC,EAC/C,MACJ,KAAKD,EAAM,QACPC,EAAW,MAAM,gBAAgB,CAAC,CAE1C,CACJ,CAAC,EAEDA,EAAW,MAAM,6CAA6C,CAAC,CAEvE,CAAC,CACL,CAEA,mBAAmB,EAAoB,EAAoB,EAA6B,CACpF,GAAIC,EAAG,eAAe,UAAU,GAAKA,EAAG,eAAe,WAAW,GAC9DC,EAAG,eAAe,UAAU,GAAKA,EAAG,eAAe,WAAW,EAAG,CACjE,IAAMhB,EAAmB,KAAK,WAC1Be,EAAG,SACHA,EAAG,UACHC,EAAG,SACHA,EAAG,SACP,EAEA,OAAO,KAAK,qBAAqBhB,EAAUD,CAAW,CAE1D,CACI,MAAU,MAAM,sDAAsD,CAE9E,CAEA,mBACI,EACA,EACA,EAOF,CACE,IAAMkB,EAAsBC,EAAY,IAAK,GAAe,KAAK,mBAAmBC,EAASC,EAAOrB,CAAW,CAAC,EAC1GsB,EAA0BJ,EAAU,QAAQ,KAAK,IAAI,GAAGA,CAAS,CAAC,EAExE,MAAO,CACH,GAAGC,EAAYG,GACf,UAAW,CACP,SAAUJ,EAAUI,GACpB,cACA,SAAUF,EAAQ,QACtB,CACJ,CACJ,CACJ"}
1
+ {"version":3,"file":"legacy.cjs","names":["legacy_default","rawValue","measurement","distance","args","rad","deg","lat1","lon1","lat2","lon2","dLat","dLon","a","resolve","data","error","reject","p1","p2","distances","otherPoints","current","value","indexOfSmallest"],"sources":["../src/legacy.ts"],"sourcesContent":["import type { ILocationPoint } from './interfaces/ILocationPoint.js';\n\nclass HaversineGeolocation {\n _convertMeasurements(distance: number, measurement: string = 'km'): number {\n let rawValue: string = '';\n switch (measurement.toLowerCase()) {\n case 'mi':\n rawValue = (distance * 0.62137).toFixed(1);\n break;\n case 'km':\n rawValue = distance.toFixed(1);\n break;\n case 'm':\n rawValue = (distance * 1000).toFixed();\n break;\n default:\n rawValue = distance.toFixed(1);\n }\n return parseFloat(rawValue);\n }\n\n _haversine(...args: number[]): number {\n const rad: number[] = args.map((deg: number) => (deg / 180.0) * Math.PI);\n const lat1: number = rad[0];\n const lon1: number = rad[1];\n const lat2: number = rad[2];\n const lon2: number = rad[3];\n const R: number = 6372.8;\n const dLat: number = lat2 - lat1;\n const dLon: number = lon2 - lon1;\n\n const a: number =\n Math.sin(dLat / 2) * Math.sin(dLat / 2) +\n Math.sin(dLon / 2) * Math.sin(dLon / 2) * Math.cos(lat1) * Math.cos(lat2);\n\n const safeA: number = Math.min(1, Math.max(0, a));\n const c: number = 2 * Math.asin(Math.sqrt(safeA));\n\n return R * c;\n }\n\n isGeolocationAvailable(): Promise<GeolocationPosition> {\n return new Promise((resolve, reject) => {\n if ('geolocation' in navigator) {\n navigator.geolocation.getCurrentPosition(\n (data: GeolocationPosition) => {\n resolve(data);\n },\n (error: GeolocationPositionError) => {\n switch (error.code) {\n case error.PERMISSION_DENIED:\n reject(new Error('Error: Permission denied'));\n break;\n case error.POSITION_UNAVAILABLE:\n reject(new Error('Error: Position unavailable'));\n break;\n case error.TIMEOUT:\n reject(new Error('Error: Timeout'));\n break;\n }\n },\n );\n } else {\n reject(new Error('Error: Geolocation disabled in your browser'));\n }\n });\n }\n\n getDistanceBetween(p1: ILocationPoint, p2: ILocationPoint, measurement: string): number {\n if (\n // biome-ignore lint/suspicious/noPrototypeBuiltins: Preserve ES2020-compatible V1 own-property checks without Object.hasOwn (ES2022).\n Object.prototype.hasOwnProperty.call(p1, 'latitude') &&\n // biome-ignore lint/suspicious/noPrototypeBuiltins: Preserve ES2020-compatible V1 own-property checks without Object.hasOwn (ES2022).\n Object.prototype.hasOwnProperty.call(p1, 'longitude') &&\n // biome-ignore lint/suspicious/noPrototypeBuiltins: Preserve ES2020-compatible V1 own-property checks without Object.hasOwn (ES2022).\n Object.prototype.hasOwnProperty.call(p2, 'latitude') &&\n // biome-ignore lint/suspicious/noPrototypeBuiltins: Preserve ES2020-compatible V1 own-property checks without Object.hasOwn (ES2022).\n Object.prototype.hasOwnProperty.call(p2, 'longitude')\n ) {\n const distance: number = this._haversine(\n p1.latitude,\n p1.longitude,\n p2.latitude,\n p2.longitude,\n );\n\n return this._convertMeasurements(distance, measurement);\n } else {\n throw new Error('Error: Position latitude or longitude is not correct');\n }\n }\n\n getClosestPosition(\n current: ILocationPoint,\n otherPoints: ILocationPoint[],\n measurement: string,\n ): ILocationPoint & {\n haversine: {\n distance: number;\n measurement: string;\n accuracy: number;\n };\n } {\n const distances: number[] = otherPoints.map((value) =>\n this.getDistanceBetween(current, value, measurement),\n );\n const indexOfSmallest: number = distances.indexOf(Math.min(...distances));\n\n return {\n ...otherPoints[indexOfSmallest],\n haversine: {\n distance: distances[indexOfSmallest],\n measurement,\n accuracy: current.accuracy,\n },\n };\n }\n}\n\nexport default new HaversineGeolocation();\n"],"mappings":"+FAuHA,IAAAA,EAAe,IAAI,KArHQ,CACvB,qBAAqB,EAAkB,EAAsB,KAAc,CACvE,IAAIC,EAAmB,GACvB,OAAQC,EAAY,YAAY,EAAhC,CACI,IAAK,KACD,GAAYC,EAAW,OAAA,CAAS,QAAQ,CAAC,EACzC,MACJ,IAAK,KACD,EAAWA,EAAS,QAAQ,CAAC,EAC7B,MACJ,IAAK,IACD,GAAYA,EAAW,IAAA,CAAM,QAAQ,EACrC,MACJ,QACI,EAAWA,EAAS,QAAQ,CAAC,CACrC,CACA,OAAO,WAAWF,CAAQ,CAC9B,CAEA,WAAW,GAAGG,EAAwB,CAClC,IAAMC,EAAgBD,EAAK,IAAK,GAAiBE,EAAM,IAAS,KAAK,EAAE,EACjEC,EAAeF,EAAI,GACnBG,EAAeH,EAAI,GACnBI,EAAeJ,EAAI,GACnBK,EAAeL,EAAI,GAEnBM,EAAeF,EAAOF,EACtBK,EAAeF,EAAOF,EAEtBK,EACF,KAAK,IAAIF,EAAO,CAAC,EAAI,KAAK,IAAIA,EAAO,CAAC,EACtC,KAAK,IAAIC,EAAO,CAAC,EAAI,KAAK,IAAIA,EAAO,CAAC,EAAI,KAAK,IAAIL,CAAI,EAAI,KAAK,IAAIE,CAAI,EAK5E,MAFkB,GAAI,KAAK,KAAK,KAAK,KADf,KAAK,IAAI,EAAG,KAAK,IAAI,EAAGI,CAAC,CACL,CAAK,CAAC,EAEzC,MACX,CAEA,wBAAuD,CACnD,OAAO,IAAI,SAAS,EAAS,IAAW,CAChC,gBAAiB,UACjB,UAAU,YAAY,mBACjB,GAA8B,CAC3BC,EAAQC,CAAI,CAChB,EACC,GAAoC,CACjC,OAAQC,EAAM,KAAd,CACI,KAAKA,EAAM,kBACPC,EAAW,MAAM,0BAA0B,CAAC,EAC5C,MACJ,KAAKD,EAAM,qBACPC,EAAW,MAAM,6BAA6B,CAAC,EAC/C,MACJ,KAAKD,EAAM,QACPC,EAAW,MAAM,gBAAgB,CAAC,CAE1C,CACJ,CACJ,EAEAA,EAAW,MAAM,6CAA6C,CAAC,CAEvE,CAAC,CACL,CAEA,mBAAmB,EAAoB,EAAoB,EAA6B,CACpF,GAEI,OAAO,UAAU,eAAe,KAAKC,EAAI,UAAU,GAEnD,OAAO,UAAU,eAAe,KAAKA,EAAI,WAAW,GAEpD,OAAO,UAAU,eAAe,KAAKC,EAAI,UAAU,GAEnD,OAAO,UAAU,eAAe,KAAKA,EAAI,WAAW,EACtD,CACE,IAAMhB,EAAmB,KAAK,WAC1Be,EAAG,SACHA,EAAG,UACHC,EAAG,SACHA,EAAG,SACP,EAEA,OAAO,KAAK,qBAAqBhB,EAAUD,CAAW,CAC1D,CACI,MAAU,MAAM,sDAAsD,CAE9E,CAEA,mBACI,EACA,EACA,EAOF,CACE,IAAMkB,EAAsBC,EAAY,IAAK,GACzC,KAAK,mBAAmBC,EAASC,EAAOrB,CAAW,CACvD,EACMsB,EAA0BJ,EAAU,QAAQ,KAAK,IAAI,GAAGA,CAAS,CAAC,EAExE,MAAO,CACH,GAAGC,EAAYG,GACf,UAAW,CACP,SAAUJ,EAAUI,GACpB,cACA,SAAUF,EAAQ,QACtB,CACJ,CACJ,CACJ"}
package/dist/legacy.mjs CHANGED
@@ -37,7 +37,7 @@ var e = new class {
37
37
  });
38
38
  }
39
39
  getDistanceBetween(e, t, n) {
40
- if (e.hasOwnProperty("latitude") && e.hasOwnProperty("longitude") && t.hasOwnProperty("latitude") && t.hasOwnProperty("longitude")) {
40
+ if (Object.prototype.hasOwnProperty.call(e, "latitude") && Object.prototype.hasOwnProperty.call(e, "longitude") && Object.prototype.hasOwnProperty.call(t, "latitude") && Object.prototype.hasOwnProperty.call(t, "longitude")) {
41
41
  let r = this._haversine(e.latitude, e.longitude, t.latitude, t.longitude);
42
42
  return this._convertMeasurements(r, n);
43
43
  }
@@ -1 +1 @@
1
- {"version":3,"file":"legacy.mjs","names":["legacy_default","rawValue","measurement","distance","args","rad","deg","lat1","lon1","lat2","lon2","dLat","dLon","a","data","error","reject","p1","p2","distances","otherPoints","current","value","indexOfSmallest"],"sources":["../src/legacy.ts"],"sourcesContent":["import type { ILocationPoint } from \"./interfaces/ILocationPoint.js\";\n\nclass HaversineGeolocation {\n _convertMeasurements(distance: number, measurement: string = 'km'): number {\n let rawValue: string = '';\n switch (measurement.toLowerCase()) {\n case 'mi' :\n rawValue = (distance * 0.62137).toFixed(1);\n break;\n case 'km' :\n rawValue = distance.toFixed(1);\n break;\n case 'm' :\n rawValue = (distance * 1000).toFixed();\n break;\n default :\n rawValue = distance.toFixed(1);\n }\n return parseFloat(rawValue);\n }\n\n _haversine(...args: number[]): number {\n const rad: number[] = args.map((deg: number) => deg / 180.0 * Math.PI);\n const lat1: number = rad[0];\n const lon1: number = rad[1];\n const lat2: number = rad[2];\n const lon2: number = rad[3];\n const R: number = 6372.8;\n const dLat: number = lat2 - lat1;\n const dLon: number = lon2 - lon1;\n\n const a: number = Math.sin(dLat / 2) *\n Math.sin(dLat / 2) +\n Math.sin(dLon / 2) *\n Math.sin(dLon / 2) *\n Math.cos(lat1) *\n Math.cos(lat2);\n\n const safeA: number = Math.min(1, Math.max(0, a));\n const c: number = 2 * Math.asin(Math.sqrt(safeA));\n\n return R * c;\n };\n\n isGeolocationAvailable(): Promise<GeolocationPosition> {\n return new Promise((resolve, reject) => {\n if ('geolocation' in navigator) {\n navigator.geolocation.getCurrentPosition((data: GeolocationPosition) => {\n resolve(data);\n }, (error: GeolocationPositionError) => {\n switch (error.code) {\n case error.PERMISSION_DENIED:\n reject(new Error(\"Error: Permission denied\"));\n break;\n case error.POSITION_UNAVAILABLE:\n reject(new Error(\"Error: Position unavailable\"));\n break;\n case error.TIMEOUT:\n reject(new Error(\"Error: Timeout\"));\n break;\n }\n });\n } else {\n reject(new Error(\"Error: Geolocation disabled in your browser\"));\n }\n });\n };\n\n getDistanceBetween(p1: ILocationPoint, p2: ILocationPoint, measurement: string): number {\n if (p1.hasOwnProperty('latitude') && p1.hasOwnProperty('longitude') &&\n p2.hasOwnProperty('latitude') && p2.hasOwnProperty('longitude')) {\n const distance: number = this._haversine(\n p1.latitude,\n p1.longitude,\n p2.latitude,\n p2.longitude\n );\n\n return this._convertMeasurements(distance, measurement)\n\n } else {\n throw new Error(\"Error: Position latitude or longitude is not correct\");\n }\n }\n\n getClosestPosition(\n current: ILocationPoint,\n otherPoints: ILocationPoint[],\n measurement: string,\n ): ILocationPoint & {\n haversine: {\n distance: number;\n measurement: string;\n accuracy: number;\n };\n } {\n const distances: number[] = otherPoints.map((value: any) => this.getDistanceBetween(current, value, measurement));\n const indexOfSmallest: number = distances.indexOf(Math.min(...distances));\n\n return {\n ...otherPoints[indexOfSmallest],\n haversine: {\n distance: distances[indexOfSmallest],\n measurement,\n accuracy: current.accuracy\n },\n };\n };\n}\n\nexport default new HaversineGeolocation();\n"],"mappings":"AA8GA,IAAAA,IAAe,IAAI,MA5GQ;CACvB,qBAAqB,GAAkB,IAAsB,MAAc;EACvE,IAAIC,IAAmB;EACvB,QAAQC,EAAY,YAAY,GAAhC;GACI,KAAK;IACD,KAAYC,IAAW,OAAA,CAAS,QAAQ,CAAC;IACzC;GACJ,KAAK;IACD,IAAWA,EAAS,QAAQ,CAAC;IAC7B;GACJ,KAAK;IACD,KAAYA,IAAW,IAAA,CAAM,QAAQ;IACrC;GACJ,SACI,IAAWA,EAAS,QAAQ,CAAC;EACrC;EACA,OAAO,WAAWF,CAAQ;CAC9B;CAEA,WAAW,GAAGG,GAAwB;EAClC,IAAMC,IAAgBD,EAAK,KAAK,MAAgBE,IAAM,MAAQ,KAAK,EAAE,GAC/DC,IAAeF,EAAI,IACnBG,IAAeH,EAAI,IACnBI,IAAeJ,EAAI,IACnBK,IAAeL,EAAI,IAEnBM,IAAeF,IAAOF,GACtBK,IAAeF,IAAOF,GAEtBK,IAAY,KAAK,IAAIF,IAAO,CAAC,IAC/B,KAAK,IAAIA,IAAO,CAAC,IACjB,KAAK,IAAIC,IAAO,CAAC,IACjB,KAAK,IAAIA,IAAO,CAAC,IACjB,KAAK,IAAIL,CAAI,IACb,KAAK,IAAIE,CAAI;EAKjB,OAFkB,IAAI,KAAK,KAAK,KAAK,KADf,KAAK,IAAI,GAAG,KAAK,IAAI,GAAGI,CAAC,CACL,CAAK,CAAC,IAEzC;CACX;CAEA,yBAAuD;EACnD,OAAO,IAAI,SAAS,GAAS,MAAW;GACpC,AAAI,iBAAiB,YACjB,UAAU,YAAY,oBAAoB,MAA8B;IACpE,EAAQC,CAAI;GAChB,IAAI,MAAoC;IACpC,QAAQC,EAAM,MAAd;KACI,KAAKA,EAAM;MACP,EAAO,gBAAI,MAAM,0BAA0B,CAAC;MAC5C;KACJ,KAAKA,EAAM;MACP,EAAO,gBAAI,MAAM,6BAA6B,CAAC;MAC/C;KACJ,KAAKA,EAAM,SACP,EAAO,gBAAI,MAAM,gBAAgB,CAAC;IAE1C;GACJ,CAAC,IAEDC,EAAO,gBAAI,MAAM,6CAA6C,CAAC;EAEvE,CAAC;CACL;CAEA,mBAAmB,GAAoB,GAAoB,GAA6B;EACpF,IAAIC,EAAG,eAAe,UAAU,KAAKA,EAAG,eAAe,WAAW,KAC9DC,EAAG,eAAe,UAAU,KAAKA,EAAG,eAAe,WAAW,GAAG;GACjE,IAAMf,IAAmB,KAAK,WAC1Bc,EAAG,UACHA,EAAG,WACHC,EAAG,UACHA,EAAG,SACP;GAEA,OAAO,KAAK,qBAAqBf,GAAUD,CAAW;EAE1D;EACI,MAAU,MAAM,sDAAsD;CAE9E;CAEA,mBACI,GACA,GACA,GAOF;EACE,IAAMiB,IAAsBC,EAAY,KAAK,MAAe,KAAK,mBAAmBC,GAASC,GAAOpB,CAAW,CAAC,GAC1GqB,IAA0BJ,EAAU,QAAQ,KAAK,IAAI,GAAGA,CAAS,CAAC;EAExE,OAAO;GACH,GAAGC,EAAYG;GACf,WAAW;IACP,UAAUJ,EAAUI;IACpB;IACA,UAAUF,EAAQ;GACtB;EACJ;CACJ;AACJ,EAEwC"}
1
+ {"version":3,"file":"legacy.mjs","names":["legacy_default","rawValue","measurement","distance","args","rad","deg","lat1","lon1","lat2","lon2","dLat","dLon","a","data","error","reject","p1","p2","distances","otherPoints","current","value","indexOfSmallest"],"sources":["../src/legacy.ts"],"sourcesContent":["import type { ILocationPoint } from './interfaces/ILocationPoint.js';\n\nclass HaversineGeolocation {\n _convertMeasurements(distance: number, measurement: string = 'km'): number {\n let rawValue: string = '';\n switch (measurement.toLowerCase()) {\n case 'mi':\n rawValue = (distance * 0.62137).toFixed(1);\n break;\n case 'km':\n rawValue = distance.toFixed(1);\n break;\n case 'm':\n rawValue = (distance * 1000).toFixed();\n break;\n default:\n rawValue = distance.toFixed(1);\n }\n return parseFloat(rawValue);\n }\n\n _haversine(...args: number[]): number {\n const rad: number[] = args.map((deg: number) => (deg / 180.0) * Math.PI);\n const lat1: number = rad[0];\n const lon1: number = rad[1];\n const lat2: number = rad[2];\n const lon2: number = rad[3];\n const R: number = 6372.8;\n const dLat: number = lat2 - lat1;\n const dLon: number = lon2 - lon1;\n\n const a: number =\n Math.sin(dLat / 2) * Math.sin(dLat / 2) +\n Math.sin(dLon / 2) * Math.sin(dLon / 2) * Math.cos(lat1) * Math.cos(lat2);\n\n const safeA: number = Math.min(1, Math.max(0, a));\n const c: number = 2 * Math.asin(Math.sqrt(safeA));\n\n return R * c;\n }\n\n isGeolocationAvailable(): Promise<GeolocationPosition> {\n return new Promise((resolve, reject) => {\n if ('geolocation' in navigator) {\n navigator.geolocation.getCurrentPosition(\n (data: GeolocationPosition) => {\n resolve(data);\n },\n (error: GeolocationPositionError) => {\n switch (error.code) {\n case error.PERMISSION_DENIED:\n reject(new Error('Error: Permission denied'));\n break;\n case error.POSITION_UNAVAILABLE:\n reject(new Error('Error: Position unavailable'));\n break;\n case error.TIMEOUT:\n reject(new Error('Error: Timeout'));\n break;\n }\n },\n );\n } else {\n reject(new Error('Error: Geolocation disabled in your browser'));\n }\n });\n }\n\n getDistanceBetween(p1: ILocationPoint, p2: ILocationPoint, measurement: string): number {\n if (\n // biome-ignore lint/suspicious/noPrototypeBuiltins: Preserve ES2020-compatible V1 own-property checks without Object.hasOwn (ES2022).\n Object.prototype.hasOwnProperty.call(p1, 'latitude') &&\n // biome-ignore lint/suspicious/noPrototypeBuiltins: Preserve ES2020-compatible V1 own-property checks without Object.hasOwn (ES2022).\n Object.prototype.hasOwnProperty.call(p1, 'longitude') &&\n // biome-ignore lint/suspicious/noPrototypeBuiltins: Preserve ES2020-compatible V1 own-property checks without Object.hasOwn (ES2022).\n Object.prototype.hasOwnProperty.call(p2, 'latitude') &&\n // biome-ignore lint/suspicious/noPrototypeBuiltins: Preserve ES2020-compatible V1 own-property checks without Object.hasOwn (ES2022).\n Object.prototype.hasOwnProperty.call(p2, 'longitude')\n ) {\n const distance: number = this._haversine(\n p1.latitude,\n p1.longitude,\n p2.latitude,\n p2.longitude,\n );\n\n return this._convertMeasurements(distance, measurement);\n } else {\n throw new Error('Error: Position latitude or longitude is not correct');\n }\n }\n\n getClosestPosition(\n current: ILocationPoint,\n otherPoints: ILocationPoint[],\n measurement: string,\n ): ILocationPoint & {\n haversine: {\n distance: number;\n measurement: string;\n accuracy: number;\n };\n } {\n const distances: number[] = otherPoints.map((value) =>\n this.getDistanceBetween(current, value, measurement),\n );\n const indexOfSmallest: number = distances.indexOf(Math.min(...distances));\n\n return {\n ...otherPoints[indexOfSmallest],\n haversine: {\n distance: distances[indexOfSmallest],\n measurement,\n accuracy: current.accuracy,\n },\n };\n }\n}\n\nexport default new HaversineGeolocation();\n"],"mappings":"AAuHA,IAAAA,IAAe,IAAI,MArHQ;CACvB,qBAAqB,GAAkB,IAAsB,MAAc;EACvE,IAAIC,IAAmB;EACvB,QAAQC,EAAY,YAAY,GAAhC;GACI,KAAK;IACD,KAAYC,IAAW,OAAA,CAAS,QAAQ,CAAC;IACzC;GACJ,KAAK;IACD,IAAWA,EAAS,QAAQ,CAAC;IAC7B;GACJ,KAAK;IACD,KAAYA,IAAW,IAAA,CAAM,QAAQ;IACrC;GACJ,SACI,IAAWA,EAAS,QAAQ,CAAC;EACrC;EACA,OAAO,WAAWF,CAAQ;CAC9B;CAEA,WAAW,GAAGG,GAAwB;EAClC,IAAMC,IAAgBD,EAAK,KAAK,MAAiBE,IAAM,MAAS,KAAK,EAAE,GACjEC,IAAeF,EAAI,IACnBG,IAAeH,EAAI,IACnBI,IAAeJ,EAAI,IACnBK,IAAeL,EAAI,IAEnBM,IAAeF,IAAOF,GACtBK,IAAeF,IAAOF,GAEtBK,IACF,KAAK,IAAIF,IAAO,CAAC,IAAI,KAAK,IAAIA,IAAO,CAAC,IACtC,KAAK,IAAIC,IAAO,CAAC,IAAI,KAAK,IAAIA,IAAO,CAAC,IAAI,KAAK,IAAIL,CAAI,IAAI,KAAK,IAAIE,CAAI;EAK5E,OAFkB,IAAI,KAAK,KAAK,KAAK,KADf,KAAK,IAAI,GAAG,KAAK,IAAI,GAAGI,CAAC,CACL,CAAK,CAAC,IAEzC;CACX;CAEA,yBAAuD;EACnD,OAAO,IAAI,SAAS,GAAS,MAAW;GACpC,AAAI,iBAAiB,YACjB,UAAU,YAAY,oBACjB,MAA8B;IAC3B,EAAQC,CAAI;GAChB,IACC,MAAoC;IACjC,QAAQC,EAAM,MAAd;KACI,KAAKA,EAAM;MACP,EAAO,gBAAI,MAAM,0BAA0B,CAAC;MAC5C;KACJ,KAAKA,EAAM;MACP,EAAO,gBAAI,MAAM,6BAA6B,CAAC;MAC/C;KACJ,KAAKA,EAAM,SACP,EAAO,gBAAI,MAAM,gBAAgB,CAAC;IAE1C;GACJ,CACJ,IAEAC,EAAO,gBAAI,MAAM,6CAA6C,CAAC;EAEvE,CAAC;CACL;CAEA,mBAAmB,GAAoB,GAAoB,GAA6B;EACpF,IAEI,OAAO,UAAU,eAAe,KAAKC,GAAI,UAAU,KAEnD,OAAO,UAAU,eAAe,KAAKA,GAAI,WAAW,KAEpD,OAAO,UAAU,eAAe,KAAKC,GAAI,UAAU,KAEnD,OAAO,UAAU,eAAe,KAAKA,GAAI,WAAW,GACtD;GACE,IAAMf,IAAmB,KAAK,WAC1Bc,EAAG,UACHA,EAAG,WACHC,EAAG,UACHA,EAAG,SACP;GAEA,OAAO,KAAK,qBAAqBf,GAAUD,CAAW;EAC1D;EACI,MAAU,MAAM,sDAAsD;CAE9E;CAEA,mBACI,GACA,GACA,GAOF;EACE,IAAMiB,IAAsBC,EAAY,KAAK,MACzC,KAAK,mBAAmBC,GAASC,GAAOpB,CAAW,CACvD,GACMqB,IAA0BJ,EAAU,QAAQ,KAAK,IAAI,GAAGA,CAAS,CAAC;EAExE,OAAO;GACH,GAAGC,EAAYG;GACf,WAAW;IACP,UAAUJ,EAAUI;IACpB;IACA,UAAUF,EAAQ;GACtB;EACJ;CACJ;AACJ,EAEwC"}
@@ -1,4 +1,4 @@
1
- import type { ILocationPoint } from "./interfaces/ILocationPoint.js";
1
+ import type { ILocationPoint } from './interfaces/ILocationPoint.js';
2
2
  declare class HaversineGeolocation {
3
3
  _convertMeasurements(distance: number, measurement?: string): number;
4
4
  _haversine(...args: number[]): number;
@@ -1 +1 @@
1
- export declare const getHaversineEntity: (HaversineGeolocation: any) => any;
1
+ export declare const getHaversineEntity: <T>(HaversineGeolocation: new () => T) => T | Record<string, never>;
@@ -4,4 +4,4 @@ import { getHaversineEntity } from './getHaversineEntity';
4
4
  import { isNodeJs } from './isNodeJs';
5
5
  import { showError } from './showError';
6
6
  import { showGeolocationError } from './showGeolocationError';
7
- export { calculateHaversine, convertMeasurement, getHaversineEntity, isNodeJs, showError, showGeolocationError };
7
+ export { calculateHaversine, convertMeasurement, getHaversineEntity, isNodeJs, showError, showGeolocationError, };
@@ -1,2 +1,2 @@
1
1
  export declare const isGeolocationSupported: () => boolean;
2
- export declare const getCurrentPosition: (options?: PositionOptions | undefined) => Promise<GeolocationPosition>;
2
+ export declare const getCurrentPosition: (options?: PositionOptions) => Promise<GeolocationPosition>;
@@ -5,4 +5,5 @@ export interface DistanceOptions {
5
5
  unit?: DistanceUnit;
6
6
  radius?: number;
7
7
  }
8
+ export declare const assertDistanceOptions: (options?: DistanceOptions) => void;
8
9
  export declare const distance: (from: Coordinate, to: Coordinate, options?: DistanceOptions) => number;
@@ -1,8 +1,8 @@
1
1
  export { assertCoordinate, isCoordinate, } from './coordinate.js';
2
- export type { Coordinate, } from './coordinate.js';
2
+ export type { Coordinate } from './coordinate.js';
3
3
  export { assertDistanceUnit, convertDistance, } from './units.js';
4
- export type { DistanceUnit, } from './units.js';
4
+ export type { DistanceUnit } from './units.js';
5
5
  export { distance, EARTH_MEAN_RADIUS_M, } from './distance.js';
6
- export type { DistanceOptions, } from './distance.js';
7
- export { nearest, } from './nearest.js';
8
- export type { NearestResult, } from './nearest.js';
6
+ export type { DistanceOptions } from './distance.js';
7
+ export { nearest } from './nearest.js';
8
+ export type { NearestResult } from './nearest.js';
@@ -1,3 +1,3 @@
1
- export declare type DistanceUnit = 'm' | 'km' | 'mi';
1
+ export type DistanceUnit = 'm' | 'km' | 'mi';
2
2
  export declare function assertDistanceUnit(value: unknown): asserts value is DistanceUnit;
3
3
  export declare const convertDistance: (value: number, from: DistanceUnit, to: DistanceUnit) => number;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "haversine-geolocation",
3
- "version": "2.0.0-alpha.1",
3
+ "version": "2.0.0-beta.1",
4
4
  "description": "Get distances between two points or get closest position to current point. Based on the Haversine Formula",
5
5
  "main": "dist/index.cjs",
6
6
  "scripts": {
@@ -11,7 +11,10 @@
11
11
  "typecheck": "tsc --noEmit",
12
12
  "build:types": "tsc -p tsconfig.types.json",
13
13
  "build:umd": "vite build --config vite.umd.config.ts",
14
- "build:runtime": "vite build --config vite.lib.config.ts"
14
+ "build:runtime": "vite build --config vite.lib.config.ts",
15
+ "size:check": "node scripts/check-package-size.mjs",
16
+ "quality": "biome check src spec scripts vite.lib.config.ts vite.umd.config.ts vitest.config.ts",
17
+ "quality:fix": "biome check --write src spec scripts vite.lib.config.ts vite.umd.config.ts vitest.config.ts"
15
18
  },
16
19
  "keywords": [
17
20
  "geolocation",
@@ -24,13 +27,14 @@
24
27
  "author": "Daniil Sydorenko <daniildeveloper@gmail.com>",
25
28
  "repository": {
26
29
  "type": "git",
27
- "url": "https://github.com/DaniilSydorenko/haversine-geolocation.git"
30
+ "url": "git+https://github.com/DaniilSydorenko/haversine-geolocation.git"
28
31
  },
29
32
  "license": "MIT",
30
33
  "devDependencies": {
31
- "typescript": "^4.4.4",
34
+ "typescript": "7.0.2",
32
35
  "vite": "8.3.4",
33
- "vitest": "5.0.3"
36
+ "vitest": "5.0.3",
37
+ "@biomejs/biome": "2.5.15"
34
38
  },
35
39
  "files": [
36
40
  "dist"