@hebcal/geo-sqlite 3.9.0 → 4.1.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.
@@ -2,21 +2,22 @@
2
2
 
3
3
  const {buildGeonamesSqlite} = require('@hebcal/geo-sqlite');
4
4
 
5
- if (process.argv.length != 8) {
6
- const infiles = 'countryInfo.txt cities5000.txt cities-patch.txt admin1CodesASCII.txt IL.txt';
5
+ const argv = process.argv.slice(2);
6
+ if (argv.length !== 7) {
7
+ const infiles = 'countryInfo.txt cities5000.txt cities-patch.txt admin1CodesASCII.txt IL.txt IL-alternatenames.txt';
7
8
  console.error(`Usage: build-geonames-sqlite geonames.sqlite3 ${infiles}`);
8
9
  process.exit(1);
9
10
  }
10
11
 
11
- const [dbFilename, countryInfo, cities, citiesPatch, admin1CodesASCII, il] = process.argv.slice(2);
12
-
13
- buildGeonamesSqlite(
14
- dbFilename,
15
- countryInfo,
16
- cities,
17
- citiesPatch,
18
- admin1CodesASCII,
19
- il,
20
- ).then(() => {
12
+ const filenames = {
13
+ dbFilename: argv[0],
14
+ countryInfotxt: argv[1],
15
+ cities5000txt: argv[2],
16
+ citiesPatch: argv[3],
17
+ admin1CodesASCIItxt: argv[4],
18
+ ILtxt: argv[5],
19
+ ILalternate: argv[6],
20
+ };
21
+ buildGeonamesSqlite(filenames).then(() => {
21
22
  console.log('Done!');
22
23
  });
@@ -9,9 +9,13 @@ curl -o $TMPDIR/countryInfo.txt http://download.geonames.org/export/dump/country
9
9
  curl -o $TMPDIR/admin1CodesASCII.txt http://download.geonames.org/export/dump/admin1CodesASCII.txt
10
10
  curl -o $TMPDIR/cities5000.zip http://download.geonames.org/export/dump/cities5000.zip
11
11
  curl -o $TMPDIR/IL.zip http://download.geonames.org/export/dump/IL.zip
12
+ curl -o $TMPDIR/alt-IL.zip http://download.geonames.org/export/dump/alternatenames/IL.zip
12
13
 
13
14
  cd $TMPDIR
14
15
  unzip cities5000.zip
16
+ unzip alt-IL.zip
17
+ mv IL.txt alt-IL.txt
18
+ rm readme.txt
15
19
  unzip IL.zip
16
20
 
17
21
  cd $CURDIR
@@ -23,7 +27,8 @@ $CURDIR/node_modules/.bin/build-geonames-sqlite \
23
27
  $TMPDIR/cities5000.txt \
24
28
  "$CURDIR/node_modules/@hebcal/geo-sqlite/cities-patch.txt" \
25
29
  $TMPDIR/admin1CodesASCII.txt \
26
- $TMPDIR/IL.txt
30
+ $TMPDIR/IL.txt \
31
+ $TMPDIR/alt-IL.txt
27
32
 
28
33
  rm -rf $TMPDIR
29
34
 
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- /*! @hebcal/geo-sqlite v3.9.0 */
1
+ /*! @hebcal/geo-sqlite v4.1.0 */
2
2
  'use strict';
3
3
 
4
4
  Object.defineProperty(exports, '__esModule', { value: true });
@@ -446,15 +446,17 @@ class GeoDb {
446
446
 
447
447
  /**
448
448
  * Builds `geonames.sqlite3` from files downloaded from geonames.org
449
- * @param {string} dbFilename
450
- * @param {string} countryInfotxt
451
- * @param {string} cities5000txt
452
- * @param {string} citiesPatch
453
- * @param {string} admin1CodesASCIItxt
454
- * @param {string} ILtxt
449
+ * @param {any} opts
455
450
  */
456
451
 
457
- async function buildGeonamesSqlite(dbFilename, countryInfotxt, cities5000txt, citiesPatch, admin1CodesASCIItxt, ILtxt) {
452
+ async function buildGeonamesSqlite(opts) {
453
+ const dbFilename = opts.dbFilename;
454
+ const countryInfotxt = opts.countryInfotxt;
455
+ const cities5000txt = opts.cities5000txt;
456
+ const citiesPatch = opts.citiesPatch;
457
+ const admin1CodesASCIItxt = opts.admin1CodesASCIItxt;
458
+ const ILtxt = opts.ILtxt;
459
+ const ILalternate = opts.ILalternate;
458
460
  const logger = pino__default["default"]({
459
461
  // level: argv.quiet ? 'warn' : 'info',
460
462
  transport: {
@@ -509,9 +511,16 @@ async function buildGeonamesSqlite(dbFilename, countryInfotxt, cities5000txt, ci
509
511
  gtopo30 int,
510
512
  timezone nvarchar(40),
511
513
  moddate date);`);
512
- await doFile(logger, db, cities5000txt, 'geoname', 19);
513
- await doFile(logger, db, citiesPatch, 'geoname', 19);
514
+
515
+ const truncateAlternateNames = a => {
516
+ a[3] = '';
517
+ return true;
518
+ };
519
+
520
+ await doFile(logger, db, cities5000txt, 'geoname', 19, truncateAlternateNames);
521
+ await doFile(logger, db, citiesPatch, 'geoname', 19, truncateAlternateNames);
514
522
  await doFile(logger, db, ILtxt, 'geoname', 19, a => {
523
+ a[3] = '';
515
524
  return a[6] == 'P' && (a[7] == 'PPL' || a[7] == 'STLMT');
516
525
  });
517
526
  doSql(logger, db, `DROP TABLE IF EXISTS admin1`, `CREATE TABLE admin1 (
@@ -527,8 +536,47 @@ async function buildGeonamesSqlite(dbFilename, countryInfotxt, cities5000txt, ci
527
536
  WHERE geonameid = 4140963;`, `UPDATE admin1
528
537
  SET name = 'Washington, D.C.', asciiname = 'Washington, D.C.'
529
538
  WHERE key = 'US.DC';`);
530
- doSql(logger, db, `DROP TABLE IF EXISTS geoname_he`, `CREATE TABLE geoname_he AS SELECT * FROM geoname LIMIT 0`);
531
- await doFile(logger, db, ILtxt, 'geoname_he', 19, filterPlacesHebrew);
539
+ doSql(logger, db, `DROP TABLE IF EXISTS alternatenames`, `CREATE TABLE alternatenames (
540
+ id int PRIMARY KEY,
541
+ geonameid int NOT NULL,
542
+ isolanguage varchar(7),
543
+ name varchar(400),
544
+ isPreferredName tinyint,
545
+ isShortName tinyint,
546
+ isColloquial tinyint,
547
+ isHistoric tinyint,
548
+ periodFrom NULL,
549
+ periodTo NULL
550
+ );`);
551
+ await doFile(logger, db, ILalternate, 'alternatenames', 10, a => {
552
+ const firstchar = a[3][0];
553
+
554
+ if (a[2] === 'he' && (firstchar < '\u05D0' || firstchar > '\u05EA')) {
555
+ a[2] = 'en';
556
+ }
557
+
558
+ if (a[2] === 'he' || a[2] === 'en') {
559
+ if (a[2] === 'he') {
560
+ a[3] = a[3].replace(/‘/g, '׳');
561
+ a[3] = a[3].replace(/’/g, '׳');
562
+ a[3] = a[3].replace(/\'/g, '׳');
563
+ a[3] = core.Locale.hebrewStripNikkud(a[3]);
564
+ } else {
565
+ a[3] = a[3].replace(/‘/g, '\'');
566
+ a[3] = a[3].replace(/’/g, '\'');
567
+ }
568
+
569
+ return true;
570
+ }
571
+
572
+ return false;
573
+ }); // remove duplicates from alternatenames
574
+
575
+ doSql(logger, db, `DROP TABLE IF EXISTS altnames`, `CREATE TABLE altnames
576
+ AS SELECT geonameid, isolanguage, name
577
+ FROM alternatenames
578
+ GROUP BY 1, 2, 3
579
+ `);
532
580
  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;`);
533
581
  doSql(logger, db, `DROP TABLE IF EXISTS geoname_fulltext`, `CREATE VIRTUAL TABLE geoname_fulltext
534
582
  USING fts3(geonameid int, longname text,
@@ -559,47 +607,32 @@ async function buildGeonamesSqlite(dbFilename, countryInfotxt, cities5000txt, ci
559
607
  AND g.country = c.ISO
560
608
  AND g.country||'.'||g.admin1 = a.key
561
609
  `, `INSERT INTO geoname_fulltext
562
- SELECT g.geonameid, g.name||', ישראל',
563
- g.name, '', 'ישראל',
610
+ SELECT g.geonameid, alt.name||', ישראל',
611
+ alt.name, '', 'ישראל',
564
612
  g.population, g.latitude, g.longitude, g.timezone
565
- FROM geoname_he g, admin1 a, country c
566
- WHERE g.country = c.ISO
567
- AND g.country||'.'||g.admin1 = a.key
613
+ FROM geoname g, altnames alt
614
+ WHERE g.country = 'IL'
615
+ AND alt.isolanguage = 'he'
616
+ AND g.geonameid = alt.geonameid
617
+ `, `INSERT INTO geoname_fulltext
618
+ SELECT g.geonameid, alt.name||', '||a1.asciiname||', Israel',
619
+ alt.name, a1.asciiname, 'Israel',
620
+ g.population, g.latitude, g.longitude, g.timezone
621
+ FROM geoname g, admin1 a1, altnames alt
622
+ WHERE g.country = 'IL'
623
+ AND alt.isolanguage = 'en'
624
+ AND g.geonameid = alt.geonameid
625
+ AND g.country||'.'||g.admin1 = a1.key
568
626
  `);
569
627
  db.close();
570
628
  return Promise.resolve(true);
571
629
  }
572
- /**
573
- * @param {string[]} a
574
- * @return {boolean}
575
- */
576
-
577
- function filterPlacesHebrew(a) {
578
- if (a[6] != 'P' || a[7] != 'PPL' && a[7] != 'STLMT') {
579
- return false;
580
- }
581
-
582
- const alternatenames = a[3].split(',');
583
-
584
- for (const name of alternatenames) {
585
- const firstchar = name[0];
586
-
587
- if (firstchar >= '\u05D0' && firstchar <= '\u05EA') {
588
- a[1] = core.Locale.hebrewStripNikkud(name); // replace 'name' field with Hebrew
589
-
590
- return true;
591
- }
592
- }
593
-
594
- return false;
595
- }
596
630
  /**
597
631
  * @param {pino.Logger} logger
598
632
  * @param {Database} db
599
633
  * @param {...string} sqls
600
634
  */
601
635
 
602
-
603
636
  function doSql(logger, db, ...sqls) {
604
637
  for (let i = 0; i < sqls.length; i++) {
605
638
  logger.info(sqls[i]);
package/dist/index.mjs CHANGED
@@ -1,4 +1,4 @@
1
- /*! @hebcal/geo-sqlite v3.9.0 */
1
+ /*! @hebcal/geo-sqlite v4.1.0 */
2
2
  import Database from 'better-sqlite3';
3
3
  import { Location, Locale } from '@hebcal/core';
4
4
  import '@hebcal/cities';
@@ -434,15 +434,17 @@ class GeoDb {
434
434
 
435
435
  /**
436
436
  * Builds `geonames.sqlite3` from files downloaded from geonames.org
437
- * @param {string} dbFilename
438
- * @param {string} countryInfotxt
439
- * @param {string} cities5000txt
440
- * @param {string} citiesPatch
441
- * @param {string} admin1CodesASCIItxt
442
- * @param {string} ILtxt
437
+ * @param {any} opts
443
438
  */
444
439
 
445
- async function buildGeonamesSqlite(dbFilename, countryInfotxt, cities5000txt, citiesPatch, admin1CodesASCIItxt, ILtxt) {
440
+ async function buildGeonamesSqlite(opts) {
441
+ const dbFilename = opts.dbFilename;
442
+ const countryInfotxt = opts.countryInfotxt;
443
+ const cities5000txt = opts.cities5000txt;
444
+ const citiesPatch = opts.citiesPatch;
445
+ const admin1CodesASCIItxt = opts.admin1CodesASCIItxt;
446
+ const ILtxt = opts.ILtxt;
447
+ const ILalternate = opts.ILalternate;
446
448
  const logger = pino({
447
449
  // level: argv.quiet ? 'warn' : 'info',
448
450
  transport: {
@@ -497,9 +499,16 @@ async function buildGeonamesSqlite(dbFilename, countryInfotxt, cities5000txt, ci
497
499
  gtopo30 int,
498
500
  timezone nvarchar(40),
499
501
  moddate date);`);
500
- await doFile(logger, db, cities5000txt, 'geoname', 19);
501
- await doFile(logger, db, citiesPatch, 'geoname', 19);
502
+
503
+ const truncateAlternateNames = a => {
504
+ a[3] = '';
505
+ return true;
506
+ };
507
+
508
+ await doFile(logger, db, cities5000txt, 'geoname', 19, truncateAlternateNames);
509
+ await doFile(logger, db, citiesPatch, 'geoname', 19, truncateAlternateNames);
502
510
  await doFile(logger, db, ILtxt, 'geoname', 19, a => {
511
+ a[3] = '';
503
512
  return a[6] == 'P' && (a[7] == 'PPL' || a[7] == 'STLMT');
504
513
  });
505
514
  doSql(logger, db, `DROP TABLE IF EXISTS admin1`, `CREATE TABLE admin1 (
@@ -515,8 +524,47 @@ async function buildGeonamesSqlite(dbFilename, countryInfotxt, cities5000txt, ci
515
524
  WHERE geonameid = 4140963;`, `UPDATE admin1
516
525
  SET name = 'Washington, D.C.', asciiname = 'Washington, D.C.'
517
526
  WHERE key = 'US.DC';`);
518
- doSql(logger, db, `DROP TABLE IF EXISTS geoname_he`, `CREATE TABLE geoname_he AS SELECT * FROM geoname LIMIT 0`);
519
- await doFile(logger, db, ILtxt, 'geoname_he', 19, filterPlacesHebrew);
527
+ doSql(logger, db, `DROP TABLE IF EXISTS alternatenames`, `CREATE TABLE alternatenames (
528
+ id int PRIMARY KEY,
529
+ geonameid int NOT NULL,
530
+ isolanguage varchar(7),
531
+ name varchar(400),
532
+ isPreferredName tinyint,
533
+ isShortName tinyint,
534
+ isColloquial tinyint,
535
+ isHistoric tinyint,
536
+ periodFrom NULL,
537
+ periodTo NULL
538
+ );`);
539
+ await doFile(logger, db, ILalternate, 'alternatenames', 10, a => {
540
+ const firstchar = a[3][0];
541
+
542
+ if (a[2] === 'he' && (firstchar < '\u05D0' || firstchar > '\u05EA')) {
543
+ a[2] = 'en';
544
+ }
545
+
546
+ if (a[2] === 'he' || a[2] === 'en') {
547
+ if (a[2] === 'he') {
548
+ a[3] = a[3].replace(/‘/g, '׳');
549
+ a[3] = a[3].replace(/’/g, '׳');
550
+ a[3] = a[3].replace(/\'/g, '׳');
551
+ a[3] = Locale.hebrewStripNikkud(a[3]);
552
+ } else {
553
+ a[3] = a[3].replace(/‘/g, '\'');
554
+ a[3] = a[3].replace(/’/g, '\'');
555
+ }
556
+
557
+ return true;
558
+ }
559
+
560
+ return false;
561
+ }); // remove duplicates from alternatenames
562
+
563
+ doSql(logger, db, `DROP TABLE IF EXISTS altnames`, `CREATE TABLE altnames
564
+ AS SELECT geonameid, isolanguage, name
565
+ FROM alternatenames
566
+ GROUP BY 1, 2, 3
567
+ `);
520
568
  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;`);
521
569
  doSql(logger, db, `DROP TABLE IF EXISTS geoname_fulltext`, `CREATE VIRTUAL TABLE geoname_fulltext
522
570
  USING fts3(geonameid int, longname text,
@@ -547,47 +595,32 @@ async function buildGeonamesSqlite(dbFilename, countryInfotxt, cities5000txt, ci
547
595
  AND g.country = c.ISO
548
596
  AND g.country||'.'||g.admin1 = a.key
549
597
  `, `INSERT INTO geoname_fulltext
550
- SELECT g.geonameid, g.name||', ישראל',
551
- g.name, '', 'ישראל',
598
+ SELECT g.geonameid, alt.name||', ישראל',
599
+ alt.name, '', 'ישראל',
552
600
  g.population, g.latitude, g.longitude, g.timezone
553
- FROM geoname_he g, admin1 a, country c
554
- WHERE g.country = c.ISO
555
- AND g.country||'.'||g.admin1 = a.key
601
+ FROM geoname g, altnames alt
602
+ WHERE g.country = 'IL'
603
+ AND alt.isolanguage = 'he'
604
+ AND g.geonameid = alt.geonameid
605
+ `, `INSERT INTO geoname_fulltext
606
+ SELECT g.geonameid, alt.name||', '||a1.asciiname||', Israel',
607
+ alt.name, a1.asciiname, 'Israel',
608
+ g.population, g.latitude, g.longitude, g.timezone
609
+ FROM geoname g, admin1 a1, altnames alt
610
+ WHERE g.country = 'IL'
611
+ AND alt.isolanguage = 'en'
612
+ AND g.geonameid = alt.geonameid
613
+ AND g.country||'.'||g.admin1 = a1.key
556
614
  `);
557
615
  db.close();
558
616
  return Promise.resolve(true);
559
617
  }
560
- /**
561
- * @param {string[]} a
562
- * @return {boolean}
563
- */
564
-
565
- function filterPlacesHebrew(a) {
566
- if (a[6] != 'P' || a[7] != 'PPL' && a[7] != 'STLMT') {
567
- return false;
568
- }
569
-
570
- const alternatenames = a[3].split(',');
571
-
572
- for (const name of alternatenames) {
573
- const firstchar = name[0];
574
-
575
- if (firstchar >= '\u05D0' && firstchar <= '\u05EA') {
576
- a[1] = Locale.hebrewStripNikkud(name); // replace 'name' field with Hebrew
577
-
578
- return true;
579
- }
580
- }
581
-
582
- return false;
583
- }
584
618
  /**
585
619
  * @param {pino.Logger} logger
586
620
  * @param {Database} db
587
621
  * @param {...string} sqls
588
622
  */
589
623
 
590
-
591
624
  function doSql(logger, db, ...sqls) {
592
625
  for (let i = 0; i < sqls.length; i++) {
593
626
  logger.info(sqls[i]);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hebcal/geo-sqlite",
3
- "version": "3.9.0",
3
+ "version": "4.1.0",
4
4
  "author": "Michael J. Radwin (https://github.com/mjradwin)",
5
5
  "keywords": [
6
6
  "hebcal"
@@ -32,7 +32,7 @@
32
32
  "@hebcal/core": "^3.33.3",
33
33
  "better-sqlite3": "^7.5.0",
34
34
  "pino": "^7.8.0",
35
- "pino-pretty": "^7.5.1"
35
+ "pino-pretty": "^7.5.3"
36
36
  },
37
37
  "scripts": {
38
38
  "build": "rollup -c",
@@ -61,10 +61,10 @@
61
61
  "@rollup/plugin-json": "^4.1.0",
62
62
  "@rollup/plugin-node-resolve": "^13.1.3",
63
63
  "ava": "^4.0.1",
64
- "eslint": "^8.9.0",
64
+ "eslint": "^8.10.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.68.0"
68
+ "rollup": "^2.69.1"
69
69
  }
70
70
  }