@k03mad/ip2geo 9.3.0 → 9.4.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.
@@ -1,3 +1,7 @@
1
1
  {
2
- "eslint.experimental.useFlatConfig": true
2
+ "cSpell.words": [
3
+ "consts",
4
+ "geoip",
5
+ "nvmrc"
6
+ ]
3
7
  }
package/app/cli.js CHANGED
@@ -7,7 +7,7 @@ import {DEFAULT_CACHE_FILE_DIR, DEFAULT_CACHE_FILE_NEWLINE, DEFAULT_CACHE_FILE_S
7
7
  import {pruneCache} from './helpers/cache.js';
8
8
  import {codeText, nameText} from './helpers/colors.js';
9
9
 
10
- const {blue, red, green} = chalk;
10
+ const {blue, red, green, dim, bold} = chalk;
11
11
 
12
12
  const args = process.argv.slice(2);
13
13
  const argsExtra = args.filter(arg => !arg.startsWith('-'));
@@ -43,6 +43,7 @@ if (isHelp) {
43
43
 
44
44
  if (isPrune) {
45
45
  const cacheFolder = argsExtra[0] || DEFAULT_CACHE_FILE_DIR;
46
+ log(blue(cacheFolder));
46
47
 
47
48
  try {
48
49
  const {duplicates, empty, longLinesFiles} = await pruneCache(
@@ -51,27 +52,22 @@ if (isPrune) {
51
52
  DEFAULT_CACHE_FILE_NEWLINE,
52
53
  );
53
54
 
54
- const message = [
55
+ log([
55
56
  '',
56
- `Removed duplicate cache entries: ${green(duplicates)}`,
57
- `Removed empty cache entries: ${green(empty)}`,
58
- ];
59
-
60
- if (longLinesFiles.size > 0) {
61
- message.push(
62
- '',
63
- red('Something went wrong with these cache files (lines too long):'),
64
- ...[...longLinesFiles].map(elem => blue(`— ${elem}`)),
65
- );
57
+ green(`Removed duplicate cache entries: ${bold(duplicates.length)}`),
58
+ ...duplicates.map(elem => dim(`— ${elem}`)),
59
+ green(`Removed empty cache entries: ${bold(empty.length)}`),
60
+ ...empty.map(elem => dim(`— ${elem}`)),
61
+ ]);
62
+
63
+ if (longLinesFiles.length > 0) {
64
+ log([
65
+ red(`Required manual check, some cache files has too long lines: ${bold(longLinesFiles.length)}`),
66
+ ...longLinesFiles.map(({file, elem}) => dim(`— ${file}\n|— ${elem}`)),
67
+ ]);
66
68
  }
67
-
68
- log(message);
69
69
  } catch (err) {
70
- if (err.code !== 'ENOENT') {
71
- logErrorExit(err);
72
- }
73
-
74
- log(`Cache folder empty: ${cacheFolder}`);
70
+ logErrorExit(red(err));
75
71
  }
76
72
  } else {
77
73
  const output = argsExtra.length === 0
@@ -5,6 +5,8 @@ import _debug from 'debug';
5
5
 
6
6
  const debug = _debug('mad:geoip');
7
7
 
8
+ const ipRe = /((25[0-5]|((?:2[0-4]|1\d|[1-9])?)\d)\.?\b){4}/;
9
+
8
10
  const outputKeys = [
9
11
  'ip',
10
12
  'continent',
@@ -161,6 +163,19 @@ export const writeToMapCache = (body, cacheMap, cacheMapMaxEntries) => {
161
163
  export const pruneCache = async (cacheDir, cacheFileSeparator, cacheFileNewline) => {
162
164
  const files = await fs.readdir(cacheDir);
163
165
 
166
+ await Promise.all(files.map(async file => {
167
+ const fullFilePath = path.join(cacheDir, file);
168
+
169
+ const [stat, data] = await Promise.all([
170
+ fs.lstat(fullFilePath),
171
+ fs.readFile(fullFilePath, {encoding: 'utf8'}),
172
+ ]);
173
+
174
+ if (stat.isDirectory() || !ipRe.test(data)) {
175
+ throw new Error(`Folder has subfolders or files without IPs, wrong cache folder arg?\n${fullFilePath}`);
176
+ }
177
+ }));
178
+
164
179
  const cacheLineToNum = line => Number(
165
180
  line.split(cacheFileSeparator)[0]
166
181
  .split('.')
@@ -168,9 +183,8 @@ export const pruneCache = async (cacheDir, cacheFileSeparator, cacheFileNewline)
168
183
  .join(''),
169
184
  );
170
185
 
171
- let duplicates = 0;
172
- let empty = 0;
173
-
186
+ const duplicates = new Set();
187
+ const empty = [];
174
188
  const longLinesFiles = new Set();
175
189
 
176
190
  await Promise.all(files.map(async file => {
@@ -183,10 +197,14 @@ export const pruneCache = async (cacheDir, cacheFileSeparator, cacheFileNewline)
183
197
  const splitted = elem.split(cacheFileSeparator);
184
198
 
185
199
  if (splitted.length > outputKeys.length) {
186
- longLinesFiles.add(fullFilePath);
200
+ longLinesFiles.add({file: fullFilePath, elem});
201
+ }
202
+
203
+ if (splitted.filter(Boolean).length > 1) {
204
+ return true;
187
205
  }
188
206
 
189
- return splitted.filter(Boolean).length > 1;
207
+ empty.push(elem);
190
208
  });
191
209
 
192
210
  const uniq = [...new Set(dataArrRemoveEmpty)]
@@ -195,9 +213,13 @@ export const pruneCache = async (cacheDir, cacheFileSeparator, cacheFileNewline)
195
213
  const fileContent = uniq.join(cacheFileNewline).trim();
196
214
  await (fileContent ? fs.writeFile(fullFilePath, fileContent) : fs.rm(fullFilePath));
197
215
 
198
- empty += dataArr.length - dataArrRemoveEmpty.length;
199
- duplicates += dataArrRemoveEmpty.length - uniq.length;
216
+ dataArrRemoveEmpty
217
+ .forEach((elem, i, arr) => arr.indexOf(elem) !== i && duplicates.add(elem));
200
218
  }));
201
219
 
202
- return {duplicates, empty, longLinesFiles};
220
+ return {
221
+ duplicates: [...duplicates],
222
+ empty,
223
+ longLinesFiles: [...longLinesFiles],
224
+ };
203
225
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@k03mad/ip2geo",
3
- "version": "9.3.0",
3
+ "version": "9.4.0",
4
4
  "description": "GeoIP library",
5
5
  "maintainers": [
6
6
  "Kirill Molchanov <k03.mad@gmail.com"
@@ -20,7 +20,7 @@
20
20
  },
21
21
  "dependencies": {
22
22
  "@k03mad/request": "6.1.0",
23
- "@k03mad/simple-log": "2.3.0",
23
+ "@k03mad/simple-log": "3.0.0",
24
24
  "chalk": "5.3.0",
25
25
  "debug": "4.3.6"
26
26
  },