@hebcal/geo-sqlite 4.9.1 → 4.9.3

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/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- /*! @hebcal/geo-sqlite v4.9.1 */
1
+ /*! @hebcal/geo-sqlite v4.9.3 */
2
2
  'use strict';
3
3
 
4
4
  var Database = require('better-sqlite3');
@@ -18,10 +18,7 @@ let a=[["\0","","","","","","","","\b","\t","\n","\v","\f","\r","","","
18
18
  * @return {string}
19
19
  */
20
20
  function munge(s) {
21
- return s.toLowerCase()
22
- .replace(/'/g, '')
23
- .replace(/ /g, '')
24
- .replace(/\+/g, '');
21
+ return s.toLowerCase().replace(/'/g, '').replace(/ /g, '').replace(/\+/g, '');
25
22
  }
26
23
 
27
24
  const GEONAME_SQL = `SELECT
@@ -39,7 +36,6 @@ LEFT JOIN country c on g.country = c.iso
39
36
  LEFT JOIN admin1 a on g.country||'.'||g.admin1 = a.key
40
37
  WHERE g.geonameid = ?
41
38
  `;
42
-
43
39
  const GEONAME_ALL_SQL = `SELECT
44
40
  g.geonameid as geonameid,
45
41
  g.name as name,
@@ -55,33 +51,25 @@ FROM geoname g
55
51
  LEFT JOIN country c on g.country = c.iso
56
52
  LEFT JOIN admin1 a on g.country||'.'||g.admin1 = a.key
57
53
  `;
58
-
59
54
  const ZIPCODE_SQL = `SELECT ZipCode,CityMixedCase,State,Latitude,Longitude,TimeZone,DayLightSaving,Population
60
55
  FROM ZIPCodes_Primary WHERE ZipCode = ?`;
61
-
62
56
  const ZIPCODE_ALL_SQL = `SELECT ZipCode,CityMixedCase,State,Latitude,Longitude,TimeZone,DayLightSaving,Population
63
57
  FROM ZIPCodes_Primary`;
64
-
65
58
  const ZIP_COMPLETE_SQL = `SELECT ZipCode,CityMixedCase,State,Latitude,Longitude,TimeZone,DayLightSaving,Population
66
59
  FROM ZIPCodes_Primary
67
60
  WHERE ZipCode LIKE ?
68
61
  ORDER BY Population DESC
69
62
  LIMIT 10`;
70
-
71
- const ZIP_FULLTEXT_COMPLETE_SQL =
72
- `SELECT ZipCode
63
+ const ZIP_FULLTEXT_COMPLETE_SQL = `SELECT ZipCode
73
64
  FROM ZIPCodes_CityFullText5
74
65
  WHERE ZIPCodes_CityFullText5 MATCH ?
75
66
  ORDER BY Population DESC
76
67
  LIMIT 20`;
77
-
78
- const GEONAME_COMPLETE_SQL =
79
- `SELECT geonameid, longname, city, admin1, country
68
+ const GEONAME_COMPLETE_SQL = `SELECT geonameid, longname, city, admin1, country
80
69
  FROM geoname_fulltext
81
70
  WHERE geoname_fulltext MATCH ?
82
71
  ORDER BY population DESC
83
72
  LIMIT 20`;
84
-
85
73
  const stateNames = {
86
74
  'AK': 'Alaska',
87
75
  'AL': 'Alabama',
@@ -133,7 +121,7 @@ const stateNames = {
133
121
  'WA': 'Washington',
134
122
  'WI': 'Wisconsin',
135
123
  'WV': 'West Virginia',
136
- 'WY': 'Wyoming',
124
+ 'WY': 'Wyoming'
137
125
  };
138
126
 
139
127
  /** Wrapper around sqlite databases */
@@ -146,9 +134,13 @@ class GeoDb {
146
134
  constructor(logger, zipsFilename, geonamesFilename) {
147
135
  this.logger = logger;
148
136
  if (logger) logger.info(`GeoDb: opening ${zipsFilename}...`);
149
- this.zipsDb = new Database(zipsFilename, {fileMustExist: true});
137
+ this.zipsDb = new Database(zipsFilename, {
138
+ fileMustExist: true
139
+ });
150
140
  if (logger) logger.info(`GeoDb: opening ${geonamesFilename}...`);
151
- this.geonamesDb = new Database(geonamesFilename, {fileMustExist: true});
141
+ this.geonamesDb = new Database(geonamesFilename, {
142
+ fileMustExist: true
143
+ });
152
144
  this.zipStmt = this.zipsDb.prepare(ZIPCODE_SQL);
153
145
  /** @type {Map<string, Location>} */
154
146
  this.zipCache = new Map();
@@ -294,15 +286,7 @@ class GeoDb {
294
286
  const country = result.country || '';
295
287
  const admin1 = result.admin1 || '';
296
288
  const cityDescr = GeoDb.geonameCityDescr(result.name, admin1, country);
297
- const location = new core.Location(
298
- result.latitude,
299
- result.longitude,
300
- result.cc == 'IL',
301
- result.timezone,
302
- cityDescr,
303
- result.cc,
304
- geonameid,
305
- );
289
+ const location = new core.Location(result.latitude, result.longitude, result.cc == 'IL', result.timezone, cityDescr, result.cc, geonameid);
306
290
  location.geo = 'geoname';
307
291
  location.geonameid = geonameid;
308
292
  location.asciiname = result.asciiname;
@@ -354,7 +338,7 @@ class GeoDb {
354
338
  longitude: res.Longitude,
355
339
  timezone: core.Location.getUsaTzid(res.State, res.TimeZone, res.DayLightSaving),
356
340
  population: res.Population,
357
- geo: 'zip',
341
+ geo: 'zip'
358
342
  };
359
343
  return obj;
360
344
  }
@@ -365,7 +349,7 @@ class GeoDb {
365
349
  * @param {boolean} latlong
366
350
  * @return {Object[]}
367
351
  */
368
- autoComplete(qraw, latlong=false) {
352
+ autoComplete(qraw, latlong = false) {
369
353
  qraw = qraw.trim();
370
354
  if (qraw.length === 0) {
371
355
  return [];
@@ -392,7 +376,7 @@ class GeoDb {
392
376
  geoRows.push(row);
393
377
  }
394
378
  }
395
- const geoMatches = geoRows.map((res) => {
379
+ const geoMatches = geoRows.map(res => {
396
380
  const loc = this.lookupGeoname(res.geonameid);
397
381
  return this.geonameLocToAutocomplete(loc, res);
398
382
  });
@@ -400,7 +384,7 @@ class GeoDb {
400
384
  this.zipFulltextCompStmt = this.zipsDb.prepare(ZIP_FULLTEXT_COMPLETE_SQL);
401
385
  }
402
386
  const zipRows = this.zipFulltextCompStmt.all(`{longname} : "${qraw}" *`);
403
- const zipMatches = zipRows.map((res) => {
387
+ const zipMatches = zipRows.map(res => {
404
388
  const loc = this.lookupZip(res.ZipCode);
405
389
  return GeoDb.zipLocToAutocomplete(loc);
406
390
  });
@@ -438,7 +422,7 @@ class GeoDb {
438
422
  latitude: loc.latitude,
439
423
  longitude: loc.longitude,
440
424
  timezone: loc.getTzid(),
441
- geo: 'geoname',
425
+ geo: 'geoname'
442
426
  };
443
427
  if (loc.population) {
444
428
  obj.population = loc.population;
@@ -475,7 +459,7 @@ class GeoDb {
475
459
  longitude: loc.longitude,
476
460
  timezone: loc.getTzid(),
477
461
  population: loc.population,
478
- geo: 'zip',
462
+ geo: 'zip'
479
463
  };
480
464
  }
481
465
 
@@ -551,11 +535,7 @@ async function buildGeonamesSqlite(opts) {
551
535
  logger.info(`Opening ${dbFilename}`);
552
536
  const db = new Database(dbFilename);
553
537
  db.pragma('journal_mode = MEMORY');
554
-
555
- doSql(logger, db,
556
- `DROP TABLE IF EXISTS country`,
557
-
558
- `CREATE TABLE country (
538
+ doSql(logger, db, `DROP TABLE IF EXISTS country`, `CREATE TABLE country (
559
539
  ISO TEXT PRIMARY KEY,
560
540
  ISO3 TEXT NOT NULL,
561
541
  IsoNumeric TEXT NOT NULL,
@@ -575,14 +555,9 @@ async function buildGeonamesSqlite(opts) {
575
555
  geonameid INT NOT NULL,
576
556
  neighbours TEXT NOT NULL,
577
557
  EquivalentFipsCode TEXT NOT NULL
578
- );`,
579
- );
558
+ );`);
580
559
  await doFile(logger, db, countryInfotxt, 'country', 19);
581
-
582
- doSql(logger, db,
583
- `DROP TABLE IF EXISTS geoname`,
584
-
585
- `CREATE TABLE geoname (
560
+ doSql(logger, db, `DROP TABLE IF EXISTS geoname`, `CREATE TABLE geoname (
586
561
  geonameid int PRIMARY KEY,
587
562
  name nvarchar(200),
588
563
  asciiname nvarchar(200),
@@ -601,48 +576,32 @@ async function buildGeonamesSqlite(opts) {
601
576
  elevation int,
602
577
  gtopo30 int,
603
578
  timezone nvarchar(40),
604
- moddate date);`,
605
- );
606
-
607
- const truncateAlternateNames = (a) => {
579
+ moddate date);`);
580
+ const truncateAlternateNames = a => {
608
581
  a[3] = '';
609
582
  return true;
610
583
  };
611
584
  await doFile(logger, db, cities5000txt, 'geoname', 19, truncateAlternateNames);
612
585
  await doFile(logger, db, citiesPatch, 'geoname', 19, truncateAlternateNames);
613
- await doFile(logger, db, ILtxt, 'geoname', 19, (a) => {
586
+ await doFile(logger, db, ILtxt, 'geoname', 19, a => {
614
587
  a[3] = '';
615
588
  return a[6] == 'P' && (a[7] == 'PPL' || a[7] == 'STLMT');
616
589
  });
617
-
618
- doSql(logger, db,
619
- `DROP TABLE IF EXISTS admin1`,
620
-
621
- `CREATE TABLE admin1 (
590
+ doSql(logger, db, `DROP TABLE IF EXISTS admin1`, `CREATE TABLE admin1 (
622
591
  key TEXT PRIMARY KEY,
623
592
  name nvarchar(200) NOT NULL,
624
593
  asciiname nvarchar(200) NOT NULL,
625
594
  geonameid int NOT NULL
626
- );`,
627
- );
628
-
595
+ );`);
629
596
  await doFile(logger, db, admin1CodesASCIItxt, 'admin1', 4);
630
597
 
631
598
  // fix inconsistencies with the USA capitol
632
- doSql(logger, db,
633
- `UPDATE geoname
599
+ doSql(logger, db, `UPDATE geoname
634
600
  SET name = 'Washington, D.C.', asciiname = 'Washington, D.C.'
635
- WHERE geonameid = 4140963;`,
636
-
637
- `UPDATE admin1
601
+ WHERE geonameid = 4140963;`, `UPDATE admin1
638
602
  SET name = 'Washington, D.C.', asciiname = 'Washington, D.C.'
639
- WHERE key = 'US.DC';`,
640
- );
641
-
642
- doSql(logger, db,
643
- `DROP TABLE IF EXISTS alternatenames`,
644
-
645
- `CREATE TABLE alternatenames (
603
+ WHERE key = 'US.DC';`);
604
+ doSql(logger, db, `DROP TABLE IF EXISTS alternatenames`, `CREATE TABLE alternatenames (
646
605
  id int PRIMARY KEY,
647
606
  geonameid int NOT NULL,
648
607
  isolanguage varchar(7),
@@ -653,10 +612,8 @@ async function buildGeonamesSqlite(opts) {
653
612
  isHistoric tinyint,
654
613
  periodFrom NULL,
655
614
  periodTo NULL
656
- );`,
657
- );
658
-
659
- await doFile(logger, db, ILalternate, 'alternatenames', 10, (a) => {
615
+ );`);
616
+ await doFile(logger, db, ILalternate, 'alternatenames', 10, a => {
660
617
  const firstchar = a[3][0];
661
618
  if (a[2] === 'he' && (firstchar < '\u05D0' || firstchar > '\u05EA')) {
662
619
  a[2] = 'en';
@@ -684,35 +641,16 @@ async function buildGeonamesSqlite(opts) {
684
641
  });
685
642
 
686
643
  // remove duplicates from alternatenames
687
- doSql(logger, db,
688
- `DROP TABLE IF EXISTS altnames`,
689
-
690
- `CREATE TABLE altnames
644
+ doSql(logger, db, `DROP TABLE IF EXISTS altnames`, `CREATE TABLE altnames
691
645
  AS SELECT geonameid, isolanguage, name
692
646
  FROM alternatenames
693
647
  GROUP BY 1, 2, 3
694
- `,
695
- );
696
-
697
- doSql(logger, db,
698
- `update admin1 set name='',asciiname='' where key like 'PS.%';`,
699
- `update country set country = '' where iso = 'PS';`,
700
- `delete from geoname where geonameid = 7303419;`,
701
- );
702
-
703
- doSql(logger, db,
704
- `DROP TABLE IF EXISTS geoname_fulltext`,
705
-
706
- `CREATE VIRTUAL TABLE geoname_fulltext
648
+ `);
649
+ doSql(logger, db, `update admin1 set name='',asciiname='' where key like 'PS.%';`, `update country set country = '' where iso = 'PS';`, `delete from geoname where geonameid = 7303419;`);
650
+ doSql(logger, db, `DROP TABLE IF EXISTS geoname_fulltext`, `CREATE VIRTUAL TABLE geoname_fulltext
707
651
  USING fts5(geonameid UNINDEXED, longname, population, city, admin1, country);
708
- `,
709
-
710
- `DROP TABLE IF EXISTS geoname_non_ascii`,
711
-
712
- `CREATE TABLE geoname_non_ascii AS
713
- SELECT geonameid FROM geoname WHERE asciiname <> name`,
714
-
715
- `INSERT INTO geoname_fulltext
652
+ `, `DROP TABLE IF EXISTS geoname_non_ascii`, `CREATE TABLE geoname_non_ascii AS
653
+ SELECT geonameid FROM geoname WHERE asciiname <> name`, `INSERT INTO geoname_fulltext
716
654
  SELECT g.geonameid,
717
655
  g.asciiname||', '||a.asciiname||', '||c.Country,
718
656
  g.population,
@@ -723,9 +661,7 @@ async function buildGeonamesSqlite(opts) {
723
661
  AND g.country <> 'IL'
724
662
  AND g.country <> 'GB'
725
663
  AND g.country||'.'||g.admin1 = a.key
726
- `,
727
-
728
- `INSERT INTO geoname_fulltext
664
+ `, `INSERT INTO geoname_fulltext
729
665
  SELECT g.geonameid,
730
666
  g.asciiname||', '||a.asciiname||', USA',
731
667
  g.population,
@@ -733,9 +669,7 @@ async function buildGeonamesSqlite(opts) {
733
669
  FROM geoname g, admin1 a
734
670
  WHERE g.country = 'US'
735
671
  AND g.country||'.'||g.admin1 = a.key
736
- `,
737
-
738
- `INSERT INTO geoname_fulltext
672
+ `, `INSERT INTO geoname_fulltext
739
673
  SELECT g.geonameid,
740
674
  g.asciiname||', '||a.asciiname||', UK',
741
675
  g.population,
@@ -743,18 +677,14 @@ async function buildGeonamesSqlite(opts) {
743
677
  FROM geoname g, admin1 a
744
678
  WHERE g.country = 'GB'
745
679
  AND g.country||'.'||g.admin1 = a.key
746
- `,
747
-
748
- `INSERT INTO geoname_fulltext
680
+ `, `INSERT INTO geoname_fulltext
749
681
  SELECT g.geonameid,
750
682
  g.asciiname||', Israel',
751
683
  g.population,
752
684
  g.asciiname,NULL,'Israel'
753
685
  FROM geoname g
754
686
  WHERE g.country = 'IL'
755
- `,
756
-
757
- `INSERT INTO geoname_fulltext
687
+ `, `INSERT INTO geoname_fulltext
758
688
  SELECT g.geonameid,
759
689
  g.asciiname||', '||c.Country,
760
690
  g.population,
@@ -762,9 +692,7 @@ async function buildGeonamesSqlite(opts) {
762
692
  FROM geoname g, country c
763
693
  WHERE g.country = c.ISO
764
694
  AND (g.admin1 = '' OR g.admin1 = '00')
765
- `,
766
-
767
- `INSERT INTO geoname_fulltext
695
+ `, `INSERT INTO geoname_fulltext
768
696
  SELECT g.geonameid,
769
697
  g.name||', '||a.name||', '||c.Country,
770
698
  g.population,
@@ -773,9 +701,7 @@ async function buildGeonamesSqlite(opts) {
773
701
  WHERE gna.geonameid = g.geonameid
774
702
  AND g.country = c.ISO
775
703
  AND g.country||'.'||g.admin1 = a.key
776
- `,
777
-
778
- `INSERT INTO geoname_fulltext
704
+ `, `INSERT INTO geoname_fulltext
779
705
  SELECT g.geonameid,
780
706
  alt.name||', ישראל',
781
707
  g.population,
@@ -784,9 +710,7 @@ async function buildGeonamesSqlite(opts) {
784
710
  WHERE g.country = 'IL'
785
711
  AND alt.isolanguage = 'he'
786
712
  AND g.geonameid = alt.geonameid
787
- `,
788
-
789
- `INSERT INTO geoname_fulltext
713
+ `, `INSERT INTO geoname_fulltext
790
714
  SELECT g.geonameid,
791
715
  alt.name||', Israel',
792
716
  g.population,
@@ -795,11 +719,7 @@ async function buildGeonamesSqlite(opts) {
795
719
  WHERE g.country = 'IL'
796
720
  AND alt.isolanguage = 'en'
797
721
  AND g.geonameid = alt.geonameid
798
- `,
799
-
800
- 'VACUUM',
801
- );
802
-
722
+ `, 'VACUUM');
803
723
  return new Promise((resolve, reject) => {
804
724
  try {
805
725
  logger.info(`Closing ${dbFilename}`);
@@ -847,11 +767,11 @@ async function doFile(logger, db, infile, tableName, expectedFields, callback) {
847
767
  try {
848
768
  const rl = readline.createInterface({
849
769
  input: fs.createReadStream(infile),
850
- crlfDelay: Infinity,
770
+ crlfDelay: Infinity
851
771
  });
852
772
  let num = 0;
853
773
  let accepted = 0;
854
- rl.on('line', (line) => {
774
+ rl.on('line', line => {
855
775
  num++;
856
776
  if (line[0] == '#') {
857
777
  return;
@@ -870,13 +790,11 @@ async function doFile(logger, db, infile, tableName, expectedFields, callback) {
870
790
  stmt.run(a);
871
791
  accepted++;
872
792
  });
873
-
874
793
  rl.on('close', () => {
875
794
  logger.info(`Inserted ${accepted} / ${num} into ${tableName} from ${infile}`);
876
795
  stmt = null;
877
796
  db.exec('COMMIT');
878
797
  });
879
-
880
798
  return resolve(events.once(rl, 'close'));
881
799
  } catch (err) {
882
800
  logger.error(err);
package/dist/index.mjs CHANGED
@@ -1,4 +1,4 @@
1
- /*! @hebcal/geo-sqlite v4.9.1 */
1
+ /*! @hebcal/geo-sqlite v4.9.3 */
2
2
  import Database from 'better-sqlite3';
3
3
  import { Location, Locale } from '@hebcal/core';
4
4
  import '@hebcal/cities';
@@ -16,10 +16,7 @@ let a=[["\0","","","","","","","","\b","\t","\n","\v","\f","\r","","","
16
16
  * @return {string}
17
17
  */
18
18
  function munge(s) {
19
- return s.toLowerCase()
20
- .replace(/'/g, '')
21
- .replace(/ /g, '')
22
- .replace(/\+/g, '');
19
+ return s.toLowerCase().replace(/'/g, '').replace(/ /g, '').replace(/\+/g, '');
23
20
  }
24
21
 
25
22
  const GEONAME_SQL = `SELECT
@@ -37,7 +34,6 @@ LEFT JOIN country c on g.country = c.iso
37
34
  LEFT JOIN admin1 a on g.country||'.'||g.admin1 = a.key
38
35
  WHERE g.geonameid = ?
39
36
  `;
40
-
41
37
  const GEONAME_ALL_SQL = `SELECT
42
38
  g.geonameid as geonameid,
43
39
  g.name as name,
@@ -53,33 +49,25 @@ FROM geoname g
53
49
  LEFT JOIN country c on g.country = c.iso
54
50
  LEFT JOIN admin1 a on g.country||'.'||g.admin1 = a.key
55
51
  `;
56
-
57
52
  const ZIPCODE_SQL = `SELECT ZipCode,CityMixedCase,State,Latitude,Longitude,TimeZone,DayLightSaving,Population
58
53
  FROM ZIPCodes_Primary WHERE ZipCode = ?`;
59
-
60
54
  const ZIPCODE_ALL_SQL = `SELECT ZipCode,CityMixedCase,State,Latitude,Longitude,TimeZone,DayLightSaving,Population
61
55
  FROM ZIPCodes_Primary`;
62
-
63
56
  const ZIP_COMPLETE_SQL = `SELECT ZipCode,CityMixedCase,State,Latitude,Longitude,TimeZone,DayLightSaving,Population
64
57
  FROM ZIPCodes_Primary
65
58
  WHERE ZipCode LIKE ?
66
59
  ORDER BY Population DESC
67
60
  LIMIT 10`;
68
-
69
- const ZIP_FULLTEXT_COMPLETE_SQL =
70
- `SELECT ZipCode
61
+ const ZIP_FULLTEXT_COMPLETE_SQL = `SELECT ZipCode
71
62
  FROM ZIPCodes_CityFullText5
72
63
  WHERE ZIPCodes_CityFullText5 MATCH ?
73
64
  ORDER BY Population DESC
74
65
  LIMIT 20`;
75
-
76
- const GEONAME_COMPLETE_SQL =
77
- `SELECT geonameid, longname, city, admin1, country
66
+ const GEONAME_COMPLETE_SQL = `SELECT geonameid, longname, city, admin1, country
78
67
  FROM geoname_fulltext
79
68
  WHERE geoname_fulltext MATCH ?
80
69
  ORDER BY population DESC
81
70
  LIMIT 20`;
82
-
83
71
  const stateNames = {
84
72
  'AK': 'Alaska',
85
73
  'AL': 'Alabama',
@@ -131,7 +119,7 @@ const stateNames = {
131
119
  'WA': 'Washington',
132
120
  'WI': 'Wisconsin',
133
121
  'WV': 'West Virginia',
134
- 'WY': 'Wyoming',
122
+ 'WY': 'Wyoming'
135
123
  };
136
124
 
137
125
  /** Wrapper around sqlite databases */
@@ -144,9 +132,13 @@ class GeoDb {
144
132
  constructor(logger, zipsFilename, geonamesFilename) {
145
133
  this.logger = logger;
146
134
  if (logger) logger.info(`GeoDb: opening ${zipsFilename}...`);
147
- this.zipsDb = new Database(zipsFilename, {fileMustExist: true});
135
+ this.zipsDb = new Database(zipsFilename, {
136
+ fileMustExist: true
137
+ });
148
138
  if (logger) logger.info(`GeoDb: opening ${geonamesFilename}...`);
149
- this.geonamesDb = new Database(geonamesFilename, {fileMustExist: true});
139
+ this.geonamesDb = new Database(geonamesFilename, {
140
+ fileMustExist: true
141
+ });
150
142
  this.zipStmt = this.zipsDb.prepare(ZIPCODE_SQL);
151
143
  /** @type {Map<string, Location>} */
152
144
  this.zipCache = new Map();
@@ -292,15 +284,7 @@ class GeoDb {
292
284
  const country = result.country || '';
293
285
  const admin1 = result.admin1 || '';
294
286
  const cityDescr = GeoDb.geonameCityDescr(result.name, admin1, country);
295
- const location = new Location(
296
- result.latitude,
297
- result.longitude,
298
- result.cc == 'IL',
299
- result.timezone,
300
- cityDescr,
301
- result.cc,
302
- geonameid,
303
- );
287
+ const location = new Location(result.latitude, result.longitude, result.cc == 'IL', result.timezone, cityDescr, result.cc, geonameid);
304
288
  location.geo = 'geoname';
305
289
  location.geonameid = geonameid;
306
290
  location.asciiname = result.asciiname;
@@ -352,7 +336,7 @@ class GeoDb {
352
336
  longitude: res.Longitude,
353
337
  timezone: Location.getUsaTzid(res.State, res.TimeZone, res.DayLightSaving),
354
338
  population: res.Population,
355
- geo: 'zip',
339
+ geo: 'zip'
356
340
  };
357
341
  return obj;
358
342
  }
@@ -363,7 +347,7 @@ class GeoDb {
363
347
  * @param {boolean} latlong
364
348
  * @return {Object[]}
365
349
  */
366
- autoComplete(qraw, latlong=false) {
350
+ autoComplete(qraw, latlong = false) {
367
351
  qraw = qraw.trim();
368
352
  if (qraw.length === 0) {
369
353
  return [];
@@ -390,7 +374,7 @@ class GeoDb {
390
374
  geoRows.push(row);
391
375
  }
392
376
  }
393
- const geoMatches = geoRows.map((res) => {
377
+ const geoMatches = geoRows.map(res => {
394
378
  const loc = this.lookupGeoname(res.geonameid);
395
379
  return this.geonameLocToAutocomplete(loc, res);
396
380
  });
@@ -398,7 +382,7 @@ class GeoDb {
398
382
  this.zipFulltextCompStmt = this.zipsDb.prepare(ZIP_FULLTEXT_COMPLETE_SQL);
399
383
  }
400
384
  const zipRows = this.zipFulltextCompStmt.all(`{longname} : "${qraw}" *`);
401
- const zipMatches = zipRows.map((res) => {
385
+ const zipMatches = zipRows.map(res => {
402
386
  const loc = this.lookupZip(res.ZipCode);
403
387
  return GeoDb.zipLocToAutocomplete(loc);
404
388
  });
@@ -436,7 +420,7 @@ class GeoDb {
436
420
  latitude: loc.latitude,
437
421
  longitude: loc.longitude,
438
422
  timezone: loc.getTzid(),
439
- geo: 'geoname',
423
+ geo: 'geoname'
440
424
  };
441
425
  if (loc.population) {
442
426
  obj.population = loc.population;
@@ -473,7 +457,7 @@ class GeoDb {
473
457
  longitude: loc.longitude,
474
458
  timezone: loc.getTzid(),
475
459
  population: loc.population,
476
- geo: 'zip',
460
+ geo: 'zip'
477
461
  };
478
462
  }
479
463
 
@@ -549,11 +533,7 @@ async function buildGeonamesSqlite(opts) {
549
533
  logger.info(`Opening ${dbFilename}`);
550
534
  const db = new Database(dbFilename);
551
535
  db.pragma('journal_mode = MEMORY');
552
-
553
- doSql(logger, db,
554
- `DROP TABLE IF EXISTS country`,
555
-
556
- `CREATE TABLE country (
536
+ doSql(logger, db, `DROP TABLE IF EXISTS country`, `CREATE TABLE country (
557
537
  ISO TEXT PRIMARY KEY,
558
538
  ISO3 TEXT NOT NULL,
559
539
  IsoNumeric TEXT NOT NULL,
@@ -573,14 +553,9 @@ async function buildGeonamesSqlite(opts) {
573
553
  geonameid INT NOT NULL,
574
554
  neighbours TEXT NOT NULL,
575
555
  EquivalentFipsCode TEXT NOT NULL
576
- );`,
577
- );
556
+ );`);
578
557
  await doFile(logger, db, countryInfotxt, 'country', 19);
579
-
580
- doSql(logger, db,
581
- `DROP TABLE IF EXISTS geoname`,
582
-
583
- `CREATE TABLE geoname (
558
+ doSql(logger, db, `DROP TABLE IF EXISTS geoname`, `CREATE TABLE geoname (
584
559
  geonameid int PRIMARY KEY,
585
560
  name nvarchar(200),
586
561
  asciiname nvarchar(200),
@@ -599,48 +574,32 @@ async function buildGeonamesSqlite(opts) {
599
574
  elevation int,
600
575
  gtopo30 int,
601
576
  timezone nvarchar(40),
602
- moddate date);`,
603
- );
604
-
605
- const truncateAlternateNames = (a) => {
577
+ moddate date);`);
578
+ const truncateAlternateNames = a => {
606
579
  a[3] = '';
607
580
  return true;
608
581
  };
609
582
  await doFile(logger, db, cities5000txt, 'geoname', 19, truncateAlternateNames);
610
583
  await doFile(logger, db, citiesPatch, 'geoname', 19, truncateAlternateNames);
611
- await doFile(logger, db, ILtxt, 'geoname', 19, (a) => {
584
+ await doFile(logger, db, ILtxt, 'geoname', 19, a => {
612
585
  a[3] = '';
613
586
  return a[6] == 'P' && (a[7] == 'PPL' || a[7] == 'STLMT');
614
587
  });
615
-
616
- doSql(logger, db,
617
- `DROP TABLE IF EXISTS admin1`,
618
-
619
- `CREATE TABLE admin1 (
588
+ doSql(logger, db, `DROP TABLE IF EXISTS admin1`, `CREATE TABLE admin1 (
620
589
  key TEXT PRIMARY KEY,
621
590
  name nvarchar(200) NOT NULL,
622
591
  asciiname nvarchar(200) NOT NULL,
623
592
  geonameid int NOT NULL
624
- );`,
625
- );
626
-
593
+ );`);
627
594
  await doFile(logger, db, admin1CodesASCIItxt, 'admin1', 4);
628
595
 
629
596
  // fix inconsistencies with the USA capitol
630
- doSql(logger, db,
631
- `UPDATE geoname
597
+ doSql(logger, db, `UPDATE geoname
632
598
  SET name = 'Washington, D.C.', asciiname = 'Washington, D.C.'
633
- WHERE geonameid = 4140963;`,
634
-
635
- `UPDATE admin1
599
+ WHERE geonameid = 4140963;`, `UPDATE admin1
636
600
  SET name = 'Washington, D.C.', asciiname = 'Washington, D.C.'
637
- WHERE key = 'US.DC';`,
638
- );
639
-
640
- doSql(logger, db,
641
- `DROP TABLE IF EXISTS alternatenames`,
642
-
643
- `CREATE TABLE alternatenames (
601
+ WHERE key = 'US.DC';`);
602
+ doSql(logger, db, `DROP TABLE IF EXISTS alternatenames`, `CREATE TABLE alternatenames (
644
603
  id int PRIMARY KEY,
645
604
  geonameid int NOT NULL,
646
605
  isolanguage varchar(7),
@@ -651,10 +610,8 @@ async function buildGeonamesSqlite(opts) {
651
610
  isHistoric tinyint,
652
611
  periodFrom NULL,
653
612
  periodTo NULL
654
- );`,
655
- );
656
-
657
- await doFile(logger, db, ILalternate, 'alternatenames', 10, (a) => {
613
+ );`);
614
+ await doFile(logger, db, ILalternate, 'alternatenames', 10, a => {
658
615
  const firstchar = a[3][0];
659
616
  if (a[2] === 'he' && (firstchar < '\u05D0' || firstchar > '\u05EA')) {
660
617
  a[2] = 'en';
@@ -682,35 +639,16 @@ async function buildGeonamesSqlite(opts) {
682
639
  });
683
640
 
684
641
  // remove duplicates from alternatenames
685
- doSql(logger, db,
686
- `DROP TABLE IF EXISTS altnames`,
687
-
688
- `CREATE TABLE altnames
642
+ doSql(logger, db, `DROP TABLE IF EXISTS altnames`, `CREATE TABLE altnames
689
643
  AS SELECT geonameid, isolanguage, name
690
644
  FROM alternatenames
691
645
  GROUP BY 1, 2, 3
692
- `,
693
- );
694
-
695
- doSql(logger, db,
696
- `update admin1 set name='',asciiname='' where key like 'PS.%';`,
697
- `update country set country = '' where iso = 'PS';`,
698
- `delete from geoname where geonameid = 7303419;`,
699
- );
700
-
701
- doSql(logger, db,
702
- `DROP TABLE IF EXISTS geoname_fulltext`,
703
-
704
- `CREATE VIRTUAL TABLE geoname_fulltext
646
+ `);
647
+ doSql(logger, db, `update admin1 set name='',asciiname='' where key like 'PS.%';`, `update country set country = '' where iso = 'PS';`, `delete from geoname where geonameid = 7303419;`);
648
+ doSql(logger, db, `DROP TABLE IF EXISTS geoname_fulltext`, `CREATE VIRTUAL TABLE geoname_fulltext
705
649
  USING fts5(geonameid UNINDEXED, longname, population, city, admin1, country);
706
- `,
707
-
708
- `DROP TABLE IF EXISTS geoname_non_ascii`,
709
-
710
- `CREATE TABLE geoname_non_ascii AS
711
- SELECT geonameid FROM geoname WHERE asciiname <> name`,
712
-
713
- `INSERT INTO geoname_fulltext
650
+ `, `DROP TABLE IF EXISTS geoname_non_ascii`, `CREATE TABLE geoname_non_ascii AS
651
+ SELECT geonameid FROM geoname WHERE asciiname <> name`, `INSERT INTO geoname_fulltext
714
652
  SELECT g.geonameid,
715
653
  g.asciiname||', '||a.asciiname||', '||c.Country,
716
654
  g.population,
@@ -721,9 +659,7 @@ async function buildGeonamesSqlite(opts) {
721
659
  AND g.country <> 'IL'
722
660
  AND g.country <> 'GB'
723
661
  AND g.country||'.'||g.admin1 = a.key
724
- `,
725
-
726
- `INSERT INTO geoname_fulltext
662
+ `, `INSERT INTO geoname_fulltext
727
663
  SELECT g.geonameid,
728
664
  g.asciiname||', '||a.asciiname||', USA',
729
665
  g.population,
@@ -731,9 +667,7 @@ async function buildGeonamesSqlite(opts) {
731
667
  FROM geoname g, admin1 a
732
668
  WHERE g.country = 'US'
733
669
  AND g.country||'.'||g.admin1 = a.key
734
- `,
735
-
736
- `INSERT INTO geoname_fulltext
670
+ `, `INSERT INTO geoname_fulltext
737
671
  SELECT g.geonameid,
738
672
  g.asciiname||', '||a.asciiname||', UK',
739
673
  g.population,
@@ -741,18 +675,14 @@ async function buildGeonamesSqlite(opts) {
741
675
  FROM geoname g, admin1 a
742
676
  WHERE g.country = 'GB'
743
677
  AND g.country||'.'||g.admin1 = a.key
744
- `,
745
-
746
- `INSERT INTO geoname_fulltext
678
+ `, `INSERT INTO geoname_fulltext
747
679
  SELECT g.geonameid,
748
680
  g.asciiname||', Israel',
749
681
  g.population,
750
682
  g.asciiname,NULL,'Israel'
751
683
  FROM geoname g
752
684
  WHERE g.country = 'IL'
753
- `,
754
-
755
- `INSERT INTO geoname_fulltext
685
+ `, `INSERT INTO geoname_fulltext
756
686
  SELECT g.geonameid,
757
687
  g.asciiname||', '||c.Country,
758
688
  g.population,
@@ -760,9 +690,7 @@ async function buildGeonamesSqlite(opts) {
760
690
  FROM geoname g, country c
761
691
  WHERE g.country = c.ISO
762
692
  AND (g.admin1 = '' OR g.admin1 = '00')
763
- `,
764
-
765
- `INSERT INTO geoname_fulltext
693
+ `, `INSERT INTO geoname_fulltext
766
694
  SELECT g.geonameid,
767
695
  g.name||', '||a.name||', '||c.Country,
768
696
  g.population,
@@ -771,9 +699,7 @@ async function buildGeonamesSqlite(opts) {
771
699
  WHERE gna.geonameid = g.geonameid
772
700
  AND g.country = c.ISO
773
701
  AND g.country||'.'||g.admin1 = a.key
774
- `,
775
-
776
- `INSERT INTO geoname_fulltext
702
+ `, `INSERT INTO geoname_fulltext
777
703
  SELECT g.geonameid,
778
704
  alt.name||', ישראל',
779
705
  g.population,
@@ -782,9 +708,7 @@ async function buildGeonamesSqlite(opts) {
782
708
  WHERE g.country = 'IL'
783
709
  AND alt.isolanguage = 'he'
784
710
  AND g.geonameid = alt.geonameid
785
- `,
786
-
787
- `INSERT INTO geoname_fulltext
711
+ `, `INSERT INTO geoname_fulltext
788
712
  SELECT g.geonameid,
789
713
  alt.name||', Israel',
790
714
  g.population,
@@ -793,11 +717,7 @@ async function buildGeonamesSqlite(opts) {
793
717
  WHERE g.country = 'IL'
794
718
  AND alt.isolanguage = 'en'
795
719
  AND g.geonameid = alt.geonameid
796
- `,
797
-
798
- 'VACUUM',
799
- );
800
-
720
+ `, 'VACUUM');
801
721
  return new Promise((resolve, reject) => {
802
722
  try {
803
723
  logger.info(`Closing ${dbFilename}`);
@@ -845,11 +765,11 @@ async function doFile(logger, db, infile, tableName, expectedFields, callback) {
845
765
  try {
846
766
  const rl = readline.createInterface({
847
767
  input: fs.createReadStream(infile),
848
- crlfDelay: Infinity,
768
+ crlfDelay: Infinity
849
769
  });
850
770
  let num = 0;
851
771
  let accepted = 0;
852
- rl.on('line', (line) => {
772
+ rl.on('line', line => {
853
773
  num++;
854
774
  if (line[0] == '#') {
855
775
  return;
@@ -868,13 +788,11 @@ async function doFile(logger, db, infile, tableName, expectedFields, callback) {
868
788
  stmt.run(a);
869
789
  accepted++;
870
790
  });
871
-
872
791
  rl.on('close', () => {
873
792
  logger.info(`Inserted ${accepted} / ${num} into ${tableName} from ${infile}`);
874
793
  stmt = null;
875
794
  db.exec('COMMIT');
876
795
  });
877
-
878
796
  return resolve(events.once(rl, 'close'));
879
797
  } catch (err) {
880
798
  logger.error(err);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hebcal/geo-sqlite",
3
- "version": "4.9.1",
3
+ "version": "4.9.3",
4
4
  "author": "Michael J. Radwin (https://github.com/mjradwin)",
5
5
  "keywords": [
6
6
  "hebcal"
@@ -8,9 +8,8 @@
8
8
  "description": "Hebcal ES6 interface to GeoNames and USA ZIP code SQLite databases",
9
9
  "main": "./dist/index.js",
10
10
  "module": "./dist/index.mjs",
11
- "type": "module",
12
11
  "bin": {
13
- "build-geonames-sqlite": "bin/build-geonames-sqlite.cjs",
12
+ "build-geonames-sqlite": "bin/build-geonames-sqlite",
14
13
  "download-and-make-dbs": "bin/download-and-make-dbs"
15
14
  },
16
15
  "repository": {
@@ -31,7 +30,7 @@
31
30
  "dependencies": {
32
31
  "@hebcal/cities": "^3.2.0",
33
32
  "@hebcal/core": "^4.3.0",
34
- "better-sqlite3": "^8.5.1",
33
+ "better-sqlite3": "^8.5.0",
35
34
  "pino": "^8.15.0",
36
35
  "pino-pretty": "^10.2.0",
37
36
  "transliteration": "^2.3.5"
@@ -42,11 +41,18 @@
42
41
  "readme": "npx jsdoc2md dist/index.js",
43
42
  "test": "ava"
44
43
  },
44
+ "ava": {
45
+ "require": ["@babel/register"]
46
+ },
45
47
  "license": "BSD-2-Clause",
46
48
  "devDependencies": {
49
+ "@babel/core": "^7.22.10",
50
+ "@babel/preset-env": "^7.22.10",
51
+ "@babel/register": "^7.22.5",
52
+ "@rollup/plugin-babel": "^6.0.3",
47
53
  "@rollup/plugin-commonjs": "^25.0.4",
48
54
  "@rollup/plugin-json": "^6.0.0",
49
- "@rollup/plugin-node-resolve": "^15.2.0",
55
+ "@rollup/plugin-node-resolve": "^15.1.0",
50
56
  "ava": "^5.3.1",
51
57
  "eslint": "^8.47.0",
52
58
  "eslint-config-google": "^0.14.0",
package/readme.txt DELETED
@@ -1,141 +0,0 @@
1
-
2
- Readme for GeoNames Gazetteer extract files
3
-
4
- ============================================================================================================
5
-
6
- This work is licensed under a Creative Commons Attribution 4.0 License,
7
- see https://creativecommons.org/licenses/by/4.0/
8
- The Data is provided "as is" without warranty or any representation of accuracy, timeliness or completeness.
9
-
10
- The data format is tab-delimited text in utf8 encoding.
11
-
12
-
13
- Files :
14
- -------
15
- XX.zip : features for country with iso code XX, see 'geoname' table for columns. 'no-country' for features not belonging to a country.
16
- allCountries.zip : all countries combined in one file, see 'geoname' table for columns
17
- cities500.zip : all cities with a population > 500 or seats of adm div down to PPLA4 (ca 185.000), see 'geoname' table for columns
18
- cities1000.zip : all cities with a population > 1000 or seats of adm div down to PPLA3 (ca 130.000), see 'geoname' table for columns
19
- cities5000.zip : all cities with a population > 5000 or PPLA (ca 50.000), see 'geoname' table for columns
20
- cities15000.zip : all cities with a population > 15000 or capitals (ca 25.000), see 'geoname' table for columns
21
- alternateNamesV2.zip : alternate names with language codes and geonameId, file with iso language codes, with new columns from and to
22
- alternateNames.zip : obsolete use V2, this file does not have the new columns to and from and will be removed in the future
23
- admin1CodesASCII.txt : names in English for admin divisions. Columns: code, name, name ascii, geonameid
24
- admin2Codes.txt : names for administrative subdivision 'admin2 code' (UTF8), Format : concatenated codes <tab>name <tab> asciiname <tab> geonameId
25
- iso-languagecodes.txt : iso 639 language codes, as used for alternate names in file alternateNames.zip
26
- featureCodes.txt : name and description for feature classes and feature codes
27
- timeZones.txt : countryCode, timezoneId, gmt offset on 1st of January, dst offset to gmt on 1st of July (of the current year), rawOffset without DST
28
- countryInfo.txt : country information : iso codes, fips codes, languages, capital ,...
29
- see the geonames webservices for additional country information,
30
- bounding box : http://api.geonames.org/countryInfo?
31
- country names in different languages : http:/api.geonames.org/countryInfoCSV?lang=it
32
- modifications-<date>.txt : all records modified on the previous day, the date is in yyyy-MM-dd format. You can use this file to daily synchronize your own geonames database.
33
- deletes-<date>.txt : all records deleted on the previous day, format : geonameId <tab> name <tab> comment.
34
-
35
- alternateNamesModifications-<date>.txt : all alternate names modified on the previous day,
36
- alternateNamesDeletes-<date>.txt : all alternate names deleted on the previous day, format : alternateNameId <tab> geonameId <tab> name <tab> comment.
37
- userTags.zip : user tags , format : geonameId <tab> tag.
38
- hierarchy.zip : parentId, childId, type. The type 'ADM' stands for the admin hierarchy modeled by the admin1-4 codes. The other entries are entered with the user interface. The relation toponym-adm hierarchy is not included in the file, it can instead be built from the admincodes of the toponym.
39
- adminCode5.zip : the new adm5 column is not yet exported in the other files (in order to not break import scripts). Instead it is availabe as separate file.
40
- columns: geonameId,adm5code
41
-
42
- The main 'geoname' table has the following fields :
43
- ---------------------------------------------------
44
- geonameid : integer id of record in geonames database
45
- name : name of geographical point (utf8) varchar(200)
46
- asciiname : name of geographical point in plain ascii characters, varchar(200)
47
- alternatenames : alternatenames, comma separated, ascii names automatically transliterated, convenience attribute from alternatename table, varchar(10000)
48
- latitude : latitude in decimal degrees (wgs84)
49
- longitude : longitude in decimal degrees (wgs84)
50
- feature class : see http://www.geonames.org/export/codes.html, char(1)
51
- feature code : see http://www.geonames.org/export/codes.html, varchar(10)
52
- country code : ISO-3166 2-letter country code, 2 characters
53
- cc2 : alternate country codes, comma separated, ISO-3166 2-letter country code, 200 characters
54
- admin1 code : fipscode (subject to change to iso code), see exceptions below, see file admin1Codes.txt for display names of this code; varchar(20)
55
- admin2 code : code for the second administrative division, a county in the US, see file admin2Codes.txt; varchar(80)
56
- admin3 code : code for third level administrative division, varchar(20)
57
- admin4 code : code for fourth level administrative division, varchar(20)
58
- population : bigint (8 byte int)
59
- elevation : in meters, integer
60
- dem : digital elevation model, srtm3 or gtopo30, average elevation of 3''x3'' (ca 90mx90m) or 30''x30'' (ca 900mx900m) area in meters, integer. srtm processed by cgiar/ciat.
61
- timezone : the iana timezone id (see file timeZone.txt) varchar(40)
62
- modification date : date of last modification in yyyy-MM-dd format
63
-
64
-
65
- AdminCodes:
66
- Most adm1 are FIPS codes. ISO codes are used for US, CH, BE and ME. UK and Greece are using an additional level between country and fips code. The code '00' stands for general features where no specific adm1 code is defined.
67
- The corresponding admin feature is found with the same countrycode and adminX codes and the respective feature code ADMx.
68
-
69
-
70
-
71
- The table 'alternate names' :
72
- -----------------------------
73
- alternateNameId : the id of this alternate name, int
74
- geonameid : geonameId referring to id in table 'geoname', int
75
- isolanguage : iso 639 language code 2- or 3-characters; 4-characters 'post' for postal codes and 'iata','icao' and faac for airport codes, fr_1793 for French Revolution names, abbr for abbreviation, link to a website (mostly to wikipedia), wkdt for the wikidataid, varchar(7)
76
- alternate name : alternate name or name variant, varchar(400)
77
- isPreferredName : '1', if this alternate name is an official/preferred name
78
- isShortName : '1', if this is a short name like 'California' for 'State of California'
79
- isColloquial : '1', if this alternate name is a colloquial or slang term. Example: 'Big Apple' for 'New York'.
80
- isHistoric : '1', if this alternate name is historic and was used in the past. Example 'Bombay' for 'Mumbai'.
81
- from : from period when the name was used
82
- to : to period when the name was used
83
-
84
- Remark : the field 'alternatenames' in the table 'geoname' is a short version of the 'alternatenames' table without links and postal codes but with ascii transliterations. You probably don't need both.
85
- If you don't need to know the language of a name variant, the field 'alternatenames' will be sufficient. If you need to know the language
86
- of a name variant, then you will need to load the table 'alternatenames' and you can drop the column in the geoname table.
87
-
88
-
89
-
90
-
91
- Boundaries:
92
- Simplified country boundaries are available in two slightly different formats:
93
- shapes_simplified_low:
94
- geonameId: The geonameId of the feature
95
- geoJson: The boundary in geoJson format
96
-
97
- shapes_simplified_low.json:
98
- similar to the abovementioned file, but fully in geojson format. The geonameId is a feature property in the geojson string.
99
-
100
-
101
- Statistics on the number of features per country and the feature class and code distributions : http://www.geonames.org/statistics/
102
-
103
-
104
- Continent codes :
105
- AF : Africa geonameId=6255146
106
- AS : Asia geonameId=6255147
107
- EU : Europe geonameId=6255148
108
- NA : North America geonameId=6255149
109
- OC : Oceania geonameId=6255151
110
- SA : South America geonameId=6255150
111
- AN : Antarctica geonameId=6255152
112
-
113
-
114
- feature classes:
115
- A: country, state, region,...
116
- H: stream, lake, ...
117
- L: parks,area, ...
118
- P: city, village,...
119
- R: road, railroad
120
- S: spot, building, farm
121
- T: mountain,hill,rock,...
122
- U: undersea
123
- V: forest,heath,...
124
-
125
-
126
- If you find errors or miss important places, please do use the wiki-style edit interface on our website
127
- https://www.geonames.org to correct inaccuracies and to add new records.
128
- Thanks in the name of the geonames community for your valuable contribution.
129
-
130
- Data Sources:
131
- https://www.geonames.org/data-sources.html
132
-
133
-
134
- More Information is also available in the geonames faq :
135
-
136
- https://forum.geonames.org/gforum/forums/show/6.page
137
-
138
- The forum : https://forum.geonames.org
139
-
140
- or the google group : https://groups.google.com/group/geonames
141
-