@hebcal/geo-sqlite 4.5.2 → 4.7.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.
Files changed (3) hide show
  1. package/dist/index.js +137 -73
  2. package/dist/index.mjs +137 -73
  3. package/package.json +6 -6
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- /*! @hebcal/geo-sqlite v4.5.2 */
1
+ /*! @hebcal/geo-sqlite v4.7.1 */
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
@@ -236,6 +236,11 @@ class GeoDb {
236
236
 
237
237
  lookupGeoname(geonameid) {
238
238
  geonameid = +geonameid;
239
+
240
+ if (geonameid === 293396) {
241
+ geonameid = 293397;
242
+ }
243
+
239
244
  const found = this.geonamesCache.get(geonameid);
240
245
  if (typeof found !== 'undefined') return found;
241
246
  const result = this.geonamesStmt.get(geonameid);
@@ -372,38 +377,7 @@ class GeoDb {
372
377
 
373
378
  const geoMatches = geoRows.map(res => {
374
379
  const loc = this.lookupGeoname(res.geonameid);
375
- const cc = loc.getCountryCode();
376
- const country = this.countryNames.get(cc) || '';
377
- const admin1 = loc.admin1 || '';
378
- const obj = {
379
- id: res.geonameid,
380
- value: loc.name,
381
- admin1,
382
- country,
383
- cc,
384
- latitude: loc.latitude,
385
- longitude: loc.longitude,
386
- timezone: loc.getTzid(),
387
- geo: 'geoname'
388
- };
389
-
390
- if (loc.population) {
391
- obj.population = loc.population;
392
- }
393
-
394
- if (loc.asciiname) {
395
- obj.asciiname = loc.asciiname;
396
- }
397
-
398
- if (country) {
399
- obj.country = country;
400
- }
401
-
402
- if (admin1) {
403
- obj.admin1 = admin1;
404
- }
405
-
406
- return obj;
380
+ return this.geonameLocToAutocomplete(loc, res);
407
381
  });
408
382
 
409
383
  if (!this.zipFulltextCompStmt) {
@@ -412,42 +386,12 @@ class GeoDb {
412
386
 
413
387
  const zipRows = this.zipFulltextCompStmt.all(`{longname} : "${qraw}" *`);
414
388
  const zipMatches = zipRows.map(res => {
415
- const zipCode = res.ZipCode;
416
- const loc = this.lookupZip(zipCode);
417
- const obj = {
418
- id: zipCode,
419
- value: loc.getName(),
420
- admin1: loc.admin1,
421
- asciiname: loc.getShortName(),
422
- country: 'United States',
423
- cc: 'US',
424
- latitude: loc.latitude,
425
- longitude: loc.longitude,
426
- timezone: loc.getTzid(),
427
- population: loc.population,
428
- geo: 'zip'
429
- };
430
- return obj;
389
+ const loc = this.lookupZip(res.ZipCode);
390
+ return GeoDb.zipLocToAutocomplete(loc);
431
391
  });
432
- const map = new Map();
433
-
434
- for (const obj of zipMatches) {
435
- const key = [obj.asciiname, stateNames[obj.admin1], obj.country].join('|');
436
-
437
- if (!map.has(key)) {
438
- map.set(key, obj);
439
- }
440
- } // GeoNames takes priority over USA ZIP code matches
441
-
442
-
443
- for (const obj of geoMatches) {
444
- const key = [obj.asciiname, obj.admin1, obj.country].join('|');
445
- map.set(key, obj);
446
- }
447
-
448
- const values = Array.from(map.values());
392
+ const values = this.mergeZipGeo(zipMatches, geoMatches);
449
393
  values.sort((a, b) => b.population - a.population);
450
- const topN = values.slice(0, 15);
394
+ const topN = values.slice(0, 12);
451
395
 
452
396
  if (!latlong) {
453
397
  for (const val of topN) {
@@ -461,6 +405,110 @@ class GeoDb {
461
405
  return topN;
462
406
  }
463
407
  }
408
+ /**
409
+ * @private
410
+ * @param {Location} loc
411
+ * @param {any} res
412
+ * @return {any}
413
+ */
414
+
415
+
416
+ geonameLocToAutocomplete(loc, res) {
417
+ const cc = loc.getCountryCode();
418
+ const country = res.country || this.countryNames.get(cc) || '';
419
+ const admin1 = res.admin || loc.admin1 || '';
420
+ const obj = {
421
+ id: res.geonameid,
422
+ value: res.longname,
423
+ admin1,
424
+ country,
425
+ cc,
426
+ latitude: loc.latitude,
427
+ longitude: loc.longitude,
428
+ timezone: loc.getTzid(),
429
+ geo: 'geoname'
430
+ };
431
+
432
+ if (loc.population) {
433
+ obj.population = loc.population;
434
+ }
435
+
436
+ if (res.city !== loc.asciiname) {
437
+ obj.name = res.city;
438
+ }
439
+
440
+ if (loc.asciiname) {
441
+ obj.asciiname = loc.asciiname;
442
+ }
443
+
444
+ if (country) {
445
+ obj.country = country;
446
+ }
447
+
448
+ if (admin1) {
449
+ obj.admin1 = admin1;
450
+ }
451
+
452
+ return obj;
453
+ }
454
+ /**
455
+ * @private
456
+ * @param {Location} loc
457
+ * @return {any}
458
+ */
459
+
460
+
461
+ static zipLocToAutocomplete(loc) {
462
+ return {
463
+ id: loc.zip,
464
+ value: loc.getName(),
465
+ admin1: loc.admin1,
466
+ asciiname: loc.getShortName(),
467
+ country: 'United States',
468
+ cc: 'US',
469
+ latitude: loc.latitude,
470
+ longitude: loc.longitude,
471
+ timezone: loc.getTzid(),
472
+ population: loc.population,
473
+ geo: 'zip'
474
+ };
475
+ }
476
+ /**
477
+ * GeoNames matches takes priority over USA ZIP code matches
478
+ * @private
479
+ * @param {any[]} zipMatches
480
+ * @param {any[]} geoMatches
481
+ * @return {any[]}
482
+ */
483
+
484
+
485
+ mergeZipGeo(zipMatches, geoMatches) {
486
+ const zlen = zipMatches.length;
487
+ const glen = geoMatches.length;
488
+
489
+ if (zlen && !glen) {
490
+ return zipMatches;
491
+ } else if (glen && !zlen) {
492
+ return geoMatches;
493
+ }
494
+
495
+ const map = new Map();
496
+
497
+ for (const obj of zipMatches) {
498
+ const key = [obj.asciiname, stateNames[obj.admin1], obj.cc].join('|');
499
+
500
+ if (!map.has(key)) {
501
+ map.set(key, obj);
502
+ }
503
+ }
504
+
505
+ for (const obj of geoMatches) {
506
+ const key = [obj.asciiname, obj.admin1, obj.cc].join('|');
507
+ map.set(key, obj);
508
+ }
509
+
510
+ return Array.from(map.values());
511
+ }
464
512
  /** Reads entire ZIP database and caches in-memory */
465
513
 
466
514
 
@@ -648,17 +696,34 @@ async function buildGeonamesSqlite(opts) {
648
696
  FROM geoname g, admin1 a, country c
649
697
  WHERE g.country = c.ISO
650
698
  AND g.country <> 'US'
699
+ AND g.country <> 'IL'
700
+ AND g.country <> 'GB'
651
701
  AND g.country||'.'||g.admin1 = a.key
652
702
  `, `INSERT INTO geoname_fulltext
653
703
  SELECT g.geonameid,
654
704
  g.asciiname||', '||a.asciiname||', USA',
655
705
  g.population,
656
- g.asciiname,a.asciiname,'USA'
706
+ g.asciiname,a.asciiname,'United States'
657
707
  FROM geoname g, admin1 a
658
708
  WHERE g.country = 'US'
659
709
  AND g.country||'.'||g.admin1 = a.key
660
710
  `, `INSERT INTO geoname_fulltext
661
711
  SELECT g.geonameid,
712
+ g.asciiname||', '||a.asciiname||', UK',
713
+ g.population,
714
+ g.asciiname,a.asciiname,'UK'
715
+ FROM geoname g, admin1 a
716
+ WHERE g.country = 'GB'
717
+ AND g.country||'.'||g.admin1 = a.key
718
+ `, `INSERT INTO geoname_fulltext
719
+ SELECT g.geonameid,
720
+ g.asciiname||', Israel',
721
+ g.population,
722
+ g.asciiname,NULL,'Israel'
723
+ FROM geoname g
724
+ WHERE g.country = 'IL'
725
+ `, `INSERT INTO geoname_fulltext
726
+ SELECT g.geonameid,
662
727
  g.asciiname||', '||c.Country,
663
728
  g.population,
664
729
  g.asciiname,NULL,c.Country
@@ -685,14 +750,13 @@ async function buildGeonamesSqlite(opts) {
685
750
  AND g.geonameid = alt.geonameid
686
751
  `, `INSERT INTO geoname_fulltext
687
752
  SELECT g.geonameid,
688
- alt.name||', '||a1.asciiname||', Israel',
753
+ alt.name||', Israel',
689
754
  g.population,
690
- alt.name,a1.asciiname,'Israel'
691
- FROM geoname g, admin1 a1, altnames alt
755
+ alt.name,NULL,'Israel'
756
+ FROM geoname g, altnames alt
692
757
  WHERE g.country = 'IL'
693
758
  AND alt.isolanguage = 'en'
694
759
  AND g.geonameid = alt.geonameid
695
- AND g.country||'.'||g.admin1 = a1.key
696
760
  `, 'VACUUM');
697
761
  db.close();
698
762
  return Promise.resolve(true);
package/dist/index.mjs CHANGED
@@ -1,4 +1,4 @@
1
- /*! @hebcal/geo-sqlite v4.5.2 */
1
+ /*! @hebcal/geo-sqlite v4.7.1 */
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
@@ -224,6 +224,11 @@ class GeoDb {
224
224
 
225
225
  lookupGeoname(geonameid) {
226
226
  geonameid = +geonameid;
227
+
228
+ if (geonameid === 293396) {
229
+ geonameid = 293397;
230
+ }
231
+
227
232
  const found = this.geonamesCache.get(geonameid);
228
233
  if (typeof found !== 'undefined') return found;
229
234
  const result = this.geonamesStmt.get(geonameid);
@@ -360,38 +365,7 @@ class GeoDb {
360
365
 
361
366
  const geoMatches = geoRows.map(res => {
362
367
  const loc = this.lookupGeoname(res.geonameid);
363
- const cc = loc.getCountryCode();
364
- const country = this.countryNames.get(cc) || '';
365
- const admin1 = loc.admin1 || '';
366
- const obj = {
367
- id: res.geonameid,
368
- value: loc.name,
369
- admin1,
370
- country,
371
- cc,
372
- latitude: loc.latitude,
373
- longitude: loc.longitude,
374
- timezone: loc.getTzid(),
375
- geo: 'geoname'
376
- };
377
-
378
- if (loc.population) {
379
- obj.population = loc.population;
380
- }
381
-
382
- if (loc.asciiname) {
383
- obj.asciiname = loc.asciiname;
384
- }
385
-
386
- if (country) {
387
- obj.country = country;
388
- }
389
-
390
- if (admin1) {
391
- obj.admin1 = admin1;
392
- }
393
-
394
- return obj;
368
+ return this.geonameLocToAutocomplete(loc, res);
395
369
  });
396
370
 
397
371
  if (!this.zipFulltextCompStmt) {
@@ -400,42 +374,12 @@ class GeoDb {
400
374
 
401
375
  const zipRows = this.zipFulltextCompStmt.all(`{longname} : "${qraw}" *`);
402
376
  const zipMatches = zipRows.map(res => {
403
- const zipCode = res.ZipCode;
404
- const loc = this.lookupZip(zipCode);
405
- const obj = {
406
- id: zipCode,
407
- value: loc.getName(),
408
- admin1: loc.admin1,
409
- asciiname: loc.getShortName(),
410
- country: 'United States',
411
- cc: 'US',
412
- latitude: loc.latitude,
413
- longitude: loc.longitude,
414
- timezone: loc.getTzid(),
415
- population: loc.population,
416
- geo: 'zip'
417
- };
418
- return obj;
377
+ const loc = this.lookupZip(res.ZipCode);
378
+ return GeoDb.zipLocToAutocomplete(loc);
419
379
  });
420
- const map = new Map();
421
-
422
- for (const obj of zipMatches) {
423
- const key = [obj.asciiname, stateNames[obj.admin1], obj.country].join('|');
424
-
425
- if (!map.has(key)) {
426
- map.set(key, obj);
427
- }
428
- } // GeoNames takes priority over USA ZIP code matches
429
-
430
-
431
- for (const obj of geoMatches) {
432
- const key = [obj.asciiname, obj.admin1, obj.country].join('|');
433
- map.set(key, obj);
434
- }
435
-
436
- const values = Array.from(map.values());
380
+ const values = this.mergeZipGeo(zipMatches, geoMatches);
437
381
  values.sort((a, b) => b.population - a.population);
438
- const topN = values.slice(0, 15);
382
+ const topN = values.slice(0, 12);
439
383
 
440
384
  if (!latlong) {
441
385
  for (const val of topN) {
@@ -449,6 +393,110 @@ class GeoDb {
449
393
  return topN;
450
394
  }
451
395
  }
396
+ /**
397
+ * @private
398
+ * @param {Location} loc
399
+ * @param {any} res
400
+ * @return {any}
401
+ */
402
+
403
+
404
+ geonameLocToAutocomplete(loc, res) {
405
+ const cc = loc.getCountryCode();
406
+ const country = res.country || this.countryNames.get(cc) || '';
407
+ const admin1 = res.admin || loc.admin1 || '';
408
+ const obj = {
409
+ id: res.geonameid,
410
+ value: res.longname,
411
+ admin1,
412
+ country,
413
+ cc,
414
+ latitude: loc.latitude,
415
+ longitude: loc.longitude,
416
+ timezone: loc.getTzid(),
417
+ geo: 'geoname'
418
+ };
419
+
420
+ if (loc.population) {
421
+ obj.population = loc.population;
422
+ }
423
+
424
+ if (res.city !== loc.asciiname) {
425
+ obj.name = res.city;
426
+ }
427
+
428
+ if (loc.asciiname) {
429
+ obj.asciiname = loc.asciiname;
430
+ }
431
+
432
+ if (country) {
433
+ obj.country = country;
434
+ }
435
+
436
+ if (admin1) {
437
+ obj.admin1 = admin1;
438
+ }
439
+
440
+ return obj;
441
+ }
442
+ /**
443
+ * @private
444
+ * @param {Location} loc
445
+ * @return {any}
446
+ */
447
+
448
+
449
+ static zipLocToAutocomplete(loc) {
450
+ return {
451
+ id: loc.zip,
452
+ value: loc.getName(),
453
+ admin1: loc.admin1,
454
+ asciiname: loc.getShortName(),
455
+ country: 'United States',
456
+ cc: 'US',
457
+ latitude: loc.latitude,
458
+ longitude: loc.longitude,
459
+ timezone: loc.getTzid(),
460
+ population: loc.population,
461
+ geo: 'zip'
462
+ };
463
+ }
464
+ /**
465
+ * GeoNames matches takes priority over USA ZIP code matches
466
+ * @private
467
+ * @param {any[]} zipMatches
468
+ * @param {any[]} geoMatches
469
+ * @return {any[]}
470
+ */
471
+
472
+
473
+ mergeZipGeo(zipMatches, geoMatches) {
474
+ const zlen = zipMatches.length;
475
+ const glen = geoMatches.length;
476
+
477
+ if (zlen && !glen) {
478
+ return zipMatches;
479
+ } else if (glen && !zlen) {
480
+ return geoMatches;
481
+ }
482
+
483
+ const map = new Map();
484
+
485
+ for (const obj of zipMatches) {
486
+ const key = [obj.asciiname, stateNames[obj.admin1], obj.cc].join('|');
487
+
488
+ if (!map.has(key)) {
489
+ map.set(key, obj);
490
+ }
491
+ }
492
+
493
+ for (const obj of geoMatches) {
494
+ const key = [obj.asciiname, obj.admin1, obj.cc].join('|');
495
+ map.set(key, obj);
496
+ }
497
+
498
+ return Array.from(map.values());
499
+ }
452
500
  /** Reads entire ZIP database and caches in-memory */
453
501
 
454
502
 
@@ -636,17 +684,34 @@ async function buildGeonamesSqlite(opts) {
636
684
  FROM geoname g, admin1 a, country c
637
685
  WHERE g.country = c.ISO
638
686
  AND g.country <> 'US'
687
+ AND g.country <> 'IL'
688
+ AND g.country <> 'GB'
639
689
  AND g.country||'.'||g.admin1 = a.key
640
690
  `, `INSERT INTO geoname_fulltext
641
691
  SELECT g.geonameid,
642
692
  g.asciiname||', '||a.asciiname||', USA',
643
693
  g.population,
644
- g.asciiname,a.asciiname,'USA'
694
+ g.asciiname,a.asciiname,'United States'
645
695
  FROM geoname g, admin1 a
646
696
  WHERE g.country = 'US'
647
697
  AND g.country||'.'||g.admin1 = a.key
648
698
  `, `INSERT INTO geoname_fulltext
649
699
  SELECT g.geonameid,
700
+ g.asciiname||', '||a.asciiname||', UK',
701
+ g.population,
702
+ g.asciiname,a.asciiname,'UK'
703
+ FROM geoname g, admin1 a
704
+ WHERE g.country = 'GB'
705
+ AND g.country||'.'||g.admin1 = a.key
706
+ `, `INSERT INTO geoname_fulltext
707
+ SELECT g.geonameid,
708
+ g.asciiname||', Israel',
709
+ g.population,
710
+ g.asciiname,NULL,'Israel'
711
+ FROM geoname g
712
+ WHERE g.country = 'IL'
713
+ `, `INSERT INTO geoname_fulltext
714
+ SELECT g.geonameid,
650
715
  g.asciiname||', '||c.Country,
651
716
  g.population,
652
717
  g.asciiname,NULL,c.Country
@@ -673,14 +738,13 @@ async function buildGeonamesSqlite(opts) {
673
738
  AND g.geonameid = alt.geonameid
674
739
  `, `INSERT INTO geoname_fulltext
675
740
  SELECT g.geonameid,
676
- alt.name||', '||a1.asciiname||', Israel',
741
+ alt.name||', Israel',
677
742
  g.population,
678
- alt.name,a1.asciiname,'Israel'
679
- FROM geoname g, admin1 a1, altnames alt
743
+ alt.name,NULL,'Israel'
744
+ FROM geoname g, altnames alt
680
745
  WHERE g.country = 'IL'
681
746
  AND alt.isolanguage = 'en'
682
747
  AND g.geonameid = alt.geonameid
683
- AND g.country||'.'||g.admin1 = a1.key
684
748
  `, 'VACUUM');
685
749
  db.close();
686
750
  return Promise.resolve(true);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hebcal/geo-sqlite",
3
- "version": "4.5.2",
3
+ "version": "4.7.1",
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
  }