@k03mad/ip2geo 6.1.0 → 7.0.1
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/.github/dependabot.yml +1 -1
- package/.github/workflows/lint.yml +4 -19
- package/.github/workflows/publish.yml +21 -0
- package/.github/workflows/test.yml +4 -19
- package/app/helpers/cache.js +25 -22
- package/app/lib/ip2geo.js +12 -5
- package/package.json +8 -8
- package/tests/cache-file-entries.js +36 -0
- package/tests/cache-file-modify.js +1 -1
- package/tests/cache-file-subfolder.js +1 -1
- package/tests/cache-map-entries.js +1 -1
- package/tests/cache-map-off.js +1 -1
- package/tests/default.js +1 -1
- package/tests/ip-multi-requests-cache.js +1 -1
- package/tests/ip-no-data.js +1 -1
- package/tests/ip-v6.js +1 -1
- package/tests/{helpers → shared}/consts.js +3 -3
package/.github/dependabot.yml
CHANGED
|
@@ -7,29 +7,14 @@ on:
|
|
|
7
7
|
pull_request:
|
|
8
8
|
branches:
|
|
9
9
|
- master
|
|
10
|
-
schedule:
|
|
11
|
-
- cron: '00 15 * * 6'
|
|
12
10
|
|
|
13
11
|
jobs:
|
|
14
12
|
lint:
|
|
15
|
-
name: Lint
|
|
16
|
-
permissions:
|
|
17
|
-
contents: read
|
|
18
13
|
runs-on: ubuntu-latest
|
|
19
14
|
steps:
|
|
20
|
-
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
- name: Install NodeJS
|
|
24
|
-
uses: actions/setup-node@v4
|
|
15
|
+
- uses: actions/checkout@v4
|
|
16
|
+
- uses: actions/setup-node@v4
|
|
25
17
|
with:
|
|
26
18
|
node-version-file: '.nvmrc'
|
|
27
|
-
|
|
28
|
-
-
|
|
29
|
-
run: npm i pnpm -g
|
|
30
|
-
|
|
31
|
-
- name: Run setup
|
|
32
|
-
run: npm run setup
|
|
33
|
-
|
|
34
|
-
- name: Run lint
|
|
35
|
-
run: npm run lint
|
|
19
|
+
- run: npm run setup
|
|
20
|
+
- run: npm run lint
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
name: Publish
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches:
|
|
6
|
+
- master
|
|
7
|
+
|
|
8
|
+
jobs:
|
|
9
|
+
publish:
|
|
10
|
+
environment: npm
|
|
11
|
+
runs-on: ubuntu-latest
|
|
12
|
+
steps:
|
|
13
|
+
- uses: actions/checkout@v4
|
|
14
|
+
- uses: actions/setup-node@v4
|
|
15
|
+
with:
|
|
16
|
+
node-version-file: '.nvmrc'
|
|
17
|
+
registry-url: 'https://registry.npmjs.org'
|
|
18
|
+
- run: npm run setup
|
|
19
|
+
- run: npm publish
|
|
20
|
+
env:
|
|
21
|
+
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
|
|
@@ -7,29 +7,14 @@ on:
|
|
|
7
7
|
pull_request:
|
|
8
8
|
branches:
|
|
9
9
|
- master
|
|
10
|
-
schedule:
|
|
11
|
-
- cron: '00 15 * * 6'
|
|
12
10
|
|
|
13
11
|
jobs:
|
|
14
12
|
test:
|
|
15
|
-
name: Test
|
|
16
|
-
permissions:
|
|
17
|
-
contents: read
|
|
18
13
|
runs-on: ubuntu-latest
|
|
19
14
|
steps:
|
|
20
|
-
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
- name: Install NodeJS
|
|
24
|
-
uses: actions/setup-node@v4
|
|
15
|
+
- uses: actions/checkout@v4
|
|
16
|
+
- uses: actions/setup-node@v4
|
|
25
17
|
with:
|
|
26
18
|
node-version-file: '.nvmrc'
|
|
27
|
-
|
|
28
|
-
-
|
|
29
|
-
run: npm i pnpm -g
|
|
30
|
-
|
|
31
|
-
- name: Run setup
|
|
32
|
-
run: npm run setup
|
|
33
|
-
|
|
34
|
-
- name: Run test
|
|
35
|
-
run: npm run test
|
|
19
|
+
- run: npm run setup
|
|
20
|
+
- run: npm run test
|
package/app/helpers/cache.js
CHANGED
|
@@ -29,7 +29,9 @@ export const collectOutputData = dataArr => {
|
|
|
29
29
|
const outputData = {};
|
|
30
30
|
|
|
31
31
|
outputKeys.forEach((key, i) => {
|
|
32
|
-
outputData[key] = dataArr[i]
|
|
32
|
+
outputData[key] = key === 'connectionAsn' && dataArr[i]
|
|
33
|
+
? Number(dataArr[i])
|
|
34
|
+
: dataArr[i];
|
|
33
35
|
});
|
|
34
36
|
|
|
35
37
|
return outputData;
|
|
@@ -94,11 +96,10 @@ export const readFromFsCache = async (ip, cacheDir, cacheFileName, cacheFileSepa
|
|
|
94
96
|
*/
|
|
95
97
|
export const writeToFsCache = async (ip, data, cacheDir, cacheFileName, cacheFileSeparator, cacheFileNewline) => {
|
|
96
98
|
const cacheFileFull = getCacheFileFullPath(ip, cacheDir, cacheFileName);
|
|
99
|
+
debug('set to fs cache: %o %o', cacheFileFull, data);
|
|
97
100
|
|
|
98
101
|
await fs.mkdir(cacheDir, {recursive: true});
|
|
99
102
|
await fs.appendFile(cacheFileFull, Object.values(data).join(cacheFileSeparator) + cacheFileNewline);
|
|
100
|
-
|
|
101
|
-
debug('set to fs cache: %o %o', cacheFileFull, data);
|
|
102
103
|
};
|
|
103
104
|
|
|
104
105
|
/**
|
|
@@ -109,38 +110,25 @@ export const writeToFsCache = async (ip, data, cacheDir, cacheFileName, cacheFil
|
|
|
109
110
|
*/
|
|
110
111
|
export const readFromMapCache = (ip, cacheMap, cacheMapMaxEntries) => {
|
|
111
112
|
if (cacheMapMaxEntries > 0) {
|
|
112
|
-
const
|
|
113
|
+
const value = cacheMap.get(ip);
|
|
113
114
|
|
|
114
|
-
if (
|
|
115
|
-
debug('get from map cache: %o',
|
|
116
|
-
return
|
|
115
|
+
if (value) {
|
|
116
|
+
debug('get from map cache: %o', value);
|
|
117
|
+
return value;
|
|
117
118
|
}
|
|
118
119
|
}
|
|
119
120
|
};
|
|
120
121
|
|
|
121
|
-
/**
|
|
122
|
-
* @param {object} body
|
|
123
|
-
* @param {string} body.ip
|
|
124
|
-
* @param {Map} cacheMap
|
|
125
|
-
* @param {number} cacheMapMaxEntries
|
|
126
|
-
*/
|
|
127
|
-
export const writeToMapCache = (body, cacheMap, cacheMapMaxEntries) => {
|
|
128
|
-
if (cacheMapMaxEntries > 0) {
|
|
129
|
-
cacheMap.set(body.ip, body);
|
|
130
|
-
debug('set to map cache: %o', body);
|
|
131
|
-
}
|
|
132
|
-
};
|
|
133
|
-
|
|
134
122
|
/**
|
|
135
123
|
* @param {Map} cacheMap
|
|
136
124
|
* @param {number} cacheMapMaxEntries
|
|
137
125
|
*/
|
|
138
126
|
export const removeFromMapCacheIfLimit = (cacheMap, cacheMapMaxEntries) => {
|
|
139
127
|
if (cacheMap.size > cacheMapMaxEntries) {
|
|
140
|
-
debug('remove from map cache by limit:
|
|
128
|
+
debug('remove from map cache by limit: %o > %o', cacheMap.size, cacheMapMaxEntries);
|
|
141
129
|
|
|
142
130
|
for (const [key] of cacheMap) {
|
|
143
|
-
debug('remove from map cache by limit:
|
|
131
|
+
debug('remove from map cache by limit: %o', key);
|
|
144
132
|
cacheMap.delete(key);
|
|
145
133
|
|
|
146
134
|
if (cacheMap.size <= cacheMapMaxEntries) {
|
|
@@ -149,3 +137,18 @@ export const removeFromMapCacheIfLimit = (cacheMap, cacheMapMaxEntries) => {
|
|
|
149
137
|
}
|
|
150
138
|
}
|
|
151
139
|
};
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* @param {object} body
|
|
143
|
+
* @param {string} body.ip
|
|
144
|
+
* @param {Map} cacheMap
|
|
145
|
+
* @param {number} cacheMapMaxEntries
|
|
146
|
+
*/
|
|
147
|
+
export const writeToMapCache = (body, cacheMap, cacheMapMaxEntries) => {
|
|
148
|
+
if (cacheMapMaxEntries > 0) {
|
|
149
|
+
debug('set to map cache: %o', body);
|
|
150
|
+
cacheMap.set(body.ip, body);
|
|
151
|
+
|
|
152
|
+
removeFromMapCacheIfLimit(cacheMap, cacheMapMaxEntries);
|
|
153
|
+
}
|
|
154
|
+
};
|
package/app/lib/ip2geo.js
CHANGED
|
@@ -8,7 +8,6 @@ import {
|
|
|
8
8
|
collectOutputData,
|
|
9
9
|
readFromFsCache,
|
|
10
10
|
readFromMapCache,
|
|
11
|
-
removeFromMapCacheIfLimit,
|
|
12
11
|
writeToFsCache,
|
|
13
12
|
writeToMapCache,
|
|
14
13
|
} from '../helpers/cache.js';
|
|
@@ -75,7 +74,11 @@ export const ip2geo = async ({
|
|
|
75
74
|
return mapCache;
|
|
76
75
|
}
|
|
77
76
|
|
|
78
|
-
const fsCache = await readFromFsCache(
|
|
77
|
+
const fsCache = await readFromFsCache(
|
|
78
|
+
ip,
|
|
79
|
+
cacheDir, cacheFileName,
|
|
80
|
+
cacheFileSeparator, cacheFileNewline,
|
|
81
|
+
);
|
|
79
82
|
|
|
80
83
|
if (fsCache) {
|
|
81
84
|
writeToMapCache(fsCache, cacheMap, cacheMapMaxEntries);
|
|
@@ -87,7 +90,11 @@ export const ip2geo = async ({
|
|
|
87
90
|
const {body} = await request(reqUrl, {}, {rps});
|
|
88
91
|
|
|
89
92
|
if (!body?.ip) {
|
|
90
|
-
logErrorExit([
|
|
93
|
+
logErrorExit([
|
|
94
|
+
'API error',
|
|
95
|
+
`request: ${reqUrl}`,
|
|
96
|
+
`response body: ${body}`,
|
|
97
|
+
]);
|
|
91
98
|
}
|
|
92
99
|
|
|
93
100
|
const outputData = collectOutputData([
|
|
@@ -107,11 +114,11 @@ export const ip2geo = async ({
|
|
|
107
114
|
]);
|
|
108
115
|
|
|
109
116
|
writeToMapCache(outputData, cacheMap, cacheMapMaxEntries);
|
|
110
|
-
removeFromMapCacheIfLimit(cacheMap, cacheMapMaxEntries);
|
|
111
117
|
|
|
112
118
|
await writeToFsCache(
|
|
113
119
|
body.ip, outputData,
|
|
114
|
-
cacheDir, cacheFileName,
|
|
120
|
+
cacheDir, cacheFileName,
|
|
121
|
+
cacheFileSeparator, cacheFileNewline,
|
|
115
122
|
);
|
|
116
123
|
|
|
117
124
|
return outputData;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@k03mad/ip2geo",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "7.0.1",
|
|
4
4
|
"description": "GeoIP library",
|
|
5
5
|
"maintainers": [
|
|
6
6
|
"Kirill Molchanov <k03.mad@gmail.com"
|
|
@@ -19,25 +19,25 @@
|
|
|
19
19
|
"node": ">=20"
|
|
20
20
|
},
|
|
21
21
|
"dependencies": {
|
|
22
|
-
"@k03mad/request": "5.6.
|
|
23
|
-
"@k03mad/simple-log": "2.1.
|
|
22
|
+
"@k03mad/request": "5.6.1",
|
|
23
|
+
"@k03mad/simple-log": "2.1.1",
|
|
24
24
|
"chalk": "5.3.0",
|
|
25
25
|
"debug": "4.3.4"
|
|
26
26
|
},
|
|
27
27
|
"devDependencies": {
|
|
28
|
-
"@k03mad/eslint-config": "20.
|
|
28
|
+
"@k03mad/eslint-config": "20.3.0",
|
|
29
29
|
"eslint": "8.56.0",
|
|
30
|
-
"husky": "9.0.
|
|
31
|
-
"mocha": "10.
|
|
30
|
+
"husky": "9.0.11",
|
|
31
|
+
"mocha": "10.3.0"
|
|
32
32
|
},
|
|
33
33
|
"scripts": {
|
|
34
34
|
"lint": "npm run lint:eslint",
|
|
35
35
|
"lint:eslint": "eslint ./ --cache",
|
|
36
|
-
"test": "mocha tests",
|
|
36
|
+
"test": "rm -rfv ./.geoip && mocha tests",
|
|
37
37
|
"clean": "npm run clean:modules && npm run clean:eslint:cache",
|
|
38
38
|
"clean:modules": "rm -rf ./node_modules || true",
|
|
39
39
|
"clean:eslint:cache": "rm -rf .eslintcache || true",
|
|
40
|
-
"setup": "npm run clean && pnpm i",
|
|
40
|
+
"setup": "npm run clean && npm i pnpm -g && pnpm i",
|
|
41
41
|
"prepare": "husky || true"
|
|
42
42
|
}
|
|
43
43
|
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import assert from 'node:assert/strict';
|
|
2
|
+
|
|
3
|
+
import {describe, it} from 'mocha';
|
|
4
|
+
|
|
5
|
+
import {ip2geo} from '../app/index.js';
|
|
6
|
+
|
|
7
|
+
import {getCurrentFilename, getTestFolder} from './helpers/path.js';
|
|
8
|
+
import {REQUEST_IPV4} from './shared/consts.js';
|
|
9
|
+
import {checkCacheFile, removeCacheFolder} from './shared/fs.js';
|
|
10
|
+
|
|
11
|
+
const testName = getCurrentFilename(import.meta.url);
|
|
12
|
+
|
|
13
|
+
describe(testName, () => {
|
|
14
|
+
const opts = {
|
|
15
|
+
cacheDir: getTestFolder(testName),
|
|
16
|
+
cacheMap: new Map(),
|
|
17
|
+
cacheMapMaxEntries: 0,
|
|
18
|
+
tries: 5,
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
it('should remove fs cache dir if exist', () => removeCacheFolder(opts.cacheDir));
|
|
22
|
+
|
|
23
|
+
Array.from({length: opts.tries}, (_, i) => i + 1).forEach(num => {
|
|
24
|
+
describe(`Try: ${num}`, () => {
|
|
25
|
+
it(`should return correct response for IP: "${REQUEST_IPV4.ip}"`, async () => {
|
|
26
|
+
const data = await ip2geo({ip: REQUEST_IPV4.ip, ...opts});
|
|
27
|
+
assert.deepEqual(data, REQUEST_IPV4);
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
it('should have cache file', () => checkCacheFile({
|
|
31
|
+
...opts,
|
|
32
|
+
response: REQUEST_IPV4,
|
|
33
|
+
}));
|
|
34
|
+
});
|
|
35
|
+
});
|
|
36
|
+
});
|
|
@@ -4,8 +4,8 @@ import {describe, it} from 'mocha';
|
|
|
4
4
|
|
|
5
5
|
import {ip2geo} from '../app/index.js';
|
|
6
6
|
|
|
7
|
-
import {REQUEST_IPV4} from './helpers/consts.js';
|
|
8
7
|
import {getCurrentFilename, getTestFolder} from './helpers/path.js';
|
|
8
|
+
import {REQUEST_IPV4} from './shared/consts.js';
|
|
9
9
|
import {checkCacheFile, removeCacheFolder} from './shared/fs.js';
|
|
10
10
|
|
|
11
11
|
const testName = getCurrentFilename(import.meta.url);
|
|
@@ -5,8 +5,8 @@ import {describe, it} from 'mocha';
|
|
|
5
5
|
|
|
6
6
|
import {ip2geo} from '../app/index.js';
|
|
7
7
|
|
|
8
|
-
import {REQUEST_IPV4} from './helpers/consts.js';
|
|
9
8
|
import {getCurrentFilename, getTestFolder} from './helpers/path.js';
|
|
9
|
+
import {REQUEST_IPV4} from './shared/consts.js';
|
|
10
10
|
import {checkCacheFile, removeCacheFolder} from './shared/fs.js';
|
|
11
11
|
|
|
12
12
|
const testName = getCurrentFilename(import.meta.url);
|
|
@@ -4,8 +4,8 @@ import {describe, it} from 'mocha';
|
|
|
4
4
|
|
|
5
5
|
import {ip2geo} from '../app/index.js';
|
|
6
6
|
|
|
7
|
-
import {REQUEST_IPV4, REQUEST_IPV6} from './helpers/consts.js';
|
|
8
7
|
import {getCurrentFilename, getTestFolder} from './helpers/path.js';
|
|
8
|
+
import {REQUEST_IPV4, REQUEST_IPV6} from './shared/consts.js';
|
|
9
9
|
import {removeCacheFolder} from './shared/fs.js';
|
|
10
10
|
|
|
11
11
|
const testName = getCurrentFilename(import.meta.url);
|
package/tests/cache-map-off.js
CHANGED
|
@@ -4,8 +4,8 @@ import {describe, it} from 'mocha';
|
|
|
4
4
|
|
|
5
5
|
import {cacheStorage, ip2geo} from '../app/index.js';
|
|
6
6
|
|
|
7
|
-
import {REQUEST_IPV4_MAP_OFF_ONLY} from './helpers/consts.js';
|
|
8
7
|
import {getCurrentFilename, getTestFolder} from './helpers/path.js';
|
|
8
|
+
import {REQUEST_IPV4_MAP_OFF_ONLY} from './shared/consts.js';
|
|
9
9
|
import {checkCacheFile, removeCacheFolder} from './shared/fs.js';
|
|
10
10
|
|
|
11
11
|
const testName = getCurrentFilename(import.meta.url);
|
package/tests/default.js
CHANGED
|
@@ -4,8 +4,8 @@ import {describe, it} from 'mocha';
|
|
|
4
4
|
|
|
5
5
|
import {cacheStorage, ip2geo} from '../app/index.js';
|
|
6
6
|
|
|
7
|
-
import {REQUEST_IPV4} from './helpers/consts.js';
|
|
8
7
|
import {getCurrentFilename} from './helpers/path.js';
|
|
8
|
+
import {REQUEST_IPV4} from './shared/consts.js';
|
|
9
9
|
import {checkCacheFile, removeCacheFolder} from './shared/fs.js';
|
|
10
10
|
|
|
11
11
|
const testName = getCurrentFilename(import.meta.url);
|
|
@@ -4,8 +4,8 @@ import {describe, it} from 'mocha';
|
|
|
4
4
|
|
|
5
5
|
import {ip2geo} from '../app/index.js';
|
|
6
6
|
|
|
7
|
-
import {REQUEST_IPV4} from './helpers/consts.js';
|
|
8
7
|
import {getCurrentFilename, getTestFolder} from './helpers/path.js';
|
|
8
|
+
import {REQUEST_IPV4} from './shared/consts.js';
|
|
9
9
|
import {checkCacheFile, removeCacheFolder} from './shared/fs.js';
|
|
10
10
|
|
|
11
11
|
const testName = getCurrentFilename(import.meta.url);
|
package/tests/ip-no-data.js
CHANGED
|
@@ -4,8 +4,8 @@ import {describe, it} from 'mocha';
|
|
|
4
4
|
|
|
5
5
|
import {ip2geo} from '../app/index.js';
|
|
6
6
|
|
|
7
|
-
import {REQUEST_IPV4} from './helpers/consts.js';
|
|
8
7
|
import {getCurrentFilename, getTestFolder} from './helpers/path.js';
|
|
8
|
+
import {REQUEST_IPV4} from './shared/consts.js';
|
|
9
9
|
import {removeCacheFolder} from './shared/fs.js';
|
|
10
10
|
|
|
11
11
|
const testName = getCurrentFilename(import.meta.url);
|
package/tests/ip-v6.js
CHANGED
|
@@ -4,8 +4,8 @@ import {describe, it} from 'mocha';
|
|
|
4
4
|
|
|
5
5
|
import {ip2geo} from '../app/index.js';
|
|
6
6
|
|
|
7
|
-
import {REQUEST_IPV6} from './helpers/consts.js';
|
|
8
7
|
import {getCurrentFilename, getTestFolder} from './helpers/path.js';
|
|
8
|
+
import {REQUEST_IPV6} from './shared/consts.js';
|
|
9
9
|
import {checkCacheFile, removeCacheFolder} from './shared/fs.js';
|
|
10
10
|
|
|
11
11
|
const testName = getCurrentFilename(import.meta.url);
|
|
@@ -21,9 +21,9 @@ export const REQUEST_IPV4_MAP_OFF_ONLY = {
|
|
|
21
21
|
country: 'United States',
|
|
22
22
|
countryCode: 'US',
|
|
23
23
|
countryEmoji: '🇺🇸',
|
|
24
|
-
region: '
|
|
25
|
-
regionCode: '
|
|
26
|
-
city: '
|
|
24
|
+
region: 'California',
|
|
25
|
+
regionCode: 'CA',
|
|
26
|
+
city: 'San Jose',
|
|
27
27
|
connectionAsn: 13_335,
|
|
28
28
|
connectionOrg: 'APNIC and Cloudflare DNS Resolver project',
|
|
29
29
|
connectionIsp: 'Cloudflare, Inc.',
|