Skip to content

Commit a8e790d

Browse files
committed
3.0.0-alpha.0
1 parent cffb6c2 commit a8e790d

File tree

13 files changed

+543
-677
lines changed

13 files changed

+543
-677
lines changed

README.md

Lines changed: 11 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,8 @@ You can see this module in action using my [official API](https://api.sefinek.ne
7272

7373

7474
## 📚 Library API
75-
GeoIP-Lite2 is completely synchronous. It does not use callbacks. All blocking file I/O is performed at startup, so all runtime calls are executed in-memory and are fast.
75+
GeoIP-Lite2 performs lookups synchronously in memory (`lookup`). It also provides async data reload methods (`reloadData`) and file watcher callbacks (`startWatchingDataUpdate`).
76+
All blocking file I/O is performed at startup, so all runtime lookups are fast.
7677
Startup may take up to 200 ms while reading and indexing data files into memory.
7778

7879
### Looking up an IP address
@@ -104,17 +105,6 @@ If the IP address was found, the `lookup` method returns an object with the foll
104105

105106
If the IP address was not found, `lookup` returns `null`.
106107

107-
### Pretty printing an IP address
108-
If you have a 32-bit unsigned integer or a number returned as part of the `range` array,
109-
you can use the `pretty` method to get a human-readable format.
110-
111-
```js
112-
console.log('IP is %s', geoIp.pretty(ip));
113-
```
114-
115-
The method returns a string if the input format is recognized, otherwise it returns the input itself.
116-
117-
118108
## 🔄 Built-in Updater
119109
This package contains an update script that downloads files from MaxMind and handles CSV conversion.
120110
A npm script alias has been configured to simplify this process. Internet access is required and MaxMind download limits apply.
@@ -144,10 +134,13 @@ You can do it programmatically, calling after scheduled data updates
144134
// Synchronously
145135
geoIp.reloadDataSync();
146136

147-
// Asynchronously
137+
// Asynchronously (callback)
148138
geoIp.reloadData(() => {
149139
console.log('Done');
150140
});
141+
142+
// Asynchronously (Promise)
143+
await geoIp.reloadData();
151144
```
152145

153146
#### Automatic Start and stop watching for data updates
@@ -163,11 +156,11 @@ This tool can be used with `npm run updatedb` to periodically update geo data on
163156
The following environment variables can be set.
164157

165158
```bash
166-
# Override the default node_modules/geoip-lite/data dir
167-
GEOTMPDIR=/some/path
168-
169-
# Override the default node_modules/geoip-lite/tmp dir
159+
# Override the default node_modules/geoip-lite2/data dir
170160
GEODATADIR=/some/path
161+
162+
# Override the default node_modules/geoip-lite2/tmp dir
163+
GEOTMPDIR=/some/path
171164
```
172165

173166

@@ -210,4 +203,4 @@ console.log(process.memoryUsage());
210203

211204

212205
## 🔐 License
213-
There are two licenses for the code and data. See the [LICENSE](LICENSE) file for details.
206+
There are two licenses for the code and data. See the [LICENSE](LICENSE) file for details.

fsWatcher.js

Lines changed: 25 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -1,76 +1,44 @@
1-
// ============================================================================
2-
// File System Watcher for Auto-Reloading GeoIP Data
3-
// ============================================================================
4-
51
const { access, constants, watch } = require('node:fs');
62
const { join } = require('node:path');
73
const FSWatcher = {};
84

9-
// ============================================================================
10-
// Watcher Management
11-
// ============================================================================
12-
13-
/**
14-
* Takes an FSWatcher object and closes it.
15-
* @param {string} name - The name of the watcher to close.
16-
*/
175
const stopWatching = name => {
18-
const watcher = FSWatcher[name];
19-
if (!watcher) return;
6+
const watchState = FSWatcher[name];
7+
if (!watchState) return;
8+
9+
if (watchState.cdId !== null) {
10+
clearTimeout(watchState.cdId);
11+
watchState.cdId = null;
12+
}
2013

21-
watcher.close();
14+
watchState.watcher.close();
2215
delete FSWatcher[name];
2316
};
2417

25-
// ============================================================================
26-
// File System Watch with Debounce
27-
// ============================================================================
28-
29-
/**
30-
* Takes a directory/file and watch for change. Upon change, call the callback.
31-
*
32-
* @param {String} name - name of this watcher
33-
* @param {String} directory - path to the directory to watch
34-
* @param {String} [filename] - (optional) specific filename to watch for, watches for all files in the directory if unspecified
35-
* @param {Number} cdDelay - delay to wait before triggering the callback
36-
* @param {Function} callback - function() - called when changes are detected
37-
*/
3818
const makeFsWatchFilter = (name, directory, filename, cdDelay, callback) => {
39-
let cdId = null;
40-
41-
// Delete the cdId and callback the outer function
42-
function timeoutCallback() {
43-
cdId = null;
19+
const watchState = { watcher: null, cdId: null };
20+
const timeoutCallback = () => {
21+
watchState.cdId = null;
4422
callback();
45-
}
46-
47-
// This function is called when there is a change in the data directory
48-
// It sets a timer to wait for the change to be completed
49-
function onWatchEvent(event, changedFile) {
50-
// Check to make sure changedFile is not null
23+
};
24+
const onWatchEvent = (_event, changedFile) => {
5125
if (!changedFile) return;
5226

5327
const filePath = join(directory, changedFile);
5428
if (!filename || filename === changedFile) {
5529
access(filePath, constants.F_OK, err => {
56-
if (err) return console.error(err);
57-
58-
// At this point, a new file system activity has been detected,
59-
// We have to wait for file transfer to be finished before moving on.
60-
61-
// If a cdId already exists, we delete it
62-
if (cdId !== null) {
63-
clearTimeout(cdId);
64-
cdId = null;
30+
if (err) {
31+
if (err.code !== 'ENOENT') console.error(err);
32+
return;
6533
}
66-
67-
// Once the cdDelay has passed, the timeoutCallback function will be called
68-
cdId = setTimeout(timeoutCallback, cdDelay);
34+
if (watchState.cdId !== null) {
35+
clearTimeout(watchState.cdId);
36+
watchState.cdId = null;
37+
}
38+
watchState.cdId = setTimeout(timeoutCallback, cdDelay);
6939
});
7040
}
71-
}
72-
73-
// Manage the case where filename is missing (because it's optional)
41+
};
7442
if (typeof cdDelay === 'function') {
7543
callback = cdDelay;
7644
cdDelay = filename;
@@ -81,11 +49,9 @@ const makeFsWatchFilter = (name, directory, filename, cdDelay, callback) => {
8149
stopWatching(name);
8250
}
8351

84-
FSWatcher[name] = watch(directory, onWatchEvent);
52+
watchState.watcher = watch(directory, onWatchEvent);
53+
FSWatcher[name] = watchState;
8554
};
8655

87-
// ============================================================================
88-
// Exports
89-
// ============================================================================
90-
9156
module.exports = { makeFsWatchFilter, stopWatching };
57+

index.d.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ interface GeoIp2Location {
1111
}
1212

1313
export function lookup(ip: string | number): GeoIp2Location | null;
14-
export function pretty(n: string | number | any[]): string;
1514
export function reloadDataSync(): void;
1615
export function reloadData(callback: (err?: Error | null) => void): void;
1716
export function reloadData(): Promise<void>;

0 commit comments

Comments
 (0)