@hebcal/geo-sqlite 4.9.2 → 4.10.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/dist/index.js +820 -0
- package/dist/index.mjs +63 -132
- package/package.json +20 -13
- package/zips-dummy.sql +1 -0
- package/readme.txt +0 -141
- /package/bin/{build-geonames-sqlite.cjs → build-geonames-sqlite} +0 -0
package/dist/index.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! @hebcal/geo-sqlite v4.
|
|
1
|
+
/*! @hebcal/geo-sqlite v4.10.0 */
|
|
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
|
|
@@ -31,13 +28,13 @@ const GEONAME_SQL = `SELECT
|
|
|
31
28
|
g.latitude as latitude,
|
|
32
29
|
g.longitude as longitude,
|
|
33
30
|
g.population as population,
|
|
31
|
+
g.gtopo30 as elevation,
|
|
34
32
|
g.timezone as timezone
|
|
35
33
|
FROM geoname g
|
|
36
34
|
LEFT JOIN country c on g.country = c.iso
|
|
37
35
|
LEFT JOIN admin1 a on g.country||'.'||g.admin1 = a.key
|
|
38
36
|
WHERE g.geonameid = ?
|
|
39
37
|
`;
|
|
40
|
-
|
|
41
38
|
const GEONAME_ALL_SQL = `SELECT
|
|
42
39
|
g.geonameid as geonameid,
|
|
43
40
|
g.name as name,
|
|
@@ -48,38 +45,33 @@ const GEONAME_ALL_SQL = `SELECT
|
|
|
48
45
|
g.latitude as latitude,
|
|
49
46
|
g.longitude as longitude,
|
|
50
47
|
g.population as population,
|
|
48
|
+
g.gtopo30 as elevation,
|
|
51
49
|
g.timezone as timezone
|
|
52
50
|
FROM geoname g
|
|
53
51
|
LEFT JOIN country c on g.country = c.iso
|
|
54
52
|
LEFT JOIN admin1 a on g.country||'.'||g.admin1 = a.key
|
|
55
53
|
`;
|
|
56
|
-
|
|
57
|
-
|
|
54
|
+
const ZIPCODE_SQL = `SELECT ZipCode,CityMixedCase,State,Latitude,Longitude,Elevation,
|
|
55
|
+
TimeZone,DayLightSaving,Population
|
|
58
56
|
FROM ZIPCodes_Primary WHERE ZipCode = ?`;
|
|
59
|
-
|
|
60
|
-
|
|
57
|
+
const ZIPCODE_ALL_SQL = `SELECT ZipCode,CityMixedCase,State,Latitude,Longitude,Elevation,
|
|
58
|
+
TimeZone,DayLightSaving,Population
|
|
61
59
|
FROM ZIPCodes_Primary`;
|
|
62
|
-
|
|
63
60
|
const ZIP_COMPLETE_SQL = `SELECT ZipCode,CityMixedCase,State,Latitude,Longitude,TimeZone,DayLightSaving,Population
|
|
64
61
|
FROM ZIPCodes_Primary
|
|
65
62
|
WHERE ZipCode LIKE ?
|
|
66
63
|
ORDER BY Population DESC
|
|
67
64
|
LIMIT 10`;
|
|
68
|
-
|
|
69
|
-
const ZIP_FULLTEXT_COMPLETE_SQL =
|
|
70
|
-
`SELECT ZipCode
|
|
65
|
+
const ZIP_FULLTEXT_COMPLETE_SQL = `SELECT ZipCode
|
|
71
66
|
FROM ZIPCodes_CityFullText5
|
|
72
67
|
WHERE ZIPCodes_CityFullText5 MATCH ?
|
|
73
68
|
ORDER BY Population DESC
|
|
74
69
|
LIMIT 20`;
|
|
75
|
-
|
|
76
|
-
const GEONAME_COMPLETE_SQL =
|
|
77
|
-
`SELECT geonameid, longname, city, admin1, country
|
|
70
|
+
const GEONAME_COMPLETE_SQL = `SELECT geonameid, longname, city, admin1, country
|
|
78
71
|
FROM geoname_fulltext
|
|
79
72
|
WHERE geoname_fulltext MATCH ?
|
|
80
73
|
ORDER BY population DESC
|
|
81
74
|
LIMIT 20`;
|
|
82
|
-
|
|
83
75
|
const stateNames = {
|
|
84
76
|
'AK': 'Alaska',
|
|
85
77
|
'AL': 'Alabama',
|
|
@@ -131,7 +123,7 @@ const stateNames = {
|
|
|
131
123
|
'WA': 'Washington',
|
|
132
124
|
'WI': 'Wisconsin',
|
|
133
125
|
'WV': 'West Virginia',
|
|
134
|
-
'WY': 'Wyoming'
|
|
126
|
+
'WY': 'Wyoming'
|
|
135
127
|
};
|
|
136
128
|
|
|
137
129
|
/** Wrapper around sqlite databases */
|
|
@@ -144,9 +136,13 @@ class GeoDb {
|
|
|
144
136
|
constructor(logger, zipsFilename, geonamesFilename) {
|
|
145
137
|
this.logger = logger;
|
|
146
138
|
if (logger) logger.info(`GeoDb: opening ${zipsFilename}...`);
|
|
147
|
-
this.zipsDb = new Database(zipsFilename, {
|
|
139
|
+
this.zipsDb = new Database(zipsFilename, {
|
|
140
|
+
fileMustExist: true
|
|
141
|
+
});
|
|
148
142
|
if (logger) logger.info(`GeoDb: opening ${geonamesFilename}...`);
|
|
149
|
-
this.geonamesDb = new Database(geonamesFilename, {
|
|
143
|
+
this.geonamesDb = new Database(geonamesFilename, {
|
|
144
|
+
fileMustExist: true
|
|
145
|
+
});
|
|
150
146
|
this.zipStmt = this.zipsDb.prepare(ZIPCODE_SQL);
|
|
151
147
|
/** @type {Map<string, Location>} */
|
|
152
148
|
this.zipCache = new Map();
|
|
@@ -222,6 +218,9 @@ class GeoDb {
|
|
|
222
218
|
location.geo = 'zip';
|
|
223
219
|
location.zip = zip;
|
|
224
220
|
location.population = result.Population;
|
|
221
|
+
if (result.Elevation) {
|
|
222
|
+
location.elevation = result.Elevation;
|
|
223
|
+
}
|
|
225
224
|
return location;
|
|
226
225
|
}
|
|
227
226
|
|
|
@@ -292,15 +291,7 @@ class GeoDb {
|
|
|
292
291
|
const country = result.country || '';
|
|
293
292
|
const admin1 = result.admin1 || '';
|
|
294
293
|
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
|
-
);
|
|
294
|
+
const location = new Location(result.latitude, result.longitude, result.cc == 'IL', result.timezone, cityDescr, result.cc, geonameid);
|
|
304
295
|
location.geo = 'geoname';
|
|
305
296
|
location.geonameid = geonameid;
|
|
306
297
|
location.asciiname = result.asciiname;
|
|
@@ -313,6 +304,9 @@ class GeoDb {
|
|
|
313
304
|
if (result.population) {
|
|
314
305
|
location.population = result.population;
|
|
315
306
|
}
|
|
307
|
+
if (result.elevation) {
|
|
308
|
+
location.elevation = result.elevation;
|
|
309
|
+
}
|
|
316
310
|
return location;
|
|
317
311
|
}
|
|
318
312
|
|
|
@@ -352,8 +346,11 @@ class GeoDb {
|
|
|
352
346
|
longitude: res.Longitude,
|
|
353
347
|
timezone: Location.getUsaTzid(res.State, res.TimeZone, res.DayLightSaving),
|
|
354
348
|
population: res.Population,
|
|
355
|
-
geo: 'zip'
|
|
349
|
+
geo: 'zip'
|
|
356
350
|
};
|
|
351
|
+
if (res.Elevation) {
|
|
352
|
+
obj.elevation = res.Elevation;
|
|
353
|
+
}
|
|
357
354
|
return obj;
|
|
358
355
|
}
|
|
359
356
|
|
|
@@ -363,7 +360,7 @@ class GeoDb {
|
|
|
363
360
|
* @param {boolean} latlong
|
|
364
361
|
* @return {Object[]}
|
|
365
362
|
*/
|
|
366
|
-
autoComplete(qraw, latlong=false) {
|
|
363
|
+
autoComplete(qraw, latlong = false) {
|
|
367
364
|
qraw = qraw.trim();
|
|
368
365
|
if (qraw.length === 0) {
|
|
369
366
|
return [];
|
|
@@ -390,7 +387,7 @@ class GeoDb {
|
|
|
390
387
|
geoRows.push(row);
|
|
391
388
|
}
|
|
392
389
|
}
|
|
393
|
-
const geoMatches = geoRows.map(
|
|
390
|
+
const geoMatches = geoRows.map(res => {
|
|
394
391
|
const loc = this.lookupGeoname(res.geonameid);
|
|
395
392
|
return this.geonameLocToAutocomplete(loc, res);
|
|
396
393
|
});
|
|
@@ -398,7 +395,7 @@ class GeoDb {
|
|
|
398
395
|
this.zipFulltextCompStmt = this.zipsDb.prepare(ZIP_FULLTEXT_COMPLETE_SQL);
|
|
399
396
|
}
|
|
400
397
|
const zipRows = this.zipFulltextCompStmt.all(`{longname} : "${qraw}" *`);
|
|
401
|
-
const zipMatches = zipRows.map(
|
|
398
|
+
const zipMatches = zipRows.map(res => {
|
|
402
399
|
const loc = this.lookupZip(res.ZipCode);
|
|
403
400
|
return GeoDb.zipLocToAutocomplete(loc);
|
|
404
401
|
});
|
|
@@ -436,7 +433,7 @@ class GeoDb {
|
|
|
436
433
|
latitude: loc.latitude,
|
|
437
434
|
longitude: loc.longitude,
|
|
438
435
|
timezone: loc.getTzid(),
|
|
439
|
-
geo: 'geoname'
|
|
436
|
+
geo: 'geoname'
|
|
440
437
|
};
|
|
441
438
|
if (loc.population) {
|
|
442
439
|
obj.population = loc.population;
|
|
@@ -473,7 +470,7 @@ class GeoDb {
|
|
|
473
470
|
longitude: loc.longitude,
|
|
474
471
|
timezone: loc.getTzid(),
|
|
475
472
|
population: loc.population,
|
|
476
|
-
geo: 'zip'
|
|
473
|
+
geo: 'zip'
|
|
477
474
|
};
|
|
478
475
|
}
|
|
479
476
|
|
|
@@ -549,11 +546,7 @@ async function buildGeonamesSqlite(opts) {
|
|
|
549
546
|
logger.info(`Opening ${dbFilename}`);
|
|
550
547
|
const db = new Database(dbFilename);
|
|
551
548
|
db.pragma('journal_mode = MEMORY');
|
|
552
|
-
|
|
553
|
-
doSql(logger, db,
|
|
554
|
-
`DROP TABLE IF EXISTS country`,
|
|
555
|
-
|
|
556
|
-
`CREATE TABLE country (
|
|
549
|
+
doSql(logger, db, `DROP TABLE IF EXISTS country`, `CREATE TABLE country (
|
|
557
550
|
ISO TEXT PRIMARY KEY,
|
|
558
551
|
ISO3 TEXT NOT NULL,
|
|
559
552
|
IsoNumeric TEXT NOT NULL,
|
|
@@ -573,14 +566,9 @@ async function buildGeonamesSqlite(opts) {
|
|
|
573
566
|
geonameid INT NOT NULL,
|
|
574
567
|
neighbours TEXT NOT NULL,
|
|
575
568
|
EquivalentFipsCode TEXT NOT NULL
|
|
576
|
-
)
|
|
577
|
-
);
|
|
569
|
+
);`);
|
|
578
570
|
await doFile(logger, db, countryInfotxt, 'country', 19);
|
|
579
|
-
|
|
580
|
-
doSql(logger, db,
|
|
581
|
-
`DROP TABLE IF EXISTS geoname`,
|
|
582
|
-
|
|
583
|
-
`CREATE TABLE geoname (
|
|
571
|
+
doSql(logger, db, `DROP TABLE IF EXISTS geoname`, `CREATE TABLE geoname (
|
|
584
572
|
geonameid int PRIMARY KEY,
|
|
585
573
|
name nvarchar(200),
|
|
586
574
|
asciiname nvarchar(200),
|
|
@@ -599,48 +587,32 @@ async function buildGeonamesSqlite(opts) {
|
|
|
599
587
|
elevation int,
|
|
600
588
|
gtopo30 int,
|
|
601
589
|
timezone nvarchar(40),
|
|
602
|
-
moddate date)
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
const truncateAlternateNames = (a) => {
|
|
590
|
+
moddate date);`);
|
|
591
|
+
const truncateAlternateNames = a => {
|
|
606
592
|
a[3] = '';
|
|
607
593
|
return true;
|
|
608
594
|
};
|
|
609
595
|
await doFile(logger, db, cities5000txt, 'geoname', 19, truncateAlternateNames);
|
|
610
596
|
await doFile(logger, db, citiesPatch, 'geoname', 19, truncateAlternateNames);
|
|
611
|
-
await doFile(logger, db, ILtxt, 'geoname', 19,
|
|
597
|
+
await doFile(logger, db, ILtxt, 'geoname', 19, a => {
|
|
612
598
|
a[3] = '';
|
|
613
599
|
return a[6] == 'P' && (a[7] == 'PPL' || a[7] == 'STLMT');
|
|
614
600
|
});
|
|
615
|
-
|
|
616
|
-
doSql(logger, db,
|
|
617
|
-
`DROP TABLE IF EXISTS admin1`,
|
|
618
|
-
|
|
619
|
-
`CREATE TABLE admin1 (
|
|
601
|
+
doSql(logger, db, `DROP TABLE IF EXISTS admin1`, `CREATE TABLE admin1 (
|
|
620
602
|
key TEXT PRIMARY KEY,
|
|
621
603
|
name nvarchar(200) NOT NULL,
|
|
622
604
|
asciiname nvarchar(200) NOT NULL,
|
|
623
605
|
geonameid int NOT NULL
|
|
624
|
-
)
|
|
625
|
-
);
|
|
626
|
-
|
|
606
|
+
);`);
|
|
627
607
|
await doFile(logger, db, admin1CodesASCIItxt, 'admin1', 4);
|
|
628
608
|
|
|
629
609
|
// fix inconsistencies with the USA capitol
|
|
630
|
-
doSql(logger, db,
|
|
631
|
-
`UPDATE geoname
|
|
610
|
+
doSql(logger, db, `UPDATE geoname
|
|
632
611
|
SET name = 'Washington, D.C.', asciiname = 'Washington, D.C.'
|
|
633
|
-
WHERE geonameid = 4140963;`,
|
|
634
|
-
|
|
635
|
-
`UPDATE admin1
|
|
612
|
+
WHERE geonameid = 4140963;`, `UPDATE admin1
|
|
636
613
|
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 (
|
|
614
|
+
WHERE key = 'US.DC';`);
|
|
615
|
+
doSql(logger, db, `DROP TABLE IF EXISTS alternatenames`, `CREATE TABLE alternatenames (
|
|
644
616
|
id int PRIMARY KEY,
|
|
645
617
|
geonameid int NOT NULL,
|
|
646
618
|
isolanguage varchar(7),
|
|
@@ -651,10 +623,8 @@ async function buildGeonamesSqlite(opts) {
|
|
|
651
623
|
isHistoric tinyint,
|
|
652
624
|
periodFrom NULL,
|
|
653
625
|
periodTo NULL
|
|
654
|
-
)
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
await doFile(logger, db, ILalternate, 'alternatenames', 10, (a) => {
|
|
626
|
+
);`);
|
|
627
|
+
await doFile(logger, db, ILalternate, 'alternatenames', 10, a => {
|
|
658
628
|
const firstchar = a[3][0];
|
|
659
629
|
if (a[2] === 'he' && (firstchar < '\u05D0' || firstchar > '\u05EA')) {
|
|
660
630
|
a[2] = 'en';
|
|
@@ -682,35 +652,16 @@ async function buildGeonamesSqlite(opts) {
|
|
|
682
652
|
});
|
|
683
653
|
|
|
684
654
|
// remove duplicates from alternatenames
|
|
685
|
-
doSql(logger, db,
|
|
686
|
-
`DROP TABLE IF EXISTS altnames`,
|
|
687
|
-
|
|
688
|
-
`CREATE TABLE altnames
|
|
655
|
+
doSql(logger, db, `DROP TABLE IF EXISTS altnames`, `CREATE TABLE altnames
|
|
689
656
|
AS SELECT geonameid, isolanguage, name
|
|
690
657
|
FROM alternatenames
|
|
691
658
|
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
|
|
659
|
+
`);
|
|
660
|
+
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;`);
|
|
661
|
+
doSql(logger, db, `DROP TABLE IF EXISTS geoname_fulltext`, `CREATE VIRTUAL TABLE geoname_fulltext
|
|
705
662
|
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
|
|
663
|
+
`, `DROP TABLE IF EXISTS geoname_non_ascii`, `CREATE TABLE geoname_non_ascii AS
|
|
664
|
+
SELECT geonameid FROM geoname WHERE asciiname <> name`, `INSERT INTO geoname_fulltext
|
|
714
665
|
SELECT g.geonameid,
|
|
715
666
|
g.asciiname||', '||a.asciiname||', '||c.Country,
|
|
716
667
|
g.population,
|
|
@@ -721,9 +672,7 @@ async function buildGeonamesSqlite(opts) {
|
|
|
721
672
|
AND g.country <> 'IL'
|
|
722
673
|
AND g.country <> 'GB'
|
|
723
674
|
AND g.country||'.'||g.admin1 = a.key
|
|
724
|
-
`,
|
|
725
|
-
|
|
726
|
-
`INSERT INTO geoname_fulltext
|
|
675
|
+
`, `INSERT INTO geoname_fulltext
|
|
727
676
|
SELECT g.geonameid,
|
|
728
677
|
g.asciiname||', '||a.asciiname||', USA',
|
|
729
678
|
g.population,
|
|
@@ -731,9 +680,7 @@ async function buildGeonamesSqlite(opts) {
|
|
|
731
680
|
FROM geoname g, admin1 a
|
|
732
681
|
WHERE g.country = 'US'
|
|
733
682
|
AND g.country||'.'||g.admin1 = a.key
|
|
734
|
-
`,
|
|
735
|
-
|
|
736
|
-
`INSERT INTO geoname_fulltext
|
|
683
|
+
`, `INSERT INTO geoname_fulltext
|
|
737
684
|
SELECT g.geonameid,
|
|
738
685
|
g.asciiname||', '||a.asciiname||', UK',
|
|
739
686
|
g.population,
|
|
@@ -741,18 +688,14 @@ async function buildGeonamesSqlite(opts) {
|
|
|
741
688
|
FROM geoname g, admin1 a
|
|
742
689
|
WHERE g.country = 'GB'
|
|
743
690
|
AND g.country||'.'||g.admin1 = a.key
|
|
744
|
-
`,
|
|
745
|
-
|
|
746
|
-
`INSERT INTO geoname_fulltext
|
|
691
|
+
`, `INSERT INTO geoname_fulltext
|
|
747
692
|
SELECT g.geonameid,
|
|
748
693
|
g.asciiname||', Israel',
|
|
749
694
|
g.population,
|
|
750
695
|
g.asciiname,NULL,'Israel'
|
|
751
696
|
FROM geoname g
|
|
752
697
|
WHERE g.country = 'IL'
|
|
753
|
-
`,
|
|
754
|
-
|
|
755
|
-
`INSERT INTO geoname_fulltext
|
|
698
|
+
`, `INSERT INTO geoname_fulltext
|
|
756
699
|
SELECT g.geonameid,
|
|
757
700
|
g.asciiname||', '||c.Country,
|
|
758
701
|
g.population,
|
|
@@ -760,9 +703,7 @@ async function buildGeonamesSqlite(opts) {
|
|
|
760
703
|
FROM geoname g, country c
|
|
761
704
|
WHERE g.country = c.ISO
|
|
762
705
|
AND (g.admin1 = '' OR g.admin1 = '00')
|
|
763
|
-
`,
|
|
764
|
-
|
|
765
|
-
`INSERT INTO geoname_fulltext
|
|
706
|
+
`, `INSERT INTO geoname_fulltext
|
|
766
707
|
SELECT g.geonameid,
|
|
767
708
|
g.name||', '||a.name||', '||c.Country,
|
|
768
709
|
g.population,
|
|
@@ -771,9 +712,7 @@ async function buildGeonamesSqlite(opts) {
|
|
|
771
712
|
WHERE gna.geonameid = g.geonameid
|
|
772
713
|
AND g.country = c.ISO
|
|
773
714
|
AND g.country||'.'||g.admin1 = a.key
|
|
774
|
-
`,
|
|
775
|
-
|
|
776
|
-
`INSERT INTO geoname_fulltext
|
|
715
|
+
`, `INSERT INTO geoname_fulltext
|
|
777
716
|
SELECT g.geonameid,
|
|
778
717
|
alt.name||', ישראל',
|
|
779
718
|
g.population,
|
|
@@ -782,9 +721,7 @@ async function buildGeonamesSqlite(opts) {
|
|
|
782
721
|
WHERE g.country = 'IL'
|
|
783
722
|
AND alt.isolanguage = 'he'
|
|
784
723
|
AND g.geonameid = alt.geonameid
|
|
785
|
-
`,
|
|
786
|
-
|
|
787
|
-
`INSERT INTO geoname_fulltext
|
|
724
|
+
`, `INSERT INTO geoname_fulltext
|
|
788
725
|
SELECT g.geonameid,
|
|
789
726
|
alt.name||', Israel',
|
|
790
727
|
g.population,
|
|
@@ -793,11 +730,7 @@ async function buildGeonamesSqlite(opts) {
|
|
|
793
730
|
WHERE g.country = 'IL'
|
|
794
731
|
AND alt.isolanguage = 'en'
|
|
795
732
|
AND g.geonameid = alt.geonameid
|
|
796
|
-
`,
|
|
797
|
-
|
|
798
|
-
'VACUUM',
|
|
799
|
-
);
|
|
800
|
-
|
|
733
|
+
`, 'VACUUM');
|
|
801
734
|
return new Promise((resolve, reject) => {
|
|
802
735
|
try {
|
|
803
736
|
logger.info(`Closing ${dbFilename}`);
|
|
@@ -845,11 +778,11 @@ async function doFile(logger, db, infile, tableName, expectedFields, callback) {
|
|
|
845
778
|
try {
|
|
846
779
|
const rl = readline.createInterface({
|
|
847
780
|
input: fs.createReadStream(infile),
|
|
848
|
-
crlfDelay: Infinity
|
|
781
|
+
crlfDelay: Infinity
|
|
849
782
|
});
|
|
850
783
|
let num = 0;
|
|
851
784
|
let accepted = 0;
|
|
852
|
-
rl.on('line',
|
|
785
|
+
rl.on('line', line => {
|
|
853
786
|
num++;
|
|
854
787
|
if (line[0] == '#') {
|
|
855
788
|
return;
|
|
@@ -868,13 +801,11 @@ async function doFile(logger, db, infile, tableName, expectedFields, callback) {
|
|
|
868
801
|
stmt.run(a);
|
|
869
802
|
accepted++;
|
|
870
803
|
});
|
|
871
|
-
|
|
872
804
|
rl.on('close', () => {
|
|
873
805
|
logger.info(`Inserted ${accepted} / ${num} into ${tableName} from ${infile}`);
|
|
874
806
|
stmt = null;
|
|
875
807
|
db.exec('COMMIT');
|
|
876
808
|
});
|
|
877
|
-
|
|
878
809
|
return resolve(events.once(rl, 'close'));
|
|
879
810
|
} catch (err) {
|
|
880
811
|
logger.error(err);
|
package/package.json
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hebcal/geo-sqlite",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.10.0",
|
|
4
4
|
"author": "Michael J. Radwin (https://github.com/mjradwin)",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"hebcal"
|
|
7
7
|
],
|
|
8
8
|
"description": "Hebcal ES6 interface to GeoNames and USA ZIP code SQLite databases",
|
|
9
|
+
"main": "./dist/index.js",
|
|
9
10
|
"module": "./dist/index.mjs",
|
|
10
|
-
"type": "module",
|
|
11
11
|
"bin": {
|
|
12
|
-
"build-geonames-sqlite": "bin/build-geonames-sqlite
|
|
12
|
+
"build-geonames-sqlite": "bin/build-geonames-sqlite",
|
|
13
13
|
"download-and-make-dbs": "bin/download-and-make-dbs"
|
|
14
14
|
},
|
|
15
15
|
"repository": {
|
|
@@ -28,11 +28,11 @@
|
|
|
28
28
|
"geo-sqlite.d.ts"
|
|
29
29
|
],
|
|
30
30
|
"dependencies": {
|
|
31
|
-
"@hebcal/cities": "^3.2.
|
|
32
|
-
"@hebcal/core": "^4.
|
|
33
|
-
"better-sqlite3": "^
|
|
34
|
-
"pino": "^8.
|
|
35
|
-
"pino-pretty": "^10.2.
|
|
31
|
+
"@hebcal/cities": "^3.2.2",
|
|
32
|
+
"@hebcal/core": "^4.5.1",
|
|
33
|
+
"better-sqlite3": "^9.1.1",
|
|
34
|
+
"pino": "^8.16.1",
|
|
35
|
+
"pino-pretty": "^10.2.3",
|
|
36
36
|
"transliteration": "^2.3.5"
|
|
37
37
|
},
|
|
38
38
|
"scripts": {
|
|
@@ -41,16 +41,23 @@
|
|
|
41
41
|
"readme": "npx jsdoc2md dist/index.js",
|
|
42
42
|
"test": "ava"
|
|
43
43
|
},
|
|
44
|
+
"ava": {
|
|
45
|
+
"require": ["@babel/register"]
|
|
46
|
+
},
|
|
44
47
|
"license": "BSD-2-Clause",
|
|
45
48
|
"devDependencies": {
|
|
46
|
-
"@
|
|
47
|
-
"@
|
|
48
|
-
"@
|
|
49
|
+
"@babel/core": "^7.23.3",
|
|
50
|
+
"@babel/preset-env": "^7.23.3",
|
|
51
|
+
"@babel/register": "^7.22.15",
|
|
52
|
+
"@rollup/plugin-babel": "^6.0.4",
|
|
53
|
+
"@rollup/plugin-commonjs": "^25.0.7",
|
|
54
|
+
"@rollup/plugin-json": "^6.0.1",
|
|
55
|
+
"@rollup/plugin-node-resolve": "^15.2.3",
|
|
49
56
|
"ava": "^5.3.1",
|
|
50
|
-
"eslint": "^8.
|
|
57
|
+
"eslint": "^8.53.0",
|
|
51
58
|
"eslint-config-google": "^0.14.0",
|
|
52
59
|
"jsdoc": "^4.0.2",
|
|
53
60
|
"jsdoc-to-markdown": "^8.0.0",
|
|
54
|
-
"rollup": "^
|
|
61
|
+
"rollup": "^4.4.0"
|
|
55
62
|
}
|
|
56
63
|
}
|
package/zips-dummy.sql
CHANGED
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
|
-
|
|
File without changes
|