geocodio-library-node 1.10.0 → 1.13.0
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 +409 -1
- package/lib/__tests__/distance.test.js +365 -0
- package/lib/__tests__/geocodioLibraryNode.test.js +4 -4
- package/lib/index.d.ts +238 -11
- package/lib/index.js +493 -11
- package/package.json +3 -1
package/README.md
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
# geocod.io Node library [![NPM version][npm-image]][npm-url]
|
|
2
|
-
> Library for performing forward and reverse address geocoding for addresses or coordinates in the US and Canada.
|
|
2
|
+
> Library for performing forward and reverse address geocoding for addresses or coordinates in the US and Canada, with support for distance calculations.
|
|
3
3
|
|
|
4
4
|
<!-- toc -->
|
|
5
5
|
|
|
@@ -10,6 +10,10 @@
|
|
|
10
10
|
* [Field appends](#field-appends)
|
|
11
11
|
* [Address components](#address-components)
|
|
12
12
|
* [Limit results](#limit-results)
|
|
13
|
+
* [Distance calculation](#distance-calculation)
|
|
14
|
+
* [Distance matrix](#distance-matrix)
|
|
15
|
+
* [Async distance jobs](#async-distance-jobs)
|
|
16
|
+
* [Geocoding with distance](#geocoding-with-distance)
|
|
13
17
|
* [Lists](#lists)
|
|
14
18
|
* [Create A List](#create-a-list)
|
|
15
19
|
* [Get List Status](#get-list-status)
|
|
@@ -231,6 +235,410 @@ geocoder.reverse('38.9002898,-76.9990361', ['timezone'], 5)
|
|
|
231
235
|
.catch(err => { ... });
|
|
232
236
|
```
|
|
233
237
|
|
|
238
|
+
### Distance calculations
|
|
239
|
+
|
|
240
|
+
Calculate distances from a single origin to multiple destinations, or compute full distance matrices.
|
|
241
|
+
|
|
242
|
+
#### Coordinate format with custom IDs
|
|
243
|
+
|
|
244
|
+
You can add custom identifiers to coordinates using the `lat,lng,id` format. The ID will be returned in the response, making it easy to match results back to your data:
|
|
245
|
+
|
|
246
|
+
```javascript
|
|
247
|
+
// String format with ID
|
|
248
|
+
'37.7749,-122.4194,warehouse_1'
|
|
249
|
+
|
|
250
|
+
// Array format with ID
|
|
251
|
+
[37.7749, -122.4194, 'warehouse_1']
|
|
252
|
+
|
|
253
|
+
// Object format with ID
|
|
254
|
+
{ lat: 37.7749, lng: -122.4194, id: 'warehouse_1' }
|
|
255
|
+
|
|
256
|
+
// Using the Coordinate class
|
|
257
|
+
new Coordinate(37.7749, -122.4194, 'warehouse_1')
|
|
258
|
+
|
|
259
|
+
// The ID is returned in the response:
|
|
260
|
+
/*
|
|
261
|
+
{
|
|
262
|
+
"query": "37.7749,-122.4194,warehouse_1",
|
|
263
|
+
"location": [37.7749, -122.4194],
|
|
264
|
+
"id": "warehouse_1",
|
|
265
|
+
"distance_miles": 3.2,
|
|
266
|
+
"distance_km": 5.1
|
|
267
|
+
}
|
|
268
|
+
*/
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
#### Distance mode and units
|
|
272
|
+
|
|
273
|
+
The SDK provides enums for type-safe distance configuration:
|
|
274
|
+
|
|
275
|
+
```javascript
|
|
276
|
+
const {
|
|
277
|
+
Geocodio,
|
|
278
|
+
Coordinate,
|
|
279
|
+
DistanceMode,
|
|
280
|
+
DistanceUnits,
|
|
281
|
+
DistanceOrderBy,
|
|
282
|
+
DistanceSortOrder
|
|
283
|
+
} = require('geocodio-library-node');
|
|
284
|
+
|
|
285
|
+
// Available modes
|
|
286
|
+
DistanceMode.Straightline // Default - great-circle (as the crow flies)
|
|
287
|
+
DistanceMode.Driving // Road network routing with duration
|
|
288
|
+
DistanceMode.Haversine // Alias for Straightline
|
|
289
|
+
|
|
290
|
+
// Available units
|
|
291
|
+
DistanceUnits.Miles // Default
|
|
292
|
+
DistanceUnits.Kilometers // or DistanceUnits.Km
|
|
293
|
+
|
|
294
|
+
// Sorting options
|
|
295
|
+
DistanceOrderBy.Distance // Default
|
|
296
|
+
DistanceOrderBy.Duration
|
|
297
|
+
|
|
298
|
+
DistanceSortOrder.Asc // Default
|
|
299
|
+
DistanceSortOrder.Desc
|
|
300
|
+
```
|
|
301
|
+
|
|
302
|
+
> **Note:** The default mode is `straightline` (great-circle distance). Use `DistanceMode.Driving` if you need road network routing with duration estimates.
|
|
303
|
+
|
|
304
|
+
#### Add distance to geocoding requests
|
|
305
|
+
|
|
306
|
+
You can add distance calculations to existing geocode or reverse geocode requests. Each geocoded result will include a `destinations` array with distances to each destination.
|
|
307
|
+
|
|
308
|
+
```javascript
|
|
309
|
+
const geocoder = new Geocodio('YOUR_API_KEY');
|
|
310
|
+
|
|
311
|
+
// Geocode an address and calculate distances to store locations
|
|
312
|
+
geocoder.geocode(
|
|
313
|
+
'1600 Pennsylvania Ave NW, Washington DC',
|
|
314
|
+
[], // fields
|
|
315
|
+
null, // limit
|
|
316
|
+
{ // distance options
|
|
317
|
+
destinations: [
|
|
318
|
+
'38.9072,-77.0369,store_dc',
|
|
319
|
+
'39.2904,-76.6122,store_baltimore',
|
|
320
|
+
'39.9526,-75.1652,store_philly'
|
|
321
|
+
],
|
|
322
|
+
distanceMode: DistanceMode.Driving,
|
|
323
|
+
distanceUnits: DistanceUnits.Miles
|
|
324
|
+
}
|
|
325
|
+
)
|
|
326
|
+
.then(response => {
|
|
327
|
+
console.log(response.results[0].destinations);
|
|
328
|
+
/*
|
|
329
|
+
[
|
|
330
|
+
{
|
|
331
|
+
"query": "38.9072,-77.0369,store_dc",
|
|
332
|
+
"location": [38.9072, -77.0369],
|
|
333
|
+
"id": "store_dc",
|
|
334
|
+
"distance_miles": 0.8,
|
|
335
|
+
"distance_km": 1.3,
|
|
336
|
+
"duration_seconds": 180
|
|
337
|
+
},
|
|
338
|
+
...
|
|
339
|
+
]
|
|
340
|
+
*/
|
|
341
|
+
});
|
|
342
|
+
|
|
343
|
+
// Reverse geocode with distances
|
|
344
|
+
geocoder.reverse(
|
|
345
|
+
'38.8977,-77.0365',
|
|
346
|
+
[],
|
|
347
|
+
null,
|
|
348
|
+
{
|
|
349
|
+
destinations: ['38.9072,-77.0369,capitol', '38.8895,-77.0353,monument'],
|
|
350
|
+
distanceMode: DistanceMode.Straightline
|
|
351
|
+
}
|
|
352
|
+
)
|
|
353
|
+
.then(response => { ... });
|
|
354
|
+
|
|
355
|
+
// With filtering - find nearest 3 stores within 50 miles
|
|
356
|
+
geocoder.geocode(
|
|
357
|
+
'1600 Pennsylvania Ave NW, Washington DC',
|
|
358
|
+
[],
|
|
359
|
+
null,
|
|
360
|
+
{
|
|
361
|
+
destinations: [
|
|
362
|
+
'38.9072,-77.0369,store_1',
|
|
363
|
+
'39.2904,-76.6122,store_2',
|
|
364
|
+
'39.9526,-75.1652,store_3',
|
|
365
|
+
'40.7128,-74.0060,store_4'
|
|
366
|
+
],
|
|
367
|
+
distanceMode: DistanceMode.Driving,
|
|
368
|
+
distanceMaxResults: 3,
|
|
369
|
+
distanceMaxDistance: 50.0,
|
|
370
|
+
distanceOrderBy: DistanceOrderBy.Distance,
|
|
371
|
+
distanceSortOrder: DistanceSortOrder.Asc
|
|
372
|
+
}
|
|
373
|
+
)
|
|
374
|
+
.then(response => { ... });
|
|
375
|
+
```
|
|
376
|
+
|
|
377
|
+
#### Single origin to multiple destinations
|
|
378
|
+
|
|
379
|
+
```javascript
|
|
380
|
+
const geocoder = new Geocodio('YOUR_API_KEY');
|
|
381
|
+
|
|
382
|
+
// Calculate distances from one origin to multiple destinations
|
|
383
|
+
geocoder.distance(
|
|
384
|
+
'37.7749,-122.4194,headquarters', // Origin with ID
|
|
385
|
+
[
|
|
386
|
+
'37.7849,-122.4094,customer_a',
|
|
387
|
+
'37.7949,-122.3994,customer_b',
|
|
388
|
+
'37.8049,-122.4294,customer_c'
|
|
389
|
+
]
|
|
390
|
+
)
|
|
391
|
+
.then(response => {
|
|
392
|
+
console.log(response);
|
|
393
|
+
/*
|
|
394
|
+
{
|
|
395
|
+
"origin": {
|
|
396
|
+
"query": "37.7749,-122.4194,headquarters",
|
|
397
|
+
"location": [37.7749, -122.4194],
|
|
398
|
+
"id": "headquarters"
|
|
399
|
+
},
|
|
400
|
+
"destinations": [
|
|
401
|
+
{
|
|
402
|
+
"query": "37.7849,-122.4094,customer_a",
|
|
403
|
+
"location": [37.7849, -122.4094],
|
|
404
|
+
"id": "customer_a",
|
|
405
|
+
"distance_miles": 0.9,
|
|
406
|
+
"distance_km": 1.4
|
|
407
|
+
},
|
|
408
|
+
...
|
|
409
|
+
]
|
|
410
|
+
}
|
|
411
|
+
*/
|
|
412
|
+
});
|
|
413
|
+
|
|
414
|
+
// Use driving mode for road network routing (includes duration)
|
|
415
|
+
geocoder.distance(
|
|
416
|
+
'37.7749,-122.4194',
|
|
417
|
+
['37.7849,-122.4094'],
|
|
418
|
+
{ mode: DistanceMode.Driving }
|
|
419
|
+
)
|
|
420
|
+
.then(response => {
|
|
421
|
+
console.log(response.destinations[0].duration_seconds); // e.g., 180
|
|
422
|
+
});
|
|
423
|
+
|
|
424
|
+
// With all filtering and sorting options
|
|
425
|
+
geocoder.distance(
|
|
426
|
+
'37.7749,-122.4194,warehouse',
|
|
427
|
+
[
|
|
428
|
+
'37.7849,-122.4094,store_1',
|
|
429
|
+
'37.7949,-122.3994,store_2',
|
|
430
|
+
'37.8049,-122.4294,store_3'
|
|
431
|
+
],
|
|
432
|
+
{
|
|
433
|
+
mode: DistanceMode.Driving,
|
|
434
|
+
units: DistanceUnits.Kilometers,
|
|
435
|
+
maxResults: 2,
|
|
436
|
+
maxDistance: 10.0,
|
|
437
|
+
orderBy: DistanceOrderBy.Distance,
|
|
438
|
+
sortOrder: DistanceSortOrder.Asc
|
|
439
|
+
}
|
|
440
|
+
)
|
|
441
|
+
.then(response => { ... });
|
|
442
|
+
|
|
443
|
+
// Using Coordinate class
|
|
444
|
+
const origin = new Coordinate(37.7749, -122.4194, 'warehouse');
|
|
445
|
+
const destinations = [
|
|
446
|
+
new Coordinate(37.7849, -122.4094, 'store_1'),
|
|
447
|
+
new Coordinate(37.7949, -122.3994, 'store_2')
|
|
448
|
+
];
|
|
449
|
+
|
|
450
|
+
geocoder.distance(origin, destinations)
|
|
451
|
+
.then(response => { ... });
|
|
452
|
+
|
|
453
|
+
// Array format for coordinates (with or without ID)
|
|
454
|
+
geocoder.distance(
|
|
455
|
+
[37.7749, -122.4194], // Without ID
|
|
456
|
+
[[37.7849, -122.4094, 'dest_1']] // With ID as third element
|
|
457
|
+
)
|
|
458
|
+
.then(response => { ... });
|
|
459
|
+
```
|
|
460
|
+
|
|
461
|
+
#### Distance matrix (multiple origins × destinations)
|
|
462
|
+
|
|
463
|
+
```javascript
|
|
464
|
+
// Calculate full distance matrix with custom IDs
|
|
465
|
+
geocoder.distanceMatrix(
|
|
466
|
+
[
|
|
467
|
+
'37.7749,-122.4194,warehouse_sf',
|
|
468
|
+
'37.8049,-122.4294,warehouse_oak'
|
|
469
|
+
],
|
|
470
|
+
[
|
|
471
|
+
'37.7849,-122.4094,customer_1',
|
|
472
|
+
'37.7949,-122.3994,customer_2'
|
|
473
|
+
]
|
|
474
|
+
)
|
|
475
|
+
.then(response => {
|
|
476
|
+
console.log(response);
|
|
477
|
+
/*
|
|
478
|
+
{
|
|
479
|
+
"mode": "driving",
|
|
480
|
+
"results": [
|
|
481
|
+
{
|
|
482
|
+
"origin": {
|
|
483
|
+
"query": "37.7749,-122.4194,warehouse_sf",
|
|
484
|
+
"location": [37.7749, -122.4194],
|
|
485
|
+
"id": "warehouse_sf"
|
|
486
|
+
},
|
|
487
|
+
"destinations": [
|
|
488
|
+
{
|
|
489
|
+
"query": "37.7849,-122.4094,customer_1",
|
|
490
|
+
"location": [37.7849, -122.4094],
|
|
491
|
+
"id": "customer_1",
|
|
492
|
+
"distance_miles": 0.9,
|
|
493
|
+
"distance_km": 1.4
|
|
494
|
+
},
|
|
495
|
+
...
|
|
496
|
+
]
|
|
497
|
+
},
|
|
498
|
+
{
|
|
499
|
+
"origin": { ..., "id": "warehouse_oak" },
|
|
500
|
+
"destinations": [...]
|
|
501
|
+
}
|
|
502
|
+
]
|
|
503
|
+
}
|
|
504
|
+
*/
|
|
505
|
+
});
|
|
506
|
+
|
|
507
|
+
// With driving mode and kilometers
|
|
508
|
+
geocoder.distanceMatrix(
|
|
509
|
+
['37.7749,-122.4194'],
|
|
510
|
+
['37.7849,-122.4094'],
|
|
511
|
+
{ mode: DistanceMode.Driving, units: DistanceUnits.Kilometers }
|
|
512
|
+
)
|
|
513
|
+
.then(response => { ... });
|
|
514
|
+
|
|
515
|
+
// Using object format
|
|
516
|
+
const origins = [
|
|
517
|
+
{ lat: 37.7749, lng: -122.4194, id: 'warehouse_sf' },
|
|
518
|
+
{ lat: 37.8049, lng: -122.4294, id: 'warehouse_oak' }
|
|
519
|
+
];
|
|
520
|
+
|
|
521
|
+
const destinations = [
|
|
522
|
+
{ lat: 37.7849, lng: -122.4094, id: 'customer_1' },
|
|
523
|
+
{ lat: 37.7949, lng: -122.3994, id: 'customer_2' }
|
|
524
|
+
];
|
|
525
|
+
|
|
526
|
+
geocoder.distanceMatrix(origins, destinations)
|
|
527
|
+
.then(response => { ... });
|
|
528
|
+
```
|
|
529
|
+
|
|
530
|
+
#### Nearest mode (find closest destinations)
|
|
531
|
+
|
|
532
|
+
```javascript
|
|
533
|
+
// Find up to 2 nearest destinations from each origin
|
|
534
|
+
geocoder.distanceMatrix(
|
|
535
|
+
['37.7749,-122.4194'],
|
|
536
|
+
['37.7849,-122.4094', '37.7949,-122.3994', '37.8049,-122.4294'],
|
|
537
|
+
{ maxResults: 2 }
|
|
538
|
+
)
|
|
539
|
+
.then(response => { ... });
|
|
540
|
+
|
|
541
|
+
// Filter by maximum distance (in miles or km depending on units)
|
|
542
|
+
geocoder.distanceMatrix(
|
|
543
|
+
['37.7749,-122.4194'],
|
|
544
|
+
[...destinations],
|
|
545
|
+
{ maxDistance: 2.0 }
|
|
546
|
+
)
|
|
547
|
+
.then(response => { ... });
|
|
548
|
+
|
|
549
|
+
// Filter by minimum and maximum distance
|
|
550
|
+
geocoder.distanceMatrix(
|
|
551
|
+
['37.7749,-122.4194'],
|
|
552
|
+
[...destinations],
|
|
553
|
+
{ minDistance: 1.0, maxDistance: 10.0 }
|
|
554
|
+
)
|
|
555
|
+
.then(response => { ... });
|
|
556
|
+
|
|
557
|
+
// Filter by duration (seconds, driving mode only)
|
|
558
|
+
geocoder.distanceMatrix(
|
|
559
|
+
['37.7749,-122.4194'],
|
|
560
|
+
[...destinations],
|
|
561
|
+
{
|
|
562
|
+
mode: DistanceMode.Driving,
|
|
563
|
+
maxDuration: 300, // 5 minutes
|
|
564
|
+
minDuration: 60 // 1 minute minimum
|
|
565
|
+
}
|
|
566
|
+
)
|
|
567
|
+
.then(response => { ... });
|
|
568
|
+
|
|
569
|
+
// Sort by duration descending
|
|
570
|
+
geocoder.distanceMatrix(
|
|
571
|
+
['37.7749,-122.4194'],
|
|
572
|
+
[...destinations],
|
|
573
|
+
{
|
|
574
|
+
mode: DistanceMode.Driving,
|
|
575
|
+
maxResults: 5,
|
|
576
|
+
orderBy: DistanceOrderBy.Duration,
|
|
577
|
+
sortOrder: DistanceSortOrder.Desc
|
|
578
|
+
}
|
|
579
|
+
)
|
|
580
|
+
.then(response => { ... });
|
|
581
|
+
```
|
|
582
|
+
|
|
583
|
+
#### Async distance matrix jobs
|
|
584
|
+
|
|
585
|
+
For large distance matrix calculations, use async jobs that process in the background.
|
|
586
|
+
|
|
587
|
+
```javascript
|
|
588
|
+
// Create a new distance matrix job
|
|
589
|
+
geocoder.createDistanceMatrixJob(
|
|
590
|
+
'My Distance Calculation',
|
|
591
|
+
['37.7749,-122.4194', '37.8049,-122.4294'],
|
|
592
|
+
['37.7849,-122.4094', '37.7949,-122.3994'],
|
|
593
|
+
{
|
|
594
|
+
mode: DistanceMode.Driving,
|
|
595
|
+
units: DistanceUnits.Miles,
|
|
596
|
+
callbackUrl: 'https://example.com/webhook' // Optional
|
|
597
|
+
}
|
|
598
|
+
)
|
|
599
|
+
.then(response => {
|
|
600
|
+
console.log(response);
|
|
601
|
+
// { id: 123, status: 'ENQUEUED', total_calculations: 4 }
|
|
602
|
+
});
|
|
603
|
+
|
|
604
|
+
// Or use list IDs from previously uploaded lists
|
|
605
|
+
geocoder.createDistanceMatrixJob(
|
|
606
|
+
'Distance from List',
|
|
607
|
+
12345, // Origins list ID
|
|
608
|
+
67890, // Destinations list ID
|
|
609
|
+
{ mode: DistanceMode.Straightline }
|
|
610
|
+
)
|
|
611
|
+
.then(response => { ... });
|
|
612
|
+
|
|
613
|
+
// Check job status
|
|
614
|
+
geocoder.distanceMatrixJobStatus(123)
|
|
615
|
+
.then(response => {
|
|
616
|
+
console.log(response.data.status); // 'ENQUEUED', 'PROCESSING', 'COMPLETED', or 'FAILED'
|
|
617
|
+
console.log(response.data.progress); // 0-100
|
|
618
|
+
});
|
|
619
|
+
|
|
620
|
+
// List all jobs (paginated)
|
|
621
|
+
geocoder.distanceMatrixJobs()
|
|
622
|
+
.then(response => { ... });
|
|
623
|
+
|
|
624
|
+
geocoder.distanceMatrixJobs(2) // Page 2
|
|
625
|
+
.then(response => { ... });
|
|
626
|
+
|
|
627
|
+
// Get results when complete (same format as distanceMatrix response)
|
|
628
|
+
geocoder.getDistanceMatrixJobResults(123)
|
|
629
|
+
.then(response => {
|
|
630
|
+
console.log(response.results);
|
|
631
|
+
});
|
|
632
|
+
|
|
633
|
+
// Or download to a file for very large results
|
|
634
|
+
geocoder.downloadDistanceMatrixJob(123, 'results.json')
|
|
635
|
+
.then(() => console.log('Downloaded!'));
|
|
636
|
+
|
|
637
|
+
// Delete a job
|
|
638
|
+
geocoder.deleteDistanceMatrixJob(123)
|
|
639
|
+
.then(() => console.log('Deleted!'));
|
|
640
|
+
```
|
|
641
|
+
|
|
234
642
|
### Lists
|
|
235
643
|
|
|
236
644
|
List methods are nested within `.list`. To access list methods, be sure to to run `geocoder.list` and then include the task method you would like to utilize.
|