@hebcal/geo-sqlite 4.5.1 → 4.7.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.
Files changed (3) hide show
  1. package/dist/index.js +133 -70
  2. package/dist/index.mjs +133 -70
  3. package/package.json +6 -6
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- /*! @hebcal/geo-sqlite v4.5.1 */
1
+ /*! @hebcal/geo-sqlite v4.7.0 */
2
2
  'use strict';
3
3
 
4
4
  Object.defineProperty(exports, '__esModule', { value: true });
@@ -65,7 +65,7 @@ FROM ZIPCodes_CityFullText5
65
65
  WHERE ZIPCodes_CityFullText5 MATCH ?
66
66
  ORDER BY Population DESC
67
67
  LIMIT 20`;
68
- const GEONAME_COMPLETE_SQL = `SELECT geonameid
68
+ const GEONAME_COMPLETE_SQL = `SELECT geonameid, longname, city, admin1, country
69
69
  FROM geoname_fulltext
70
70
  WHERE geoname_fulltext MATCH ?
71
71
  ORDER BY population DESC
@@ -318,6 +318,7 @@ class GeoDb {
318
318
  admin1: res.State,
319
319
  asciiname: res.CityMixedCase,
320
320
  country: 'United States',
321
+ cc: 'US',
321
322
  latitude: res.Latitude,
322
323
  longitude: res.Longitude,
323
324
  timezone: core.Location.getUsaTzid(res.State, res.TimeZone, res.DayLightSaving),
@@ -371,36 +372,7 @@ class GeoDb {
371
372
 
372
373
  const geoMatches = geoRows.map(res => {
373
374
  const loc = this.lookupGeoname(res.geonameid);
374
- const country = this.countryNames.get(loc.getCountryCode()) || '';
375
- const admin1 = loc.admin1 || '';
376
- const obj = {
377
- id: res.geonameid,
378
- value: loc.name,
379
- admin1,
380
- country,
381
- latitude: loc.latitude,
382
- longitude: loc.longitude,
383
- timezone: loc.getTzid(),
384
- geo: 'geoname'
385
- };
386
-
387
- if (loc.population) {
388
- obj.population = loc.population;
389
- }
390
-
391
- if (loc.asciiname) {
392
- obj.asciiname = loc.asciiname;
393
- }
394
-
395
- if (country) {
396
- obj.country = country;
397
- }
398
-
399
- if (admin1) {
400
- obj.admin1 = admin1;
401
- }
402
-
403
- return obj;
375
+ return this.geonameLocToAutocomplete(loc, res);
404
376
  });
405
377
 
406
378
  if (!this.zipFulltextCompStmt) {
@@ -409,41 +381,12 @@ class GeoDb {
409
381
 
410
382
  const zipRows = this.zipFulltextCompStmt.all(`{longname} : "${qraw}" *`);
411
383
  const zipMatches = zipRows.map(res => {
412
- const zipCode = res.ZipCode;
413
- const loc = this.lookupZip(zipCode);
414
- const obj = {
415
- id: zipCode,
416
- value: loc.getName(),
417
- admin1: loc.admin1,
418
- asciiname: loc.getShortName(),
419
- country: 'United States',
420
- latitude: loc.latitude,
421
- longitude: loc.longitude,
422
- timezone: loc.getTzid(),
423
- population: loc.population,
424
- geo: 'zip'
425
- };
426
- return obj;
384
+ const loc = this.lookupZip(res.ZipCode);
385
+ return GeoDb.zipLocToAutocomplete(loc);
427
386
  });
428
- const map = new Map();
429
-
430
- for (const obj of zipMatches) {
431
- const key = [obj.asciiname, stateNames[obj.admin1], obj.country].join('|');
432
-
433
- if (!map.has(key)) {
434
- map.set(key, obj);
435
- }
436
- } // GeoNames takes priority over USA ZIP code matches
437
-
438
-
439
- for (const obj of geoMatches) {
440
- const key = [obj.asciiname, obj.admin1, obj.country].join('|');
441
- map.set(key, obj);
442
- }
443
-
444
- const values = Array.from(map.values());
387
+ const values = this.mergeZipGeo(zipMatches, geoMatches);
445
388
  values.sort((a, b) => b.population - a.population);
446
- const topN = values.slice(0, 15);
389
+ const topN = values.slice(0, 12);
447
390
 
448
391
  if (!latlong) {
449
392
  for (const val of topN) {
@@ -457,6 +400,110 @@ class GeoDb {
457
400
  return topN;
458
401
  }
459
402
  }
403
+ /**
404
+ * @private
405
+ * @param {Location} loc
406
+ * @param {any} res
407
+ * @return {any}
408
+ */
409
+
410
+
411
+ geonameLocToAutocomplete(loc, res) {
412
+ const cc = loc.getCountryCode();
413
+ const country = res.country || this.countryNames.get(cc) || '';
414
+ const admin1 = res.admin || loc.admin1 || '';
415
+ const obj = {
416
+ id: res.geonameid,
417
+ value: res.longname,
418
+ admin1,
419
+ country,
420
+ cc,
421
+ latitude: loc.latitude,
422
+ longitude: loc.longitude,
423
+ timezone: loc.getTzid(),
424
+ geo: 'geoname'
425
+ };
426
+
427
+ if (loc.population) {
428
+ obj.population = loc.population;
429
+ }
430
+
431
+ if (res.city !== loc.asciiname) {
432
+ obj.name = res.city;
433
+ }
434
+
435
+ if (loc.asciiname) {
436
+ obj.asciiname = loc.asciiname;
437
+ }
438
+
439
+ if (country) {
440
+ obj.country = country;
441
+ }
442
+
443
+ if (admin1) {
444
+ obj.admin1 = admin1;
445
+ }
446
+
447
+ return obj;
448
+ }
449
+ /**
450
+ * @private
451
+ * @param {Location} loc
452
+ * @return {any}
453
+ */
454
+
455
+
456
+ static zipLocToAutocomplete(loc) {
457
+ return {
458
+ id: loc.zip,
459
+ value: loc.getName(),
460
+ admin1: loc.admin1,
461
+ asciiname: loc.getShortName(),
462
+ country: 'United States',
463
+ cc: 'US',
464
+ latitude: loc.latitude,
465
+ longitude: loc.longitude,
466
+ timezone: loc.getTzid(),
467
+ population: loc.population,
468
+ geo: 'zip'
469
+ };
470
+ }
471
+ /**
472
+ * GeoNames matches takes priority over USA ZIP code matches
473
+ * @private
474
+ * @param {any[]} zipMatches
475
+ * @param {any[]} geoMatches
476
+ * @return {any[]}
477
+ */
478
+
479
+
480
+ mergeZipGeo(zipMatches, geoMatches) {
481
+ const zlen = zipMatches.length;
482
+ const glen = geoMatches.length;
483
+
484
+ if (zlen && !glen) {
485
+ return zipMatches;
486
+ } else if (glen && !zlen) {
487
+ return geoMatches;
488
+ }
489
+
490
+ const map = new Map();
491
+
492
+ for (const obj of zipMatches) {
493
+ const key = [obj.asciiname, stateNames[obj.admin1], obj.cc].join('|');
494
+
495
+ if (!map.has(key)) {
496
+ map.set(key, obj);
497
+ }
498
+ }
499
+
500
+ for (const obj of geoMatches) {
501
+ const key = [obj.asciiname, obj.admin1, obj.cc].join('|');
502
+ map.set(key, obj);
503
+ }
504
+
505
+ return Array.from(map.values());
506
+ }
460
507
  /** Reads entire ZIP database and caches in-memory */
461
508
 
462
509
 
@@ -644,17 +691,34 @@ async function buildGeonamesSqlite(opts) {
644
691
  FROM geoname g, admin1 a, country c
645
692
  WHERE g.country = c.ISO
646
693
  AND g.country <> 'US'
694
+ AND g.country <> 'IL'
695
+ AND g.country <> 'GB'
647
696
  AND g.country||'.'||g.admin1 = a.key
648
697
  `, `INSERT INTO geoname_fulltext
649
698
  SELECT g.geonameid,
650
699
  g.asciiname||', '||a.asciiname||', USA',
651
700
  g.population,
652
- g.asciiname,a.asciiname,'USA'
701
+ g.asciiname,a.asciiname,'United States'
653
702
  FROM geoname g, admin1 a
654
703
  WHERE g.country = 'US'
655
704
  AND g.country||'.'||g.admin1 = a.key
656
705
  `, `INSERT INTO geoname_fulltext
657
706
  SELECT g.geonameid,
707
+ g.asciiname||', '||a.asciiname||', UK',
708
+ g.population,
709
+ g.asciiname,a.asciiname,'UK'
710
+ FROM geoname g, admin1 a
711
+ WHERE g.country = 'GB'
712
+ AND g.country||'.'||g.admin1 = a.key
713
+ `, `INSERT INTO geoname_fulltext
714
+ SELECT g.geonameid,
715
+ g.asciiname||', Israel',
716
+ g.population,
717
+ g.asciiname,NULL,'Israel'
718
+ FROM geoname g
719
+ WHERE g.country = 'IL'
720
+ `, `INSERT INTO geoname_fulltext
721
+ SELECT g.geonameid,
658
722
  g.asciiname||', '||c.Country,
659
723
  g.population,
660
724
  g.asciiname,NULL,c.Country
@@ -681,14 +745,13 @@ async function buildGeonamesSqlite(opts) {
681
745
  AND g.geonameid = alt.geonameid
682
746
  `, `INSERT INTO geoname_fulltext
683
747
  SELECT g.geonameid,
684
- alt.name||', '||a1.asciiname||', Israel',
748
+ alt.name||', Israel',
685
749
  g.population,
686
- alt.name,a1.asciiname,'Israel'
687
- FROM geoname g, admin1 a1, altnames alt
750
+ alt.name,NULL,'Israel'
751
+ FROM geoname g, altnames alt
688
752
  WHERE g.country = 'IL'
689
753
  AND alt.isolanguage = 'en'
690
754
  AND g.geonameid = alt.geonameid
691
- AND g.country||'.'||g.admin1 = a1.key
692
755
  `, 'VACUUM');
693
756
  db.close();
694
757
  return Promise.resolve(true);
package/dist/index.mjs CHANGED
@@ -1,4 +1,4 @@
1
- /*! @hebcal/geo-sqlite v4.5.1 */
1
+ /*! @hebcal/geo-sqlite v4.7.0 */
2
2
  import Database from 'better-sqlite3';
3
3
  import { Location, Locale } from '@hebcal/core';
4
4
  import '@hebcal/cities';
@@ -53,7 +53,7 @@ FROM ZIPCodes_CityFullText5
53
53
  WHERE ZIPCodes_CityFullText5 MATCH ?
54
54
  ORDER BY Population DESC
55
55
  LIMIT 20`;
56
- const GEONAME_COMPLETE_SQL = `SELECT geonameid
56
+ const GEONAME_COMPLETE_SQL = `SELECT geonameid, longname, city, admin1, country
57
57
  FROM geoname_fulltext
58
58
  WHERE geoname_fulltext MATCH ?
59
59
  ORDER BY population DESC
@@ -306,6 +306,7 @@ class GeoDb {
306
306
  admin1: res.State,
307
307
  asciiname: res.CityMixedCase,
308
308
  country: 'United States',
309
+ cc: 'US',
309
310
  latitude: res.Latitude,
310
311
  longitude: res.Longitude,
311
312
  timezone: Location.getUsaTzid(res.State, res.TimeZone, res.DayLightSaving),
@@ -359,36 +360,7 @@ class GeoDb {
359
360
 
360
361
  const geoMatches = geoRows.map(res => {
361
362
  const loc = this.lookupGeoname(res.geonameid);
362
- const country = this.countryNames.get(loc.getCountryCode()) || '';
363
- const admin1 = loc.admin1 || '';
364
- const obj = {
365
- id: res.geonameid,
366
- value: loc.name,
367
- admin1,
368
- country,
369
- latitude: loc.latitude,
370
- longitude: loc.longitude,
371
- timezone: loc.getTzid(),
372
- geo: 'geoname'
373
- };
374
-
375
- if (loc.population) {
376
- obj.population = loc.population;
377
- }
378
-
379
- if (loc.asciiname) {
380
- obj.asciiname = loc.asciiname;
381
- }
382
-
383
- if (country) {
384
- obj.country = country;
385
- }
386
-
387
- if (admin1) {
388
- obj.admin1 = admin1;
389
- }
390
-
391
- return obj;
363
+ return this.geonameLocToAutocomplete(loc, res);
392
364
  });
393
365
 
394
366
  if (!this.zipFulltextCompStmt) {
@@ -397,41 +369,12 @@ class GeoDb {
397
369
 
398
370
  const zipRows = this.zipFulltextCompStmt.all(`{longname} : "${qraw}" *`);
399
371
  const zipMatches = zipRows.map(res => {
400
- const zipCode = res.ZipCode;
401
- const loc = this.lookupZip(zipCode);
402
- const obj = {
403
- id: zipCode,
404
- value: loc.getName(),
405
- admin1: loc.admin1,
406
- asciiname: loc.getShortName(),
407
- country: 'United States',
408
- latitude: loc.latitude,
409
- longitude: loc.longitude,
410
- timezone: loc.getTzid(),
411
- population: loc.population,
412
- geo: 'zip'
413
- };
414
- return obj;
372
+ const loc = this.lookupZip(res.ZipCode);
373
+ return GeoDb.zipLocToAutocomplete(loc);
415
374
  });
416
- const map = new Map();
417
-
418
- for (const obj of zipMatches) {
419
- const key = [obj.asciiname, stateNames[obj.admin1], obj.country].join('|');
420
-
421
- if (!map.has(key)) {
422
- map.set(key, obj);
423
- }
424
- } // GeoNames takes priority over USA ZIP code matches
425
-
426
-
427
- for (const obj of geoMatches) {
428
- const key = [obj.asciiname, obj.admin1, obj.country].join('|');
429
- map.set(key, obj);
430
- }
431
-
432
- const values = Array.from(map.values());
375
+ const values = this.mergeZipGeo(zipMatches, geoMatches);
433
376
  values.sort((a, b) => b.population - a.population);
434
- const topN = values.slice(0, 15);
377
+ const topN = values.slice(0, 12);
435
378
 
436
379
  if (!latlong) {
437
380
  for (const val of topN) {
@@ -445,6 +388,110 @@ class GeoDb {
445
388
  return topN;
446
389
  }
447
390
  }
391
+ /**
392
+ * @private
393
+ * @param {Location} loc
394
+ * @param {any} res
395
+ * @return {any}
396
+ */
397
+
398
+
399
+ geonameLocToAutocomplete(loc, res) {
400
+ const cc = loc.getCountryCode();
401
+ const country = res.country || this.countryNames.get(cc) || '';
402
+ const admin1 = res.admin || loc.admin1 || '';
403
+ const obj = {
404
+ id: res.geonameid,
405
+ value: res.longname,
406
+ admin1,
407
+ country,
408
+ cc,
409
+ latitude: loc.latitude,
410
+ longitude: loc.longitude,
411
+ timezone: loc.getTzid(),
412
+ geo: 'geoname'
413
+ };
414
+
415
+ if (loc.population) {
416
+ obj.population = loc.population;
417
+ }
418
+
419
+ if (res.city !== loc.asciiname) {
420
+ obj.name = res.city;
421
+ }
422
+
423
+ if (loc.asciiname) {
424
+ obj.asciiname = loc.asciiname;
425
+ }
426
+
427
+ if (country) {
428
+ obj.country = country;
429
+ }
430
+
431
+ if (admin1) {
432
+ obj.admin1 = admin1;
433
+ }
434
+
435
+ return obj;
436
+ }
437
+ /**
438
+ * @private
439
+ * @param {Location} loc
440
+ * @return {any}
441
+ */
442
+
443
+
444
+ static zipLocToAutocomplete(loc) {
445
+ return {
446
+ id: loc.zip,
447
+ value: loc.getName(),
448
+ admin1: loc.admin1,
449
+ asciiname: loc.getShortName(),
450
+ country: 'United States',
451
+ cc: 'US',
452
+ latitude: loc.latitude,
453
+ longitude: loc.longitude,
454
+ timezone: loc.getTzid(),
455
+ population: loc.population,
456
+ geo: 'zip'
457
+ };
458
+ }
459
+ /**
460
+ * GeoNames matches takes priority over USA ZIP code matches
461
+ * @private
462
+ * @param {any[]} zipMatches
463
+ * @param {any[]} geoMatches
464
+ * @return {any[]}
465
+ */
466
+
467
+
468
+ mergeZipGeo(zipMatches, geoMatches) {
469
+ const zlen = zipMatches.length;
470
+ const glen = geoMatches.length;
471
+
472
+ if (zlen && !glen) {
473
+ return zipMatches;
474
+ } else if (glen && !zlen) {
475
+ return geoMatches;
476
+ }
477
+
478
+ const map = new Map();
479
+
480
+ for (const obj of zipMatches) {
481
+ const key = [obj.asciiname, stateNames[obj.admin1], obj.cc].join('|');
482
+
483
+ if (!map.has(key)) {
484
+ map.set(key, obj);
485
+ }
486
+ }
487
+
488
+ for (const obj of geoMatches) {
489
+ const key = [obj.asciiname, obj.admin1, obj.cc].join('|');
490
+ map.set(key, obj);
491
+ }
492
+
493
+ return Array.from(map.values());
494
+ }
448
495
  /** Reads entire ZIP database and caches in-memory */
449
496
 
450
497
 
@@ -632,17 +679,34 @@ async function buildGeonamesSqlite(opts) {
632
679
  FROM geoname g, admin1 a, country c
633
680
  WHERE g.country = c.ISO
634
681
  AND g.country <> 'US'
682
+ AND g.country <> 'IL'
683
+ AND g.country <> 'GB'
635
684
  AND g.country||'.'||g.admin1 = a.key
636
685
  `, `INSERT INTO geoname_fulltext
637
686
  SELECT g.geonameid,
638
687
  g.asciiname||', '||a.asciiname||', USA',
639
688
  g.population,
640
- g.asciiname,a.asciiname,'USA'
689
+ g.asciiname,a.asciiname,'United States'
641
690
  FROM geoname g, admin1 a
642
691
  WHERE g.country = 'US'
643
692
  AND g.country||'.'||g.admin1 = a.key
644
693
  `, `INSERT INTO geoname_fulltext
645
694
  SELECT g.geonameid,
695
+ g.asciiname||', '||a.asciiname||', UK',
696
+ g.population,
697
+ g.asciiname,a.asciiname,'UK'
698
+ FROM geoname g, admin1 a
699
+ WHERE g.country = 'GB'
700
+ AND g.country||'.'||g.admin1 = a.key
701
+ `, `INSERT INTO geoname_fulltext
702
+ SELECT g.geonameid,
703
+ g.asciiname||', Israel',
704
+ g.population,
705
+ g.asciiname,NULL,'Israel'
706
+ FROM geoname g
707
+ WHERE g.country = 'IL'
708
+ `, `INSERT INTO geoname_fulltext
709
+ SELECT g.geonameid,
646
710
  g.asciiname||', '||c.Country,
647
711
  g.population,
648
712
  g.asciiname,NULL,c.Country
@@ -669,14 +733,13 @@ async function buildGeonamesSqlite(opts) {
669
733
  AND g.geonameid = alt.geonameid
670
734
  `, `INSERT INTO geoname_fulltext
671
735
  SELECT g.geonameid,
672
- alt.name||', '||a1.asciiname||', Israel',
736
+ alt.name||', Israel',
673
737
  g.population,
674
- alt.name,a1.asciiname,'Israel'
675
- FROM geoname g, admin1 a1, altnames alt
738
+ alt.name,NULL,'Israel'
739
+ FROM geoname g, altnames alt
676
740
  WHERE g.country = 'IL'
677
741
  AND alt.isolanguage = 'en'
678
742
  AND g.geonameid = alt.geonameid
679
- AND g.country||'.'||g.admin1 = a1.key
680
743
  `, 'VACUUM');
681
744
  db.close();
682
745
  return Promise.resolve(true);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hebcal/geo-sqlite",
3
- "version": "4.5.1",
3
+ "version": "4.7.0",
4
4
  "author": "Michael J. Radwin (https://github.com/mjradwin)",
5
5
  "keywords": [
6
6
  "hebcal"
@@ -31,8 +31,8 @@
31
31
  "@hebcal/cities": "^3.1.2",
32
32
  "@hebcal/core": "^3.38.0",
33
33
  "better-sqlite3": "^7.5.3",
34
- "pino": "^7.11.0",
35
- "pino-pretty": "^7.6.1"
34
+ "pino": "^8.0.0",
35
+ "pino-pretty": "^8.0.0"
36
36
  },
37
37
  "scripts": {
38
38
  "build": "rollup -c",
@@ -60,11 +60,11 @@
60
60
  "@rollup/plugin-commonjs": "^22.0.0",
61
61
  "@rollup/plugin-json": "^4.1.0",
62
62
  "@rollup/plugin-node-resolve": "^13.3.0",
63
- "ava": "^4.2.0",
64
- "eslint": "^8.16.0",
63
+ "ava": "^4.3.0",
64
+ "eslint": "^8.17.0",
65
65
  "eslint-config-google": "^0.14.0",
66
66
  "jsdoc": "^3.6.10",
67
67
  "jsdoc-to-markdown": "^7.1.1",
68
- "rollup": "^2.75.4"
68
+ "rollup": "^2.75.5"
69
69
  }
70
70
  }