@hebcal/geo-sqlite 3.6.1 → 3.8.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 CHANGED
@@ -1,4 +1,4 @@
1
- /*! @hebcal/geo-sqlite v3.6.0 */
1
+ /*! @hebcal/geo-sqlite v3.8.0 */
2
2
  'use strict';
3
3
 
4
4
  Object.defineProperty(exports, '__esModule', { value: true });
@@ -52,18 +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
58
  ORDER BY Population DESC
59
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`;
60
65
  const GEONAME_COMPLETE_SQL = `SELECT geonameid, asciiname, admin1, country,
61
66
  population, latitude, longitude, timezone
62
67
  FROM geoname_fulltext
63
68
  WHERE longname MATCH ?
64
69
  GROUP BY geonameid
65
70
  ORDER BY population DESC
66
- LIMIT 10`;
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
+ };
67
125
  /** Wrapper around sqlite databases */
68
126
 
69
127
  class GeoDb {
@@ -83,14 +141,32 @@ class GeoDb {
83
141
  fileMustExist: true
84
142
  });
85
143
  this.zipStmt = this.zipsDb.prepare(ZIPCODE_SQL);
144
+ /** @type {Map<string, Location>} */
145
+
86
146
  this.zipCache = new Map();
87
147
  this.geonamesStmt = this.geonamesDb.prepare(GEONAME_SQL);
148
+ /** @type {Map<number, Location>} */
149
+
88
150
  this.geonamesCache = new Map();
151
+ /** @type {Map<string, Location>} */
152
+
89
153
  this.legacyCities = new Map();
90
154
 
91
155
  for (const [name, id] of Object.entries(city2geonameid)) {
92
156
  this.legacyCities.set(GeoDb.munge(name), id);
93
157
  }
158
+
159
+ const stmt = this.geonamesDb.prepare(`SELECT ISO, Country FROM country WHERE Country <> ''`);
160
+ const rows = stmt.all();
161
+ const map = new Map();
162
+
163
+ for (const row of rows) {
164
+ map.set(row.ISO, row.Country);
165
+ }
166
+ /** @type {Map<string, string>} */
167
+
168
+
169
+ this.countryNames = map;
94
170
  }
95
171
  /** Closes database handles */
96
172
 
@@ -116,19 +192,20 @@ class GeoDb {
116
192
 
117
193
 
118
194
  lookupZip(zip) {
119
- const found = this.zipCache.get(zip);
195
+ const zip5 = zip.trim().substring(0, 5);
196
+ const found = this.zipCache.get(zip5);
120
197
  if (typeof found !== 'undefined') return found;
121
- const result = this.zipStmt.get(zip);
198
+ const result = this.zipStmt.get(zip5);
122
199
 
123
200
  if (!result) {
124
- if (this.logger) this.logger.warn(`GeoDb: unknown zipcode=${zip}`);
125
- this.zipCache.set(zip, null);
201
+ if (this.logger) this.logger.warn(`GeoDb: unknown zipcode=${zip5}`);
202
+ this.zipCache.set(zip5, null);
126
203
  return null;
127
204
  }
128
205
 
129
- result.ZipCode = String(zip);
206
+ result.ZipCode = String(zip5);
130
207
  const location = this.makeZipLocation(result);
131
- this.zipCache.set(zip, location);
208
+ this.zipCache.set(zip5, location);
132
209
  return location;
133
210
  }
134
211
  /**
@@ -218,6 +295,28 @@ class GeoDb {
218
295
  return null;
219
296
  }
220
297
  }
298
+ /**
299
+ * @private
300
+ * @param {any[]} res
301
+ * @return {Object[]}
302
+ */
303
+
304
+
305
+ static zipResultToObj(res) {
306
+ const obj = {
307
+ id: String(res.ZipCode),
308
+ value: `${res.CityMixedCase}, ${res.State} ${res.ZipCode}`,
309
+ admin1: res.State,
310
+ asciiname: res.CityMixedCase,
311
+ country: 'United States',
312
+ latitude: res.Latitude,
313
+ longitude: res.Longitude,
314
+ timezone: core.Location.getUsaTzid(res.State, res.TimeZone, res.DayLightSaving),
315
+ population: res.Population,
316
+ geo: 'zip'
317
+ };
318
+ return obj;
319
+ }
221
320
  /**
222
321
  * Generates autocomplete results based on a query string
223
322
  * @param {string} qraw
@@ -226,43 +325,37 @@ class GeoDb {
226
325
 
227
326
 
228
327
  autoComplete(qraw) {
328
+ qraw = qraw.trim();
329
+
229
330
  if (qraw.length === 0) {
230
331
  return [];
231
332
  }
232
333
 
233
- if (qraw.charCodeAt(0) >= 48 && qraw.charCodeAt(0) <= 57) {
334
+ const firstCharCode = qraw.charCodeAt(0);
335
+
336
+ if (firstCharCode >= 48 && firstCharCode <= 57) {
234
337
  if (!this.zipCompStmt) {
235
338
  this.zipCompStmt = this.zipsDb.prepare(ZIP_COMPLETE_SQL);
236
339
  }
237
340
 
238
- return this.zipCompStmt.all(qraw + '%').map(res => {
239
- const obj = {
240
- id: String(res.ZipCode),
241
- value: `${res.CityMixedCase}, ${res.State} ${res.ZipCode}`,
242
- admin1: res.State,
243
- asciiname: res.CityMixedCase,
244
- country: 'United States',
245
- latitude: res.Latitude,
246
- longitude: res.Longitude,
247
- timezone: core.Location.getUsaTzid(res.State, res.TimeZone, res.DayLightSaving),
248
- population: res.Population,
249
- geo: 'zip'
250
- };
251
- return obj;
252
- });
341
+ const zip5 = qraw.substring(0, 5);
342
+ return this.zipCompStmt.all(zip5 + '%').map(GeoDb.zipResultToObj);
253
343
  } else {
254
344
  if (!this.geonamesCompStmt) {
255
345
  this.geonamesCompStmt = this.geonamesDb.prepare(GEONAME_COMPLETE_SQL);
256
346
  }
257
347
 
258
348
  qraw = qraw.replace(/\"/g, '""');
259
- return this.geonamesCompStmt.all(`"${qraw}*"`).map(res => {
349
+ const geoRows = this.geonamesCompStmt.all(`"${qraw}*"`);
350
+ const geoMatches = geoRows.map(res => {
260
351
  const country = res.country || '';
261
352
  const admin1 = res.admin1 || '';
262
353
  const obj = {
263
354
  id: res.geonameid,
264
355
  value: core.Location.geonameCityDescr(res.asciiname, admin1, country),
265
356
  asciiname: res.asciiname,
357
+ admin1,
358
+ country,
266
359
  latitude: res.latitude,
267
360
  longitude: res.longitude,
268
361
  timezone: res.timezone,
@@ -281,6 +374,32 @@ class GeoDb {
281
374
  obj.tokens = Array.from(new Set(res.asciiname.split(' ').concat(admin1.split(' '), country.split(' '))));
282
375
  return obj;
283
376
  });
377
+
378
+ if (!this.zipFulltextCompStmt) {
379
+ this.zipFulltextCompStmt = this.zipsDb.prepare(ZIP_FULLTEXT_COMPLETE_SQL);
380
+ }
381
+
382
+ const zipRows = this.zipFulltextCompStmt.all(`"${qraw}*"`);
383
+ const zipMatches = zipRows.map(GeoDb.zipResultToObj);
384
+ const map = new Map();
385
+
386
+ for (const obj of zipMatches) {
387
+ const key = [obj.asciiname, stateNames[obj.admin1], obj.country].join('|');
388
+
389
+ if (!map.has(key)) {
390
+ map.set(key, obj);
391
+ }
392
+ } // GeoNames takes priority over USA ZIP code matches
393
+
394
+
395
+ for (const obj of geoMatches) {
396
+ const key = [obj.asciiname, obj.admin1, obj.country].join('|');
397
+ map.set(key, obj);
398
+ }
399
+
400
+ const values = Array.from(map.values());
401
+ values.sort((a, b) => b.population - a.population);
402
+ return values.slice(0, 10);
284
403
  }
285
404
  }
286
405
  /** Reads entire ZIP database and caches in-memory */
package/dist/index.mjs CHANGED
@@ -1,4 +1,4 @@
1
- /*! @hebcal/geo-sqlite v3.6.0 */
1
+ /*! @hebcal/geo-sqlite v3.8.0 */
2
2
  import Database from 'better-sqlite3';
3
3
  import { Location, Locale } from '@hebcal/core';
4
4
  import pino from 'pino';
@@ -40,18 +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
46
  ORDER BY Population DESC
47
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`;
48
53
  const GEONAME_COMPLETE_SQL = `SELECT geonameid, asciiname, admin1, country,
49
54
  population, latitude, longitude, timezone
50
55
  FROM geoname_fulltext
51
56
  WHERE longname MATCH ?
52
57
  GROUP BY geonameid
53
58
  ORDER BY population DESC
54
- LIMIT 10`;
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
+ };
55
113
  /** Wrapper around sqlite databases */
56
114
 
57
115
  class GeoDb {
@@ -71,14 +129,32 @@ class GeoDb {
71
129
  fileMustExist: true
72
130
  });
73
131
  this.zipStmt = this.zipsDb.prepare(ZIPCODE_SQL);
132
+ /** @type {Map<string, Location>} */
133
+
74
134
  this.zipCache = new Map();
75
135
  this.geonamesStmt = this.geonamesDb.prepare(GEONAME_SQL);
136
+ /** @type {Map<number, Location>} */
137
+
76
138
  this.geonamesCache = new Map();
139
+ /** @type {Map<string, Location>} */
140
+
77
141
  this.legacyCities = new Map();
78
142
 
79
143
  for (const [name, id] of Object.entries(city2geonameid)) {
80
144
  this.legacyCities.set(GeoDb.munge(name), id);
81
145
  }
146
+
147
+ const stmt = this.geonamesDb.prepare(`SELECT ISO, Country FROM country WHERE Country <> ''`);
148
+ const rows = stmt.all();
149
+ const map = new Map();
150
+
151
+ for (const row of rows) {
152
+ map.set(row.ISO, row.Country);
153
+ }
154
+ /** @type {Map<string, string>} */
155
+
156
+
157
+ this.countryNames = map;
82
158
  }
83
159
  /** Closes database handles */
84
160
 
@@ -104,19 +180,20 @@ class GeoDb {
104
180
 
105
181
 
106
182
  lookupZip(zip) {
107
- const found = this.zipCache.get(zip);
183
+ const zip5 = zip.trim().substring(0, 5);
184
+ const found = this.zipCache.get(zip5);
108
185
  if (typeof found !== 'undefined') return found;
109
- const result = this.zipStmt.get(zip);
186
+ const result = this.zipStmt.get(zip5);
110
187
 
111
188
  if (!result) {
112
- if (this.logger) this.logger.warn(`GeoDb: unknown zipcode=${zip}`);
113
- this.zipCache.set(zip, null);
189
+ if (this.logger) this.logger.warn(`GeoDb: unknown zipcode=${zip5}`);
190
+ this.zipCache.set(zip5, null);
114
191
  return null;
115
192
  }
116
193
 
117
- result.ZipCode = String(zip);
194
+ result.ZipCode = String(zip5);
118
195
  const location = this.makeZipLocation(result);
119
- this.zipCache.set(zip, location);
196
+ this.zipCache.set(zip5, location);
120
197
  return location;
121
198
  }
122
199
  /**
@@ -206,6 +283,28 @@ class GeoDb {
206
283
  return null;
207
284
  }
208
285
  }
286
+ /**
287
+ * @private
288
+ * @param {any[]} res
289
+ * @return {Object[]}
290
+ */
291
+
292
+
293
+ static zipResultToObj(res) {
294
+ const obj = {
295
+ id: String(res.ZipCode),
296
+ value: `${res.CityMixedCase}, ${res.State} ${res.ZipCode}`,
297
+ admin1: res.State,
298
+ asciiname: res.CityMixedCase,
299
+ country: 'United States',
300
+ latitude: res.Latitude,
301
+ longitude: res.Longitude,
302
+ timezone: Location.getUsaTzid(res.State, res.TimeZone, res.DayLightSaving),
303
+ population: res.Population,
304
+ geo: 'zip'
305
+ };
306
+ return obj;
307
+ }
209
308
  /**
210
309
  * Generates autocomplete results based on a query string
211
310
  * @param {string} qraw
@@ -214,43 +313,37 @@ class GeoDb {
214
313
 
215
314
 
216
315
  autoComplete(qraw) {
316
+ qraw = qraw.trim();
317
+
217
318
  if (qraw.length === 0) {
218
319
  return [];
219
320
  }
220
321
 
221
- if (qraw.charCodeAt(0) >= 48 && qraw.charCodeAt(0) <= 57) {
322
+ const firstCharCode = qraw.charCodeAt(0);
323
+
324
+ if (firstCharCode >= 48 && firstCharCode <= 57) {
222
325
  if (!this.zipCompStmt) {
223
326
  this.zipCompStmt = this.zipsDb.prepare(ZIP_COMPLETE_SQL);
224
327
  }
225
328
 
226
- return this.zipCompStmt.all(qraw + '%').map(res => {
227
- const obj = {
228
- id: String(res.ZipCode),
229
- value: `${res.CityMixedCase}, ${res.State} ${res.ZipCode}`,
230
- admin1: res.State,
231
- asciiname: res.CityMixedCase,
232
- country: 'United States',
233
- latitude: res.Latitude,
234
- longitude: res.Longitude,
235
- timezone: Location.getUsaTzid(res.State, res.TimeZone, res.DayLightSaving),
236
- population: res.Population,
237
- geo: 'zip'
238
- };
239
- return obj;
240
- });
329
+ const zip5 = qraw.substring(0, 5);
330
+ return this.zipCompStmt.all(zip5 + '%').map(GeoDb.zipResultToObj);
241
331
  } else {
242
332
  if (!this.geonamesCompStmt) {
243
333
  this.geonamesCompStmt = this.geonamesDb.prepare(GEONAME_COMPLETE_SQL);
244
334
  }
245
335
 
246
336
  qraw = qraw.replace(/\"/g, '""');
247
- return this.geonamesCompStmt.all(`"${qraw}*"`).map(res => {
337
+ const geoRows = this.geonamesCompStmt.all(`"${qraw}*"`);
338
+ const geoMatches = geoRows.map(res => {
248
339
  const country = res.country || '';
249
340
  const admin1 = res.admin1 || '';
250
341
  const obj = {
251
342
  id: res.geonameid,
252
343
  value: Location.geonameCityDescr(res.asciiname, admin1, country),
253
344
  asciiname: res.asciiname,
345
+ admin1,
346
+ country,
254
347
  latitude: res.latitude,
255
348
  longitude: res.longitude,
256
349
  timezone: res.timezone,
@@ -269,6 +362,32 @@ class GeoDb {
269
362
  obj.tokens = Array.from(new Set(res.asciiname.split(' ').concat(admin1.split(' '), country.split(' '))));
270
363
  return obj;
271
364
  });
365
+
366
+ if (!this.zipFulltextCompStmt) {
367
+ this.zipFulltextCompStmt = this.zipsDb.prepare(ZIP_FULLTEXT_COMPLETE_SQL);
368
+ }
369
+
370
+ const zipRows = this.zipFulltextCompStmt.all(`"${qraw}*"`);
371
+ const zipMatches = zipRows.map(GeoDb.zipResultToObj);
372
+ const map = new Map();
373
+
374
+ for (const obj of zipMatches) {
375
+ const key = [obj.asciiname, stateNames[obj.admin1], obj.country].join('|');
376
+
377
+ if (!map.has(key)) {
378
+ map.set(key, obj);
379
+ }
380
+ } // GeoNames takes priority over USA ZIP code matches
381
+
382
+
383
+ for (const obj of geoMatches) {
384
+ const key = [obj.asciiname, obj.admin1, obj.country].join('|');
385
+ map.set(key, obj);
386
+ }
387
+
388
+ const values = Array.from(map.values());
389
+ values.sort((a, b) => b.population - a.population);
390
+ return values.slice(0, 10);
272
391
  }
273
392
  }
274
393
  /** Reads entire ZIP database and caches in-memory */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hebcal/geo-sqlite",
3
- "version": "3.6.1",
3
+ "version": "3.8.0",
4
4
  "author": "Michael J. Radwin (https://github.com/mjradwin)",
5
5
  "keywords": [
6
6
  "hebcal"
@@ -28,10 +28,10 @@
28
28
  "geo-sqlite.d.ts"
29
29
  ],
30
30
  "dependencies": {
31
- "@hebcal/core": "^3.32.0",
32
- "better-sqlite3": "^7.4.6",
33
- "pino": "^7.6.2",
34
- "pino-pretty": "^7.3.0"
31
+ "@hebcal/core": "^3.33.2",
32
+ "better-sqlite3": "^7.5.0",
33
+ "pino": "^7.6.4",
34
+ "pino-pretty": "^7.5.0"
35
35
  },
36
36
  "scripts": {
37
37
  "build": "rollup -c",
@@ -60,19 +60,19 @@
60
60
  "license": "BSD-2-Clause",
61
61
  "devDependencies": {
62
62
  "@ava/babel": "^2.0.0",
63
- "@babel/core": "^7.16.7",
63
+ "@babel/core": "^7.16.12",
64
64
  "@babel/polyfill": "^7.12.1",
65
- "@babel/preset-env": "^7.16.7",
66
- "@babel/register": "^7.16.7",
65
+ "@babel/preset-env": "^7.16.11",
66
+ "@babel/register": "^7.16.9",
67
67
  "@rollup/plugin-babel": "^5.3.0",
68
68
  "@rollup/plugin-commonjs": "^21.0.1",
69
69
  "@rollup/plugin-json": "^4.1.0",
70
70
  "@rollup/plugin-node-resolve": "^13.1.3",
71
71
  "ava": "^3.15.0",
72
- "eslint": "^8.6.0",
72
+ "eslint": "^8.7.0",
73
73
  "eslint-config-google": "^0.14.0",
74
- "jsdoc": "^3.6.7",
74
+ "jsdoc": "^3.6.9",
75
75
  "jsdoc-to-markdown": "^7.1.0",
76
- "rollup": "^2.63.0"
76
+ "rollup": "^2.66.0"
77
77
  }
78
78
  }
package/zips-dummy.sql CHANGED
@@ -8,3 +8,6 @@ CREATE TABLE ZIPCodes_Primary (
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);