@k03mad/ip2geo 19.3.3 → 20.0.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/.vscode/settings.json +2 -1
- package/app/api.ts +120 -0
- package/app/cli.ts +102 -0
- package/app/helpers/cache.ts +257 -0
- package/app/helpers/utils.ts +1 -0
- package/app/types.ts +15 -0
- package/cli.js +3 -0
- package/package.json +14 -11
- package/pnpm-workspace.yaml +4 -42
- package/tests/cache-file-entries.ts +37 -0
- package/tests/cache-file-modify.ts +34 -0
- package/tests/cache-file-subfolder.ts +34 -0
- package/tests/cache-map-entries.ts +41 -0
- package/tests/cache-map-max-entries.ts +50 -0
- package/tests/cache-map-off.ts +34 -0
- package/tests/default.ts +55 -0
- package/tests/helpers/path.ts +5 -0
- package/tests/ip-multi-requests-cache.ts +39 -0
- package/tests/ip-no-data.ts +33 -0
- package/tests/ip-v6.ts +31 -0
- package/tests/shared/consts.ts +49 -0
- package/tests/shared/fs.ts +44 -0
- package/tsconfig.json +9 -0
- package/app/api.js +0 -142
- package/app/cli.js +0 -104
- package/app/helpers/cache.js +0 -274
- package/app/helpers/utils.js +0 -2
- package/tests/cache-file-entries.js +0 -37
- package/tests/cache-file-modify.js +0 -34
- package/tests/cache-file-subfolder.js +0 -34
- package/tests/cache-map-entries.js +0 -41
- package/tests/cache-map-max-entries.js +0 -50
- package/tests/cache-map-off.js +0 -35
- package/tests/default.js +0 -55
- package/tests/helpers/path.js +0 -13
- package/tests/ip-multi-requests-cache.js +0 -39
- package/tests/ip-no-data.js +0 -35
- package/tests/ip-v6.js +0 -31
- package/tests/shared/consts.js +0 -47
- package/tests/shared/fs.js +0 -42
- /package/app/helpers/{colors.js → colors.ts} +0 -0
package/app/helpers/cache.js
DELETED
|
@@ -1,274 +0,0 @@
|
|
|
1
|
-
import fs from 'node:fs/promises';
|
|
2
|
-
import path from 'node:path';
|
|
3
|
-
|
|
4
|
-
import _debug from 'debug';
|
|
5
|
-
import {isIP} from 'is-ip';
|
|
6
|
-
|
|
7
|
-
import {getArrayDups} from './utils.js';
|
|
8
|
-
|
|
9
|
-
const debug = _debug('mad:geoip');
|
|
10
|
-
|
|
11
|
-
const outputKeys = [
|
|
12
|
-
'ip',
|
|
13
|
-
'continent',
|
|
14
|
-
'continentCode',
|
|
15
|
-
'country',
|
|
16
|
-
'countryCode',
|
|
17
|
-
'countryEmoji',
|
|
18
|
-
'region',
|
|
19
|
-
'regionCode',
|
|
20
|
-
'city',
|
|
21
|
-
'connectionAsn',
|
|
22
|
-
'connectionOrg',
|
|
23
|
-
'connectionIsp',
|
|
24
|
-
'connectionDomain',
|
|
25
|
-
];
|
|
26
|
-
|
|
27
|
-
/**
|
|
28
|
-
* @param {string[]} dataArr
|
|
29
|
-
* @returns {object}
|
|
30
|
-
*/
|
|
31
|
-
export const collectOutputData = dataArr => {
|
|
32
|
-
const outputData = {};
|
|
33
|
-
|
|
34
|
-
outputKeys.forEach((key, i) => {
|
|
35
|
-
outputData[key] = key === 'connectionAsn' && dataArr[i] ? Number(dataArr[i]) : dataArr[i];
|
|
36
|
-
});
|
|
37
|
-
|
|
38
|
-
return outputData;
|
|
39
|
-
};
|
|
40
|
-
|
|
41
|
-
/**
|
|
42
|
-
* @param {string} ip
|
|
43
|
-
* @param {string} cacheDir
|
|
44
|
-
* @param {string} cacheFileName
|
|
45
|
-
* @returns {string}
|
|
46
|
-
*/
|
|
47
|
-
const getCacheFileFullPath = (ip, cacheDir, cacheFileName) => {
|
|
48
|
-
const [firstOctet] = ip.split(/[.:]/);
|
|
49
|
-
return path.join(cacheDir, `${firstOctet}_${cacheFileName}`);
|
|
50
|
-
};
|
|
51
|
-
|
|
52
|
-
/**
|
|
53
|
-
* @param {string} ip
|
|
54
|
-
* @param {string} cacheDir
|
|
55
|
-
* @param {string} cacheFileName
|
|
56
|
-
* @param {string} cacheFileSeparator
|
|
57
|
-
* @param {string} cacheFileNewline
|
|
58
|
-
* @returns {Promise<object>}
|
|
59
|
-
*/
|
|
60
|
-
export const readFromFsCache = async (
|
|
61
|
-
ip,
|
|
62
|
-
cacheDir,
|
|
63
|
-
cacheFileName,
|
|
64
|
-
cacheFileSeparator,
|
|
65
|
-
cacheFileNewline,
|
|
66
|
-
) => {
|
|
67
|
-
const cacheFileFull = getCacheFileFullPath(ip, cacheDir, cacheFileName);
|
|
68
|
-
|
|
69
|
-
try {
|
|
70
|
-
await fs.mkdir(cacheDir, {recursive: true});
|
|
71
|
-
const content = await fs.readFile(cacheFileFull, {encoding: 'utf8'});
|
|
72
|
-
|
|
73
|
-
if (content) {
|
|
74
|
-
const data = content.split(cacheFileNewline);
|
|
75
|
-
|
|
76
|
-
for (const elem of data) {
|
|
77
|
-
const fileData = elem.split(cacheFileSeparator);
|
|
78
|
-
|
|
79
|
-
if (ip === fileData[0]) {
|
|
80
|
-
const outputData = collectOutputData(fileData);
|
|
81
|
-
debug('get from fs cache: %o %o', cacheFileFull, outputData);
|
|
82
|
-
return outputData;
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
} catch (err) {
|
|
87
|
-
if (err.code === 'ENOENT') {
|
|
88
|
-
await fs.appendFile(cacheFileFull, '');
|
|
89
|
-
} else {
|
|
90
|
-
throw err;
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
};
|
|
94
|
-
|
|
95
|
-
/**
|
|
96
|
-
* @param {string} ip
|
|
97
|
-
* @param {object} data
|
|
98
|
-
* @param {string} cacheDir
|
|
99
|
-
* @param {string} cacheFileName
|
|
100
|
-
* @param {string} cacheFileSeparator
|
|
101
|
-
* @param {string} cacheFileNewline
|
|
102
|
-
* @returns {Promise<void>}
|
|
103
|
-
*/
|
|
104
|
-
export const writeToFsCache = async (
|
|
105
|
-
ip,
|
|
106
|
-
data,
|
|
107
|
-
cacheDir,
|
|
108
|
-
cacheFileName,
|
|
109
|
-
cacheFileSeparator,
|
|
110
|
-
cacheFileNewline,
|
|
111
|
-
) => {
|
|
112
|
-
const cacheFileFull = getCacheFileFullPath(ip, cacheDir, cacheFileName);
|
|
113
|
-
debug('set to fs cache: %o %o', cacheFileFull, data);
|
|
114
|
-
|
|
115
|
-
await fs.mkdir(cacheDir, {recursive: true});
|
|
116
|
-
|
|
117
|
-
await fs.appendFile(
|
|
118
|
-
cacheFileFull,
|
|
119
|
-
cacheFileNewline + Object.values(data).join(cacheFileSeparator),
|
|
120
|
-
);
|
|
121
|
-
};
|
|
122
|
-
|
|
123
|
-
/**
|
|
124
|
-
* @param {string} ip
|
|
125
|
-
* @param {Map} cacheMap
|
|
126
|
-
* @param {number} cacheMapMaxEntries
|
|
127
|
-
* @returns {object | undefined}
|
|
128
|
-
*/
|
|
129
|
-
export const readFromMapCache = (ip, cacheMap, cacheMapMaxEntries) => {
|
|
130
|
-
if (cacheMapMaxEntries > 0) {
|
|
131
|
-
const value = cacheMap.get(ip);
|
|
132
|
-
|
|
133
|
-
if (value) {
|
|
134
|
-
debug('get from map cache: %o', value);
|
|
135
|
-
return value;
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
};
|
|
139
|
-
|
|
140
|
-
/**
|
|
141
|
-
* @param {Map} cacheMap
|
|
142
|
-
* @param {number} cacheMapMaxEntries
|
|
143
|
-
*/
|
|
144
|
-
export const removeFromMapCacheIfLimit = (cacheMap, cacheMapMaxEntries) => {
|
|
145
|
-
if (cacheMap.size > cacheMapMaxEntries) {
|
|
146
|
-
debug('remove from map cache by limit: %o > %o', cacheMap.size, cacheMapMaxEntries);
|
|
147
|
-
|
|
148
|
-
for (const [key] of cacheMap) {
|
|
149
|
-
debug('remove from map cache by limit: %o', key);
|
|
150
|
-
cacheMap.delete(key);
|
|
151
|
-
|
|
152
|
-
if (cacheMap.size <= cacheMapMaxEntries) {
|
|
153
|
-
break;
|
|
154
|
-
}
|
|
155
|
-
}
|
|
156
|
-
}
|
|
157
|
-
};
|
|
158
|
-
|
|
159
|
-
/**
|
|
160
|
-
* @param {object} body
|
|
161
|
-
* @param {string} body.ip
|
|
162
|
-
* @param {Map} cacheMap
|
|
163
|
-
* @param {number} cacheMapMaxEntries
|
|
164
|
-
*/
|
|
165
|
-
export const writeToMapCache = (body, cacheMap, cacheMapMaxEntries) => {
|
|
166
|
-
if (cacheMapMaxEntries > 0) {
|
|
167
|
-
debug('set to map cache: %o', body);
|
|
168
|
-
cacheMap.set(body.ip, body);
|
|
169
|
-
|
|
170
|
-
removeFromMapCacheIfLimit(cacheMap, cacheMapMaxEntries);
|
|
171
|
-
}
|
|
172
|
-
};
|
|
173
|
-
|
|
174
|
-
/**
|
|
175
|
-
* @param {string} cacheDir
|
|
176
|
-
* @param {string} cacheFileSeparator
|
|
177
|
-
* @param {string} cacheFileNewline
|
|
178
|
-
*/
|
|
179
|
-
export const pruneCache = async (cacheDir, cacheFileSeparator, cacheFileNewline) => {
|
|
180
|
-
const files = await fs.readdir(cacheDir);
|
|
181
|
-
|
|
182
|
-
await Promise.all(
|
|
183
|
-
files.map(async file => {
|
|
184
|
-
const fullFilePath = path.join(cacheDir, file);
|
|
185
|
-
|
|
186
|
-
const [stat, data] = await Promise.all([
|
|
187
|
-
fs.lstat(fullFilePath),
|
|
188
|
-
fs.readFile(fullFilePath, {encoding: 'utf8'}),
|
|
189
|
-
]);
|
|
190
|
-
|
|
191
|
-
const firstIp = data
|
|
192
|
-
?.split(cacheFileNewline)
|
|
193
|
-
?.find(Boolean)
|
|
194
|
-
?.split(cacheFileSeparator)[0];
|
|
195
|
-
|
|
196
|
-
if (stat.isDirectory() || (firstIp && !isIP(firstIp))) {
|
|
197
|
-
throw new Error(
|
|
198
|
-
`Folder has subfolders or files without IPs, wrong cache folder arg?\n${fullFilePath}`,
|
|
199
|
-
);
|
|
200
|
-
}
|
|
201
|
-
}),
|
|
202
|
-
);
|
|
203
|
-
|
|
204
|
-
const cacheLineToNum = line =>
|
|
205
|
-
Number(
|
|
206
|
-
line
|
|
207
|
-
.split(cacheFileSeparator)[0]
|
|
208
|
-
.split('.')
|
|
209
|
-
.map(num => `00${num}`.slice(-3))
|
|
210
|
-
.join(''),
|
|
211
|
-
);
|
|
212
|
-
|
|
213
|
-
const duplicates = new Set();
|
|
214
|
-
const different = new Set();
|
|
215
|
-
const empty = [];
|
|
216
|
-
const longLinesFiles = new Set();
|
|
217
|
-
let entries = 0;
|
|
218
|
-
|
|
219
|
-
await Promise.all(
|
|
220
|
-
files.map(async file => {
|
|
221
|
-
const fullFilePath = path.join(cacheDir, file);
|
|
222
|
-
|
|
223
|
-
const data = await fs.readFile(fullFilePath, {encoding: 'utf8'});
|
|
224
|
-
const dataArr = data.split(cacheFileNewline).filter(Boolean);
|
|
225
|
-
|
|
226
|
-
const dataArrRemoveEmpty = dataArr.filter(elem => {
|
|
227
|
-
const splitted = elem.split(cacheFileSeparator);
|
|
228
|
-
|
|
229
|
-
if (splitted.length > outputKeys.length) {
|
|
230
|
-
longLinesFiles.add({file: fullFilePath, elem});
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
if (splitted.filter(Boolean).length > 1) {
|
|
234
|
-
return true;
|
|
235
|
-
}
|
|
236
|
-
|
|
237
|
-
empty.push(elem);
|
|
238
|
-
});
|
|
239
|
-
|
|
240
|
-
const uniqSorted = [...new Set(dataArrRemoveEmpty)].toSorted(
|
|
241
|
-
(a, b) => cacheLineToNum(a) - cacheLineToNum(b),
|
|
242
|
-
);
|
|
243
|
-
|
|
244
|
-
getArrayDups(dataArrRemoveEmpty).forEach(dup => duplicates.add(dup));
|
|
245
|
-
const dupsIp = getArrayDups(uniqSorted.map(elem => elem.split(cacheFileSeparator)[0]));
|
|
246
|
-
|
|
247
|
-
const removeDiffs = uniqSorted.filter(elem => {
|
|
248
|
-
if (dupsIp.includes(elem.split(cacheFileSeparator)[0])) {
|
|
249
|
-
different.add(elem);
|
|
250
|
-
return false;
|
|
251
|
-
}
|
|
252
|
-
|
|
253
|
-
return true;
|
|
254
|
-
});
|
|
255
|
-
|
|
256
|
-
const fileContent = removeDiffs.join(cacheFileNewline).trim();
|
|
257
|
-
|
|
258
|
-
if (fileContent) {
|
|
259
|
-
await fs.writeFile(fullFilePath, fileContent);
|
|
260
|
-
entries += removeDiffs.length;
|
|
261
|
-
} else {
|
|
262
|
-
await fs.rm(fullFilePath);
|
|
263
|
-
}
|
|
264
|
-
}),
|
|
265
|
-
);
|
|
266
|
-
|
|
267
|
-
return {
|
|
268
|
-
entries,
|
|
269
|
-
duplicates: [...duplicates],
|
|
270
|
-
different: [...different],
|
|
271
|
-
empty,
|
|
272
|
-
longLinesFiles: [...longLinesFiles],
|
|
273
|
-
};
|
|
274
|
-
};
|
package/app/helpers/utils.js
DELETED
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
import assert from 'node:assert/strict';
|
|
2
|
-
|
|
3
|
-
import {describe, it} from 'mocha';
|
|
4
|
-
|
|
5
|
-
import {ip2geo} from '../app/api.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', () =>
|
|
31
|
-
checkCacheFile({
|
|
32
|
-
...opts,
|
|
33
|
-
response: REQUEST_IPV4,
|
|
34
|
-
}));
|
|
35
|
-
});
|
|
36
|
-
});
|
|
37
|
-
});
|
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
import assert from 'node:assert/strict';
|
|
2
|
-
|
|
3
|
-
import {describe, it} from 'mocha';
|
|
4
|
-
|
|
5
|
-
import {ip2geo} from '../app/api.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
|
-
cacheFileName: 'ips.md',
|
|
17
|
-
cacheFileSeparator: '-_-',
|
|
18
|
-
cacheFileNewline: '%%%',
|
|
19
|
-
cacheMap: new Map(),
|
|
20
|
-
};
|
|
21
|
-
|
|
22
|
-
it('should remove fs cache dir if exist', () => removeCacheFolder(opts.cacheDir));
|
|
23
|
-
|
|
24
|
-
it(`should return correct response for IP: "${REQUEST_IPV4.ip}"`, async () => {
|
|
25
|
-
const data = await ip2geo({ip: REQUEST_IPV4.ip, ...opts});
|
|
26
|
-
assert.deepEqual(data, REQUEST_IPV4);
|
|
27
|
-
});
|
|
28
|
-
|
|
29
|
-
it('should have cache file', () =>
|
|
30
|
-
checkCacheFile({
|
|
31
|
-
...opts,
|
|
32
|
-
response: REQUEST_IPV4,
|
|
33
|
-
}));
|
|
34
|
-
});
|
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
import assert from 'node:assert/strict';
|
|
2
|
-
import path from 'node:path';
|
|
3
|
-
|
|
4
|
-
import {describe, it} from 'mocha';
|
|
5
|
-
|
|
6
|
-
import {ip2geo} from '../app/api.js';
|
|
7
|
-
|
|
8
|
-
import {getCurrentFilename, getTestFolder} from './helpers/path.js';
|
|
9
|
-
import {REQUEST_IPV4} from './shared/consts.js';
|
|
10
|
-
import {checkCacheFile, removeCacheFolder} from './shared/fs.js';
|
|
11
|
-
|
|
12
|
-
const testName = getCurrentFilename(import.meta.url);
|
|
13
|
-
|
|
14
|
-
describe(testName, () => {
|
|
15
|
-
const SUBFOLDERS = 5;
|
|
16
|
-
|
|
17
|
-
const opts = {
|
|
18
|
-
cacheDir: getTestFolder(path.join(...Array.from({length: SUBFOLDERS}, () => testName))),
|
|
19
|
-
cacheMap: new Map(),
|
|
20
|
-
};
|
|
21
|
-
|
|
22
|
-
it('should remove fs cache dir if exist', () => removeCacheFolder(opts.cacheDir));
|
|
23
|
-
|
|
24
|
-
it(`should return correct response for IP: "${REQUEST_IPV4.ip}"`, async () => {
|
|
25
|
-
const data = await ip2geo({ip: REQUEST_IPV4.ip, ...opts});
|
|
26
|
-
assert.deepEqual(data, REQUEST_IPV4);
|
|
27
|
-
});
|
|
28
|
-
|
|
29
|
-
it('should have cache file', () =>
|
|
30
|
-
checkCacheFile({
|
|
31
|
-
...opts,
|
|
32
|
-
response: REQUEST_IPV4,
|
|
33
|
-
}));
|
|
34
|
-
});
|
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
import assert from 'node:assert/strict';
|
|
2
|
-
|
|
3
|
-
import {describe, it} from 'mocha';
|
|
4
|
-
|
|
5
|
-
import {ip2geo} from '../app/api.js';
|
|
6
|
-
|
|
7
|
-
import {getCurrentFilename, getTestFolder} from './helpers/path.js';
|
|
8
|
-
import {REQUEST_IPV4, REQUEST_IPV6} from './shared/consts.js';
|
|
9
|
-
import {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
|
-
};
|
|
18
|
-
|
|
19
|
-
it('should remove fs cache dir if exist', () => removeCacheFolder(opts.cacheDir));
|
|
20
|
-
|
|
21
|
-
it(`should return correct response for IP: "${REQUEST_IPV4.ip}"`, async () => {
|
|
22
|
-
const data = await ip2geo({ip: REQUEST_IPV4.ip, ...opts});
|
|
23
|
-
assert.deepEqual(data, REQUEST_IPV4);
|
|
24
|
-
});
|
|
25
|
-
|
|
26
|
-
it('should have 1 correct cache entry', () => {
|
|
27
|
-
assert.equal(opts.cacheMap.size, 1);
|
|
28
|
-
assert.deepEqual(opts.cacheMap.get(REQUEST_IPV4.ip), REQUEST_IPV4);
|
|
29
|
-
});
|
|
30
|
-
|
|
31
|
-
it.skip(`should return correct response for IP: "${REQUEST_IPV6.ip}"`, async () => {
|
|
32
|
-
const data = await ip2geo({ip: REQUEST_IPV6.ip, ...opts});
|
|
33
|
-
assert.deepEqual(data, REQUEST_IPV6);
|
|
34
|
-
});
|
|
35
|
-
|
|
36
|
-
it.skip('should have 2 correct cache entries', () => {
|
|
37
|
-
assert.equal(opts.cacheMap.size, 2);
|
|
38
|
-
assert.deepEqual(opts.cacheMap.get(REQUEST_IPV4.ip), REQUEST_IPV4);
|
|
39
|
-
assert.deepEqual(opts.cacheMap.get(REQUEST_IPV6.ip), REQUEST_IPV6);
|
|
40
|
-
});
|
|
41
|
-
});
|
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
import assert from 'node:assert/strict';
|
|
2
|
-
|
|
3
|
-
import {describe, it} from 'mocha';
|
|
4
|
-
|
|
5
|
-
import {ip2geo} from '../app/api.js';
|
|
6
|
-
|
|
7
|
-
import {getCurrentFilename, getTestFolder} from './helpers/path.js';
|
|
8
|
-
import {removeCacheFolder} from './shared/fs.js';
|
|
9
|
-
|
|
10
|
-
const testName = getCurrentFilename(import.meta.url);
|
|
11
|
-
|
|
12
|
-
describe(testName, () => {
|
|
13
|
-
const firstReqIps = ['10.10.10.10', '20.20.20.20', '30.30.30.30', '40.40.40.40', '50.50.50.50'];
|
|
14
|
-
|
|
15
|
-
const secondReqIps = ['60.60.60.60'];
|
|
16
|
-
|
|
17
|
-
const opts = {
|
|
18
|
-
cacheDir: getTestFolder(testName),
|
|
19
|
-
cacheMap: new Map(),
|
|
20
|
-
cacheMapMaxEntries: 2,
|
|
21
|
-
};
|
|
22
|
-
|
|
23
|
-
it('should remove fs cache dir if exist', () => removeCacheFolder(opts.cacheDir));
|
|
24
|
-
|
|
25
|
-
firstReqIps.forEach(ip => {
|
|
26
|
-
it(`should request geo for IP: "${ip}"`, async () => {
|
|
27
|
-
await ip2geo({ip, ...opts});
|
|
28
|
-
});
|
|
29
|
-
});
|
|
30
|
-
|
|
31
|
-
it(`should have ${opts.cacheMapMaxEntries} correct cache entries`, () => {
|
|
32
|
-
assert.equal(opts.cacheMap.size, opts.cacheMapMaxEntries);
|
|
33
|
-
assert.deepEqual([...opts.cacheMap.keys()], firstReqIps.slice(-opts.cacheMapMaxEntries));
|
|
34
|
-
});
|
|
35
|
-
|
|
36
|
-
secondReqIps.forEach(ip => {
|
|
37
|
-
it(`should request geo for IP: "${ip}"`, async () => {
|
|
38
|
-
await ip2geo({ip, ...opts});
|
|
39
|
-
});
|
|
40
|
-
});
|
|
41
|
-
|
|
42
|
-
it(`should have ${opts.cacheMapMaxEntries} correct cache entries`, () => {
|
|
43
|
-
assert.equal(opts.cacheMap.size, opts.cacheMapMaxEntries);
|
|
44
|
-
|
|
45
|
-
assert.deepEqual(
|
|
46
|
-
[...opts.cacheMap.keys()],
|
|
47
|
-
[firstReqIps, secondReqIps].flat().slice(-opts.cacheMapMaxEntries),
|
|
48
|
-
);
|
|
49
|
-
});
|
|
50
|
-
});
|
package/tests/cache-map-off.js
DELETED
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
import assert from 'node:assert/strict';
|
|
2
|
-
|
|
3
|
-
import {describe, it} from 'mocha';
|
|
4
|
-
|
|
5
|
-
import {cacheStorage, ip2geo} from '../app/api.js';
|
|
6
|
-
|
|
7
|
-
import {getCurrentFilename, getTestFolder} from './helpers/path.js';
|
|
8
|
-
import {REQUEST_IPV4_MAP_OFF_ONLY} 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
|
-
cacheMapMaxEntries: 0,
|
|
17
|
-
};
|
|
18
|
-
|
|
19
|
-
it('should remove fs cache dir if exist', () => removeCacheFolder(opts.cacheDir));
|
|
20
|
-
|
|
21
|
-
it(`should return correct response for IP: "${REQUEST_IPV4_MAP_OFF_ONLY.ip}"`, async () => {
|
|
22
|
-
const data = await ip2geo({ip: REQUEST_IPV4_MAP_OFF_ONLY.ip, ...opts});
|
|
23
|
-
assert.deepEqual(data, REQUEST_IPV4_MAP_OFF_ONLY);
|
|
24
|
-
});
|
|
25
|
-
|
|
26
|
-
it('should have cache file', () =>
|
|
27
|
-
checkCacheFile({
|
|
28
|
-
...opts,
|
|
29
|
-
response: REQUEST_IPV4_MAP_OFF_ONLY,
|
|
30
|
-
}));
|
|
31
|
-
|
|
32
|
-
it('should not have cache entries', () => {
|
|
33
|
-
assert.equal(cacheStorage.size, 0);
|
|
34
|
-
});
|
|
35
|
-
});
|
package/tests/default.js
DELETED
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
import assert from 'node:assert/strict';
|
|
2
|
-
|
|
3
|
-
import {describe, it} from 'mocha';
|
|
4
|
-
|
|
5
|
-
import {cacheStorage, ip2geo} from '../app/api.js';
|
|
6
|
-
|
|
7
|
-
import {getCurrentFilename} 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
|
-
it('should remove fs cache dir if exist', () => removeCacheFolder());
|
|
15
|
-
|
|
16
|
-
describe('with ip arg', () => {
|
|
17
|
-
it(`should return correct response for IP: "${REQUEST_IPV4.ip}"`, async () => {
|
|
18
|
-
const data = await ip2geo({ip: REQUEST_IPV4.ip});
|
|
19
|
-
assert.deepEqual(data, REQUEST_IPV4);
|
|
20
|
-
});
|
|
21
|
-
|
|
22
|
-
it('should have cache file', () =>
|
|
23
|
-
checkCacheFile({
|
|
24
|
-
response: REQUEST_IPV4,
|
|
25
|
-
}));
|
|
26
|
-
|
|
27
|
-
it('should have 1 correct cache entry', () => {
|
|
28
|
-
assert.equal(cacheStorage.size, 1);
|
|
29
|
-
assert.deepEqual(cacheStorage.get(REQUEST_IPV4.ip), REQUEST_IPV4);
|
|
30
|
-
});
|
|
31
|
-
});
|
|
32
|
-
|
|
33
|
-
describe('without ip arg', () => {
|
|
34
|
-
let data;
|
|
35
|
-
|
|
36
|
-
it('should request geoip without ip arg', async () => {
|
|
37
|
-
data = await ip2geo();
|
|
38
|
-
});
|
|
39
|
-
|
|
40
|
-
Object.keys(REQUEST_IPV4).forEach(key => {
|
|
41
|
-
it(`should have "${key}" in request response`, () => {
|
|
42
|
-
assert.ok(Object.hasOwn(data, key));
|
|
43
|
-
});
|
|
44
|
-
});
|
|
45
|
-
|
|
46
|
-
it('should not have extra keys in request response', () => {
|
|
47
|
-
assert.deepEqual(Object.keys(data), Object.keys(REQUEST_IPV4));
|
|
48
|
-
});
|
|
49
|
-
|
|
50
|
-
it('should have 2 cache entries', () => {
|
|
51
|
-
assert.equal(cacheStorage.size, 2);
|
|
52
|
-
assert.deepEqual(cacheStorage.get(REQUEST_IPV4.ip), REQUEST_IPV4);
|
|
53
|
-
});
|
|
54
|
-
});
|
|
55
|
-
});
|
package/tests/helpers/path.js
DELETED
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import path from 'node:path';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* @param {string} file Import.meta.url
|
|
5
|
-
* @returns {string}
|
|
6
|
-
*/
|
|
7
|
-
export const getCurrentFilename = file => path.basename(file, '.js');
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* @param {string} file
|
|
11
|
-
* @returns {string}
|
|
12
|
-
*/
|
|
13
|
-
export const getTestFolder = file => path.join('.geoip', file);
|
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
import assert from 'node:assert/strict';
|
|
2
|
-
|
|
3
|
-
import {describe, it} from 'mocha';
|
|
4
|
-
|
|
5
|
-
import {ip2geo} from '../app/api.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
|
-
requestsCount: 5,
|
|
18
|
-
};
|
|
19
|
-
|
|
20
|
-
it('should remove fs cache dir if exist', () => removeCacheFolder(opts.cacheDir));
|
|
21
|
-
|
|
22
|
-
Array.from({length: opts.requestsCount}).forEach(() => {
|
|
23
|
-
it(`should return correct response for IP: "${REQUEST_IPV4.ip}"`, async () => {
|
|
24
|
-
const data = await ip2geo({ip: REQUEST_IPV4.ip, ...opts});
|
|
25
|
-
assert.deepEqual(data, REQUEST_IPV4);
|
|
26
|
-
});
|
|
27
|
-
});
|
|
28
|
-
|
|
29
|
-
it('should have cache file', () =>
|
|
30
|
-
checkCacheFile({
|
|
31
|
-
...opts,
|
|
32
|
-
response: REQUEST_IPV4,
|
|
33
|
-
}));
|
|
34
|
-
|
|
35
|
-
it('should have 1 correct cache entry', () => {
|
|
36
|
-
assert.equal(opts.cacheMap.size, 1);
|
|
37
|
-
assert.deepEqual(opts.cacheMap.get(REQUEST_IPV4.ip), REQUEST_IPV4);
|
|
38
|
-
});
|
|
39
|
-
});
|
package/tests/ip-no-data.js
DELETED
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
import assert from 'node:assert/strict';
|
|
2
|
-
|
|
3
|
-
import {describe, it} from 'mocha';
|
|
4
|
-
|
|
5
|
-
import {ip2geo} from '../app/api.js';
|
|
6
|
-
|
|
7
|
-
import {getCurrentFilename, getTestFolder} from './helpers/path.js';
|
|
8
|
-
import {REQUEST_IPV4} from './shared/consts.js';
|
|
9
|
-
import {removeCacheFolder} from './shared/fs.js';
|
|
10
|
-
|
|
11
|
-
const testName = getCurrentFilename(import.meta.url);
|
|
12
|
-
|
|
13
|
-
describe(testName, () => {
|
|
14
|
-
const responses = [{ip: '10.10.10.10'}, {ip: '192.168.1.100'}];
|
|
15
|
-
|
|
16
|
-
const opts = {
|
|
17
|
-
cacheDir: getTestFolder(testName),
|
|
18
|
-
cacheMap: new Map(),
|
|
19
|
-
};
|
|
20
|
-
|
|
21
|
-
it('should remove fs cache dir if exist', () => removeCacheFolder(opts.cacheDir));
|
|
22
|
-
|
|
23
|
-
responses.forEach(response => {
|
|
24
|
-
Object.keys(REQUEST_IPV4).forEach(elem => {
|
|
25
|
-
if (elem !== 'ip') {
|
|
26
|
-
response[elem] = undefined;
|
|
27
|
-
}
|
|
28
|
-
});
|
|
29
|
-
|
|
30
|
-
it(`should return empty response for IP: "${response.ip}"`, async () => {
|
|
31
|
-
const data = await ip2geo({ip: response.ip, ...opts});
|
|
32
|
-
assert.deepEqual(data, response);
|
|
33
|
-
});
|
|
34
|
-
});
|
|
35
|
-
});
|
package/tests/ip-v6.js
DELETED
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
import assert from 'node:assert/strict';
|
|
2
|
-
|
|
3
|
-
import {describe, it} from 'mocha';
|
|
4
|
-
|
|
5
|
-
import {ip2geo} from '../app/api.js';
|
|
6
|
-
|
|
7
|
-
import {getCurrentFilename, getTestFolder} from './helpers/path.js';
|
|
8
|
-
import {REQUEST_IPV6} from './shared/consts.js';
|
|
9
|
-
import {checkCacheFile, removeCacheFolder} from './shared/fs.js';
|
|
10
|
-
|
|
11
|
-
const testName = getCurrentFilename(import.meta.url);
|
|
12
|
-
|
|
13
|
-
describe.skip(testName, () => {
|
|
14
|
-
const opts = {
|
|
15
|
-
cacheDir: getTestFolder(testName),
|
|
16
|
-
cacheMap: new Map(),
|
|
17
|
-
};
|
|
18
|
-
|
|
19
|
-
it('should remove fs cache dir if exist', () => removeCacheFolder(opts.cacheDir));
|
|
20
|
-
|
|
21
|
-
it(`should return correct response for IP: "${REQUEST_IPV6.ip}"`, async () => {
|
|
22
|
-
const data = await ip2geo({ip: REQUEST_IPV6.ip, ...opts});
|
|
23
|
-
assert.deepEqual(data, REQUEST_IPV6);
|
|
24
|
-
});
|
|
25
|
-
|
|
26
|
-
it('should have cache file', () =>
|
|
27
|
-
checkCacheFile({
|
|
28
|
-
...opts,
|
|
29
|
-
response: REQUEST_IPV6,
|
|
30
|
-
}));
|
|
31
|
-
});
|