@hebcal/geo-sqlite 3.5.0 → 3.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +115 -18
- package/dist/index.mjs +115 -18
- package/package.json +1 -1
- package/zips-dummy.sql +4 -1
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! @hebcal/geo-sqlite v3.
|
|
1
|
+
/*! @hebcal/geo-sqlite v3.7.0 */
|
|
2
2
|
'use strict';
|
|
3
3
|
|
|
4
4
|
Object.defineProperty(exports, '__esModule', { value: true });
|
|
@@ -52,17 +52,76 @@ const ZIPCODE_SQL = `SELECT CityMixedCase,State,Latitude,Longitude,TimeZone,DayL
|
|
|
52
52
|
FROM ZIPCodes_Primary WHERE ZipCode = ?`;
|
|
53
53
|
const ZIPCODE_ALL_SQL = `SELECT ZipCode,CityMixedCase,State,Latitude,Longitude,TimeZone,DayLightSaving
|
|
54
54
|
FROM ZIPCodes_Primary`;
|
|
55
|
-
const ZIP_COMPLETE_SQL = `SELECT ZipCode,CityMixedCase,State,Latitude,Longitude,TimeZone,DayLightSaving
|
|
55
|
+
const ZIP_COMPLETE_SQL = `SELECT ZipCode,CityMixedCase,State,Latitude,Longitude,TimeZone,DayLightSaving,Population
|
|
56
56
|
FROM ZIPCodes_Primary
|
|
57
57
|
WHERE ZipCode LIKE ?
|
|
58
|
+
ORDER BY Population DESC
|
|
58
59
|
LIMIT 10`;
|
|
60
|
+
const ZIP_FULLTEXT_COMPLETE_SQL = `SELECT ZipCode,CityMixedCase,State,Latitude,Longitude,TimeZone,DayLightSaving,Population
|
|
61
|
+
FROM ZIPCodes_CityFullText
|
|
62
|
+
WHERE CityMixedCase MATCH ?
|
|
63
|
+
ORDER BY Population DESC
|
|
64
|
+
LIMIT 15`;
|
|
59
65
|
const GEONAME_COMPLETE_SQL = `SELECT geonameid, asciiname, admin1, country,
|
|
60
66
|
population, latitude, longitude, timezone
|
|
61
67
|
FROM geoname_fulltext
|
|
62
68
|
WHERE longname MATCH ?
|
|
63
69
|
GROUP BY geonameid
|
|
64
70
|
ORDER BY population DESC
|
|
65
|
-
LIMIT
|
|
71
|
+
LIMIT 15`;
|
|
72
|
+
const stateNames = {
|
|
73
|
+
'AK': 'Alaska',
|
|
74
|
+
'AL': 'Alabama',
|
|
75
|
+
'AR': 'Arkansas',
|
|
76
|
+
'AZ': 'Arizona',
|
|
77
|
+
'CA': 'California',
|
|
78
|
+
'CO': 'Colorado',
|
|
79
|
+
'CT': 'Connecticut',
|
|
80
|
+
'DC': 'Washington, D.C.',
|
|
81
|
+
'DE': 'Delaware',
|
|
82
|
+
'FL': 'Florida',
|
|
83
|
+
'GA': 'Georgia',
|
|
84
|
+
'HI': 'Hawaii',
|
|
85
|
+
'IA': 'Iowa',
|
|
86
|
+
'ID': 'Idaho',
|
|
87
|
+
'IL': 'Illinois',
|
|
88
|
+
'IN': 'Indiana',
|
|
89
|
+
'KS': 'Kansas',
|
|
90
|
+
'KY': 'Kentucky',
|
|
91
|
+
'LA': 'Louisiana',
|
|
92
|
+
'MA': 'Massachusetts',
|
|
93
|
+
'MD': 'Maryland',
|
|
94
|
+
'ME': 'Maine',
|
|
95
|
+
'MI': 'Michigan',
|
|
96
|
+
'MN': 'Minnesota',
|
|
97
|
+
'MO': 'Missouri',
|
|
98
|
+
'MS': 'Mississippi',
|
|
99
|
+
'MT': 'Montana',
|
|
100
|
+
'NC': 'North Carolina',
|
|
101
|
+
'ND': 'North Dakota',
|
|
102
|
+
'NE': 'Nebraska',
|
|
103
|
+
'NH': 'New Hampshire',
|
|
104
|
+
'NJ': 'New Jersey',
|
|
105
|
+
'NM': 'New Mexico',
|
|
106
|
+
'NV': 'Nevada',
|
|
107
|
+
'NY': 'New York',
|
|
108
|
+
'OH': 'Ohio',
|
|
109
|
+
'OK': 'Oklahoma',
|
|
110
|
+
'OR': 'Oregon',
|
|
111
|
+
'PA': 'Pennsylvania',
|
|
112
|
+
'RI': 'Rhode Island',
|
|
113
|
+
'SC': 'South Carolina',
|
|
114
|
+
'SD': 'South Dakota',
|
|
115
|
+
'TN': 'Tennessee',
|
|
116
|
+
'TX': 'Texas',
|
|
117
|
+
'UT': 'Utah',
|
|
118
|
+
'VA': 'Virginia',
|
|
119
|
+
'VT': 'Vermont',
|
|
120
|
+
'WA': 'Washington',
|
|
121
|
+
'WI': 'Wisconsin',
|
|
122
|
+
'WV': 'West Virginia',
|
|
123
|
+
'WY': 'Wyoming'
|
|
124
|
+
};
|
|
66
125
|
/** Wrapper around sqlite databases */
|
|
67
126
|
|
|
68
127
|
class GeoDb {
|
|
@@ -217,6 +276,28 @@ class GeoDb {
|
|
|
217
276
|
return null;
|
|
218
277
|
}
|
|
219
278
|
}
|
|
279
|
+
/**
|
|
280
|
+
* @private
|
|
281
|
+
* @param {any[]} res
|
|
282
|
+
* @return {Object[]}
|
|
283
|
+
*/
|
|
284
|
+
|
|
285
|
+
|
|
286
|
+
static zipResultToObj(res) {
|
|
287
|
+
const obj = {
|
|
288
|
+
id: String(res.ZipCode),
|
|
289
|
+
value: `${res.CityMixedCase}, ${res.State} ${res.ZipCode}`,
|
|
290
|
+
admin1: res.State,
|
|
291
|
+
asciiname: res.CityMixedCase,
|
|
292
|
+
country: 'United States',
|
|
293
|
+
latitude: res.Latitude,
|
|
294
|
+
longitude: res.Longitude,
|
|
295
|
+
timezone: core.Location.getUsaTzid(res.State, res.TimeZone, res.DayLightSaving),
|
|
296
|
+
population: res.Population,
|
|
297
|
+
geo: 'zip'
|
|
298
|
+
};
|
|
299
|
+
return obj;
|
|
300
|
+
}
|
|
220
301
|
/**
|
|
221
302
|
* Generates autocomplete results based on a query string
|
|
222
303
|
* @param {string} qraw
|
|
@@ -234,33 +315,23 @@ class GeoDb {
|
|
|
234
315
|
this.zipCompStmt = this.zipsDb.prepare(ZIP_COMPLETE_SQL);
|
|
235
316
|
}
|
|
236
317
|
|
|
237
|
-
return this.zipCompStmt.all(qraw + '%').map(
|
|
238
|
-
const obj = {
|
|
239
|
-
id: String(res.ZipCode),
|
|
240
|
-
value: `${res.CityMixedCase}, ${res.State} ${res.ZipCode}`,
|
|
241
|
-
admin1: res.State,
|
|
242
|
-
asciiname: res.CityMixedCase,
|
|
243
|
-
country: 'United States',
|
|
244
|
-
latitude: res.Latitude,
|
|
245
|
-
longitude: res.Longitude,
|
|
246
|
-
timezone: core.Location.getUsaTzid(res.State, res.TimeZone, res.DayLightSaving),
|
|
247
|
-
geo: 'zip'
|
|
248
|
-
};
|
|
249
|
-
return obj;
|
|
250
|
-
});
|
|
318
|
+
return this.zipCompStmt.all(qraw + '%').map(GeoDb.zipResultToObj);
|
|
251
319
|
} else {
|
|
252
320
|
if (!this.geonamesCompStmt) {
|
|
253
321
|
this.geonamesCompStmt = this.geonamesDb.prepare(GEONAME_COMPLETE_SQL);
|
|
254
322
|
}
|
|
255
323
|
|
|
256
324
|
qraw = qraw.replace(/\"/g, '""');
|
|
257
|
-
|
|
325
|
+
const geoRows = this.geonamesCompStmt.all(`"${qraw}*"`);
|
|
326
|
+
const geoMatches = geoRows.map(res => {
|
|
258
327
|
const country = res.country || '';
|
|
259
328
|
const admin1 = res.admin1 || '';
|
|
260
329
|
const obj = {
|
|
261
330
|
id: res.geonameid,
|
|
262
331
|
value: core.Location.geonameCityDescr(res.asciiname, admin1, country),
|
|
263
332
|
asciiname: res.asciiname,
|
|
333
|
+
admin1,
|
|
334
|
+
country,
|
|
264
335
|
latitude: res.latitude,
|
|
265
336
|
longitude: res.longitude,
|
|
266
337
|
timezone: res.timezone,
|
|
@@ -279,6 +350,32 @@ class GeoDb {
|
|
|
279
350
|
obj.tokens = Array.from(new Set(res.asciiname.split(' ').concat(admin1.split(' '), country.split(' '))));
|
|
280
351
|
return obj;
|
|
281
352
|
});
|
|
353
|
+
|
|
354
|
+
if (!this.zipFulltextCompStmt) {
|
|
355
|
+
this.zipFulltextCompStmt = this.zipsDb.prepare(ZIP_FULLTEXT_COMPLETE_SQL);
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
const zipRows = this.zipFulltextCompStmt.all(`"${qraw}*"`);
|
|
359
|
+
const zipMatches = zipRows.map(GeoDb.zipResultToObj);
|
|
360
|
+
const map = new Map();
|
|
361
|
+
|
|
362
|
+
for (const obj of zipMatches) {
|
|
363
|
+
const key = [obj.asciiname, stateNames[obj.admin1], obj.country].join('|');
|
|
364
|
+
|
|
365
|
+
if (!map.has(key)) {
|
|
366
|
+
map.set(key, obj);
|
|
367
|
+
}
|
|
368
|
+
} // GeoNames takes priority over USA ZIP code matches
|
|
369
|
+
|
|
370
|
+
|
|
371
|
+
for (const obj of geoMatches) {
|
|
372
|
+
const key = [obj.asciiname, obj.admin1, obj.country].join('|');
|
|
373
|
+
map.set(key, obj);
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
const values = Array.from(map.values());
|
|
377
|
+
values.sort((a, b) => b.population - a.population);
|
|
378
|
+
return values.slice(0, 10);
|
|
282
379
|
}
|
|
283
380
|
}
|
|
284
381
|
/** Reads entire ZIP database and caches in-memory */
|
package/dist/index.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! @hebcal/geo-sqlite v3.
|
|
1
|
+
/*! @hebcal/geo-sqlite v3.7.0 */
|
|
2
2
|
import Database from 'better-sqlite3';
|
|
3
3
|
import { Location, Locale } from '@hebcal/core';
|
|
4
4
|
import pino from 'pino';
|
|
@@ -40,17 +40,76 @@ const ZIPCODE_SQL = `SELECT CityMixedCase,State,Latitude,Longitude,TimeZone,DayL
|
|
|
40
40
|
FROM ZIPCodes_Primary WHERE ZipCode = ?`;
|
|
41
41
|
const ZIPCODE_ALL_SQL = `SELECT ZipCode,CityMixedCase,State,Latitude,Longitude,TimeZone,DayLightSaving
|
|
42
42
|
FROM ZIPCodes_Primary`;
|
|
43
|
-
const ZIP_COMPLETE_SQL = `SELECT ZipCode,CityMixedCase,State,Latitude,Longitude,TimeZone,DayLightSaving
|
|
43
|
+
const ZIP_COMPLETE_SQL = `SELECT ZipCode,CityMixedCase,State,Latitude,Longitude,TimeZone,DayLightSaving,Population
|
|
44
44
|
FROM ZIPCodes_Primary
|
|
45
45
|
WHERE ZipCode LIKE ?
|
|
46
|
+
ORDER BY Population DESC
|
|
46
47
|
LIMIT 10`;
|
|
48
|
+
const ZIP_FULLTEXT_COMPLETE_SQL = `SELECT ZipCode,CityMixedCase,State,Latitude,Longitude,TimeZone,DayLightSaving,Population
|
|
49
|
+
FROM ZIPCodes_CityFullText
|
|
50
|
+
WHERE CityMixedCase MATCH ?
|
|
51
|
+
ORDER BY Population DESC
|
|
52
|
+
LIMIT 15`;
|
|
47
53
|
const GEONAME_COMPLETE_SQL = `SELECT geonameid, asciiname, admin1, country,
|
|
48
54
|
population, latitude, longitude, timezone
|
|
49
55
|
FROM geoname_fulltext
|
|
50
56
|
WHERE longname MATCH ?
|
|
51
57
|
GROUP BY geonameid
|
|
52
58
|
ORDER BY population DESC
|
|
53
|
-
LIMIT
|
|
59
|
+
LIMIT 15`;
|
|
60
|
+
const stateNames = {
|
|
61
|
+
'AK': 'Alaska',
|
|
62
|
+
'AL': 'Alabama',
|
|
63
|
+
'AR': 'Arkansas',
|
|
64
|
+
'AZ': 'Arizona',
|
|
65
|
+
'CA': 'California',
|
|
66
|
+
'CO': 'Colorado',
|
|
67
|
+
'CT': 'Connecticut',
|
|
68
|
+
'DC': 'Washington, D.C.',
|
|
69
|
+
'DE': 'Delaware',
|
|
70
|
+
'FL': 'Florida',
|
|
71
|
+
'GA': 'Georgia',
|
|
72
|
+
'HI': 'Hawaii',
|
|
73
|
+
'IA': 'Iowa',
|
|
74
|
+
'ID': 'Idaho',
|
|
75
|
+
'IL': 'Illinois',
|
|
76
|
+
'IN': 'Indiana',
|
|
77
|
+
'KS': 'Kansas',
|
|
78
|
+
'KY': 'Kentucky',
|
|
79
|
+
'LA': 'Louisiana',
|
|
80
|
+
'MA': 'Massachusetts',
|
|
81
|
+
'MD': 'Maryland',
|
|
82
|
+
'ME': 'Maine',
|
|
83
|
+
'MI': 'Michigan',
|
|
84
|
+
'MN': 'Minnesota',
|
|
85
|
+
'MO': 'Missouri',
|
|
86
|
+
'MS': 'Mississippi',
|
|
87
|
+
'MT': 'Montana',
|
|
88
|
+
'NC': 'North Carolina',
|
|
89
|
+
'ND': 'North Dakota',
|
|
90
|
+
'NE': 'Nebraska',
|
|
91
|
+
'NH': 'New Hampshire',
|
|
92
|
+
'NJ': 'New Jersey',
|
|
93
|
+
'NM': 'New Mexico',
|
|
94
|
+
'NV': 'Nevada',
|
|
95
|
+
'NY': 'New York',
|
|
96
|
+
'OH': 'Ohio',
|
|
97
|
+
'OK': 'Oklahoma',
|
|
98
|
+
'OR': 'Oregon',
|
|
99
|
+
'PA': 'Pennsylvania',
|
|
100
|
+
'RI': 'Rhode Island',
|
|
101
|
+
'SC': 'South Carolina',
|
|
102
|
+
'SD': 'South Dakota',
|
|
103
|
+
'TN': 'Tennessee',
|
|
104
|
+
'TX': 'Texas',
|
|
105
|
+
'UT': 'Utah',
|
|
106
|
+
'VA': 'Virginia',
|
|
107
|
+
'VT': 'Vermont',
|
|
108
|
+
'WA': 'Washington',
|
|
109
|
+
'WI': 'Wisconsin',
|
|
110
|
+
'WV': 'West Virginia',
|
|
111
|
+
'WY': 'Wyoming'
|
|
112
|
+
};
|
|
54
113
|
/** Wrapper around sqlite databases */
|
|
55
114
|
|
|
56
115
|
class GeoDb {
|
|
@@ -205,6 +264,28 @@ class GeoDb {
|
|
|
205
264
|
return null;
|
|
206
265
|
}
|
|
207
266
|
}
|
|
267
|
+
/**
|
|
268
|
+
* @private
|
|
269
|
+
* @param {any[]} res
|
|
270
|
+
* @return {Object[]}
|
|
271
|
+
*/
|
|
272
|
+
|
|
273
|
+
|
|
274
|
+
static zipResultToObj(res) {
|
|
275
|
+
const obj = {
|
|
276
|
+
id: String(res.ZipCode),
|
|
277
|
+
value: `${res.CityMixedCase}, ${res.State} ${res.ZipCode}`,
|
|
278
|
+
admin1: res.State,
|
|
279
|
+
asciiname: res.CityMixedCase,
|
|
280
|
+
country: 'United States',
|
|
281
|
+
latitude: res.Latitude,
|
|
282
|
+
longitude: res.Longitude,
|
|
283
|
+
timezone: Location.getUsaTzid(res.State, res.TimeZone, res.DayLightSaving),
|
|
284
|
+
population: res.Population,
|
|
285
|
+
geo: 'zip'
|
|
286
|
+
};
|
|
287
|
+
return obj;
|
|
288
|
+
}
|
|
208
289
|
/**
|
|
209
290
|
* Generates autocomplete results based on a query string
|
|
210
291
|
* @param {string} qraw
|
|
@@ -222,33 +303,23 @@ class GeoDb {
|
|
|
222
303
|
this.zipCompStmt = this.zipsDb.prepare(ZIP_COMPLETE_SQL);
|
|
223
304
|
}
|
|
224
305
|
|
|
225
|
-
return this.zipCompStmt.all(qraw + '%').map(
|
|
226
|
-
const obj = {
|
|
227
|
-
id: String(res.ZipCode),
|
|
228
|
-
value: `${res.CityMixedCase}, ${res.State} ${res.ZipCode}`,
|
|
229
|
-
admin1: res.State,
|
|
230
|
-
asciiname: res.CityMixedCase,
|
|
231
|
-
country: 'United States',
|
|
232
|
-
latitude: res.Latitude,
|
|
233
|
-
longitude: res.Longitude,
|
|
234
|
-
timezone: Location.getUsaTzid(res.State, res.TimeZone, res.DayLightSaving),
|
|
235
|
-
geo: 'zip'
|
|
236
|
-
};
|
|
237
|
-
return obj;
|
|
238
|
-
});
|
|
306
|
+
return this.zipCompStmt.all(qraw + '%').map(GeoDb.zipResultToObj);
|
|
239
307
|
} else {
|
|
240
308
|
if (!this.geonamesCompStmt) {
|
|
241
309
|
this.geonamesCompStmt = this.geonamesDb.prepare(GEONAME_COMPLETE_SQL);
|
|
242
310
|
}
|
|
243
311
|
|
|
244
312
|
qraw = qraw.replace(/\"/g, '""');
|
|
245
|
-
|
|
313
|
+
const geoRows = this.geonamesCompStmt.all(`"${qraw}*"`);
|
|
314
|
+
const geoMatches = geoRows.map(res => {
|
|
246
315
|
const country = res.country || '';
|
|
247
316
|
const admin1 = res.admin1 || '';
|
|
248
317
|
const obj = {
|
|
249
318
|
id: res.geonameid,
|
|
250
319
|
value: Location.geonameCityDescr(res.asciiname, admin1, country),
|
|
251
320
|
asciiname: res.asciiname,
|
|
321
|
+
admin1,
|
|
322
|
+
country,
|
|
252
323
|
latitude: res.latitude,
|
|
253
324
|
longitude: res.longitude,
|
|
254
325
|
timezone: res.timezone,
|
|
@@ -267,6 +338,32 @@ class GeoDb {
|
|
|
267
338
|
obj.tokens = Array.from(new Set(res.asciiname.split(' ').concat(admin1.split(' '), country.split(' '))));
|
|
268
339
|
return obj;
|
|
269
340
|
});
|
|
341
|
+
|
|
342
|
+
if (!this.zipFulltextCompStmt) {
|
|
343
|
+
this.zipFulltextCompStmt = this.zipsDb.prepare(ZIP_FULLTEXT_COMPLETE_SQL);
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
const zipRows = this.zipFulltextCompStmt.all(`"${qraw}*"`);
|
|
347
|
+
const zipMatches = zipRows.map(GeoDb.zipResultToObj);
|
|
348
|
+
const map = new Map();
|
|
349
|
+
|
|
350
|
+
for (const obj of zipMatches) {
|
|
351
|
+
const key = [obj.asciiname, stateNames[obj.admin1], obj.country].join('|');
|
|
352
|
+
|
|
353
|
+
if (!map.has(key)) {
|
|
354
|
+
map.set(key, obj);
|
|
355
|
+
}
|
|
356
|
+
} // GeoNames takes priority over USA ZIP code matches
|
|
357
|
+
|
|
358
|
+
|
|
359
|
+
for (const obj of geoMatches) {
|
|
360
|
+
const key = [obj.asciiname, obj.admin1, obj.country].join('|');
|
|
361
|
+
map.set(key, obj);
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
const values = Array.from(map.values());
|
|
365
|
+
values.sort((a, b) => b.population - a.population);
|
|
366
|
+
return values.slice(0, 10);
|
|
270
367
|
}
|
|
271
368
|
}
|
|
272
369
|
/** Reads entire ZIP database and caches in-memory */
|
package/package.json
CHANGED
package/zips-dummy.sql
CHANGED
|
@@ -6,5 +6,8 @@ CREATE TABLE ZIPCodes_Primary (
|
|
|
6
6
|
Longitude decimal(12, 6),
|
|
7
7
|
TimeZone char(2) NULL,
|
|
8
8
|
DayLightSaving char(1) NULL,
|
|
9
|
-
|
|
9
|
+
Population int NULL
|
|
10
10
|
);
|
|
11
|
+
|
|
12
|
+
CREATE VIRTUAL TABLE ZIPCodes_CityFullText
|
|
13
|
+
USING fts3(ZipCode,CityMixedCase,State,Latitude,Longitude,TimeZone,DayLightSaving,Population);
|