meodp 0.0.5 → 0.0.7
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/README.md +5 -0
- package/bin/index.mjs +0 -0
- package/dist/cli/index.cjs +168 -18
- package/dist/cli/index.mjs +154 -7
- package/dist/index.cjs +39 -36
- package/dist/index.d.cts +89 -3
- package/dist/index.d.mts +89 -3
- package/dist/index.d.ts +89 -3
- package/dist/index.mjs +9 -8
- package/dist/shared/{meodp.f86a1a9f.mjs → meodp.5489574b.mjs} +313 -191
- package/dist/shared/{meodp.e8cfff87.cjs → meodp.9bf8b8ff.cjs} +319 -195
- package/package.json +6 -2
|
@@ -1,37 +1,73 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
const consola = require('consola');
|
|
4
|
-
const PQueue = require('p-queue');
|
|
5
3
|
const utils = require('consola/utils');
|
|
6
4
|
const playwright = require('playwright');
|
|
7
5
|
const path = require('node:path');
|
|
8
6
|
const process = require('node:process');
|
|
9
|
-
const
|
|
10
|
-
const
|
|
11
|
-
const
|
|
12
|
-
const winston = require('winston');
|
|
7
|
+
const consola = require('consola');
|
|
8
|
+
const node = require('lowdb/node');
|
|
9
|
+
const PQueue = require('p-queue');
|
|
13
10
|
const cliProgress = require('cli-progress');
|
|
14
11
|
const Options = require('cli-progress/lib/options.js');
|
|
15
12
|
const _defaultFormatBar = require('cli-progress/lib/format-bar.js');
|
|
16
13
|
const _defaultFormatTime = require('cli-progress/lib/format-time.js');
|
|
14
|
+
const dateFns = require('date-fns');
|
|
15
|
+
const fs = require('fs-extra');
|
|
16
|
+
const stripAnsi = require('strip-ansi');
|
|
17
|
+
const winston = require('winston');
|
|
17
18
|
|
|
18
19
|
function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e.default : e; }
|
|
19
20
|
|
|
20
|
-
const consola__default = /*#__PURE__*/_interopDefaultCompat(consola);
|
|
21
|
-
const PQueue__default = /*#__PURE__*/_interopDefaultCompat(PQueue);
|
|
22
21
|
const path__default = /*#__PURE__*/_interopDefaultCompat(path);
|
|
23
22
|
const process__default = /*#__PURE__*/_interopDefaultCompat(process);
|
|
24
|
-
const
|
|
25
|
-
const
|
|
26
|
-
const winston__default = /*#__PURE__*/_interopDefaultCompat(winston);
|
|
23
|
+
const consola__default = /*#__PURE__*/_interopDefaultCompat(consola);
|
|
24
|
+
const PQueue__default = /*#__PURE__*/_interopDefaultCompat(PQueue);
|
|
27
25
|
const cliProgress__default = /*#__PURE__*/_interopDefaultCompat(cliProgress);
|
|
28
26
|
const Options__default = /*#__PURE__*/_interopDefaultCompat(Options);
|
|
29
27
|
const _defaultFormatBar__default = /*#__PURE__*/_interopDefaultCompat(_defaultFormatBar);
|
|
30
28
|
const _defaultFormatTime__default = /*#__PURE__*/_interopDefaultCompat(_defaultFormatTime);
|
|
29
|
+
const fs__default = /*#__PURE__*/_interopDefaultCompat(fs);
|
|
30
|
+
const stripAnsi__default = /*#__PURE__*/_interopDefaultCompat(stripAnsi);
|
|
31
|
+
const winston__default = /*#__PURE__*/_interopDefaultCompat(winston);
|
|
31
32
|
|
|
32
33
|
const siteUrlMap = /* @__PURE__ */ new Map();
|
|
33
34
|
const PQueueMap = /* @__PURE__ */ new Map();
|
|
34
35
|
|
|
36
|
+
const formatter = (options, params, payload) => {
|
|
37
|
+
const { value, total } = params;
|
|
38
|
+
const formatTime = options.formatTime || _defaultFormatTime__default;
|
|
39
|
+
const formatBar = options.formatBar || _defaultFormatBar__default;
|
|
40
|
+
const bar = formatBar(params.progress, options);
|
|
41
|
+
const stopTime = params.stopTime || Date.now();
|
|
42
|
+
const elapsedTime = Math.round((stopTime - params.startTime) / 1e3);
|
|
43
|
+
const duration_formatted = formatTime(elapsedTime, options, 1);
|
|
44
|
+
consola__default.debug(duration_formatted);
|
|
45
|
+
if (!payload.type) {
|
|
46
|
+
options = Object.assign({}, options, cliProgress__default.Presets.rect);
|
|
47
|
+
Options__default.assignDerivedOptions(options);
|
|
48
|
+
const bar2 = formatBar(params.progress, options);
|
|
49
|
+
const { site } = payload;
|
|
50
|
+
const url = payload.url || "";
|
|
51
|
+
return `${bar2} ${value}/${total} | ${utils.colors.yellow(site || "MEODP Item")} | ${utils.colors.cyan(url || "URL")}`;
|
|
52
|
+
} else {
|
|
53
|
+
const { error_count, emoji, url, type } = payload;
|
|
54
|
+
const errorInfo = error_count ? `\u274C${error_count} ` : "";
|
|
55
|
+
return `${bar} \u2705${utils.colors.green(value)}/${total} ${errorInfo}| ${duration_formatted} | ${emoji} ${utils.colors.yellow(type)} | ${utils.colors.cyan(url)}`;
|
|
56
|
+
}
|
|
57
|
+
};
|
|
58
|
+
const multiBar = new cliProgress__default.MultiBar({
|
|
59
|
+
hideCursor: true,
|
|
60
|
+
// format: '{bar} {percentage}% | ✅{value}/{total} ❌{error_count} | {duration_formatted} | {name}',
|
|
61
|
+
format: formatter,
|
|
62
|
+
barsize: 20,
|
|
63
|
+
autopadding: true,
|
|
64
|
+
barCompleteChar: "\u2588",
|
|
65
|
+
barIncompleteChar: "\u2591",
|
|
66
|
+
// important! redraw everything to avoid "empty" completed bars
|
|
67
|
+
forceRedraw: true
|
|
68
|
+
}, cliProgress__default.Presets.rect);
|
|
69
|
+
const progressBarMap = /* @__PURE__ */ new Map();
|
|
70
|
+
|
|
35
71
|
var __defProp$1 = Object.defineProperty;
|
|
36
72
|
var __defNormalProp$1 = (obj, key, value) => key in obj ? __defProp$1(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
37
73
|
var __publicField$1 = (obj, key, value) => {
|
|
@@ -81,7 +117,11 @@ const _LocalLog = class _LocalLog {
|
|
|
81
117
|
* @desc append log
|
|
82
118
|
*/
|
|
83
119
|
static async SiteLog(urlItem, ...args) {
|
|
84
|
-
|
|
120
|
+
let id = urlItem.name || urlItem.url;
|
|
121
|
+
if (id.endsWith("/")) {
|
|
122
|
+
id = id.slice(0, -1);
|
|
123
|
+
}
|
|
124
|
+
const logName = id.replace("https://", "").replace("http://", "").replace(/\//g, "-");
|
|
85
125
|
const logPath = path__default.resolve(this.logFolder, urlItem.type, `${logName}.log`);
|
|
86
126
|
await _LocalLog.log(logPath, ...args);
|
|
87
127
|
}
|
|
@@ -160,57 +200,132 @@ const COLORFUL_SYMBOLS = {
|
|
|
160
200
|
line: utils.colors.dim(RAW_SYMBOLS.line)
|
|
161
201
|
};
|
|
162
202
|
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
const
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
203
|
+
function createMEODPLogger() {
|
|
204
|
+
return {
|
|
205
|
+
_log: (...args) => {
|
|
206
|
+
const allLogPath = path__default.resolve(MEODP.logFolder, "all.log");
|
|
207
|
+
LocalLog.log(allLogPath, stripAnsi__default(args.join(" ")));
|
|
208
|
+
},
|
|
209
|
+
log: (...args) => {
|
|
210
|
+
const content = formatArgs(args);
|
|
211
|
+
consola__default.log(content);
|
|
212
|
+
MEODP.logger._log(content);
|
|
213
|
+
},
|
|
214
|
+
inner: (...args) => {
|
|
215
|
+
const content = formatArgs(args);
|
|
216
|
+
consola__default.log(COLORFUL_SYMBOLS.line, " ", content);
|
|
217
|
+
MEODP.logger._log(COLORFUL_SYMBOLS.line, " ", content);
|
|
218
|
+
},
|
|
219
|
+
start: (...args) => {
|
|
220
|
+
const content = formatArgs(args);
|
|
221
|
+
consola__default.start(content);
|
|
222
|
+
MEODP.logger._log(COLORFUL_SYMBOLS.start, content);
|
|
223
|
+
},
|
|
224
|
+
success: (...args) => {
|
|
225
|
+
const content = formatArgs(args);
|
|
226
|
+
consola__default.success(content);
|
|
227
|
+
MEODP.logger._log(COLORFUL_SYMBOLS.success, content);
|
|
228
|
+
},
|
|
229
|
+
info: (...args) => {
|
|
230
|
+
const content = formatArgs(args);
|
|
231
|
+
consola__default.info(content);
|
|
232
|
+
MEODP.logger._log(COLORFUL_SYMBOLS.info, content);
|
|
233
|
+
},
|
|
234
|
+
warn: (...args) => {
|
|
235
|
+
const content = formatArgs(args);
|
|
236
|
+
consola__default.warn(content);
|
|
237
|
+
MEODP.logger._log(COLORFUL_SYMBOLS.warn, content);
|
|
238
|
+
},
|
|
239
|
+
error: (...args) => {
|
|
240
|
+
const content = formatArgs(args);
|
|
241
|
+
consola__default.log(COLORFUL_SYMBOLS.error, content);
|
|
242
|
+
MEODP.logger._log(COLORFUL_SYMBOLS.error, content);
|
|
243
|
+
MEODP.wLogger.error(content);
|
|
244
|
+
}
|
|
245
|
+
};
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
function createWinstonLogger() {
|
|
249
|
+
const allLogPath = path__default.resolve(MEODP.logFolder, "all.log");
|
|
250
|
+
const errorLogPath = path__default.resolve(MEODP.logFolder, "error.log");
|
|
251
|
+
const customFormats = [
|
|
252
|
+
winston__default.format.timestamp({
|
|
253
|
+
format: "YYYY-MM-DD HH:mm:ss"
|
|
254
|
+
})
|
|
255
|
+
// winston.format.colorize(),
|
|
256
|
+
// winston.format.errors({ stack: true }),
|
|
257
|
+
// winston.format.json(),
|
|
258
|
+
// winston.format.simple(),
|
|
259
|
+
// winston.format.uncolorize(),
|
|
260
|
+
];
|
|
261
|
+
customFormats.push(
|
|
262
|
+
winston__default.format.printf(({ level, message, timestamp, service }) => {
|
|
263
|
+
const content = [
|
|
264
|
+
timestamp,
|
|
265
|
+
`[${service}]`,
|
|
266
|
+
level.toUpperCase(),
|
|
267
|
+
message
|
|
268
|
+
];
|
|
269
|
+
return content.join(" ");
|
|
270
|
+
})
|
|
271
|
+
);
|
|
272
|
+
const customTransports = [
|
|
273
|
+
new winston__default.transports.File({
|
|
274
|
+
filename: errorLogPath,
|
|
275
|
+
level: "error"
|
|
276
|
+
}),
|
|
277
|
+
new winston__default.transports.File({
|
|
278
|
+
filename: allLogPath
|
|
279
|
+
// level: 'info',
|
|
280
|
+
})
|
|
281
|
+
];
|
|
282
|
+
return winston__default.createLogger({
|
|
283
|
+
level: "info",
|
|
284
|
+
format: winston__default.format.combine(...customFormats),
|
|
285
|
+
defaultMeta: { service: "MEODP" },
|
|
286
|
+
transports: customTransports,
|
|
287
|
+
exitOnError: false
|
|
288
|
+
});
|
|
289
|
+
}
|
|
197
290
|
|
|
198
291
|
function formatArgs(args) {
|
|
199
292
|
return args.join(" ");
|
|
200
293
|
}
|
|
294
|
+
const TIME_COLOR = {
|
|
295
|
+
fast: utils.colors.green,
|
|
296
|
+
medium: utils.colors.yellow,
|
|
297
|
+
slow: utils.colors.red
|
|
298
|
+
};
|
|
299
|
+
function getFormattedDuration(duration) {
|
|
300
|
+
const durationText = `${(duration / 1e3).toString()}s`;
|
|
301
|
+
let type;
|
|
302
|
+
if (duration < 500) {
|
|
303
|
+
type = "fast";
|
|
304
|
+
} else if (duration < 3e3) {
|
|
305
|
+
type = "medium";
|
|
306
|
+
} else {
|
|
307
|
+
type = "slow";
|
|
308
|
+
}
|
|
309
|
+
return TIME_COLOR[type](durationText);
|
|
310
|
+
}
|
|
201
311
|
function getFormattedDataFromResponse(res) {
|
|
202
312
|
const statusCode = res?.status();
|
|
203
313
|
const statusText = res?.statusText();
|
|
204
314
|
const statusInfo = statusText ? `${statusCode?.toString()} ${statusText}` : statusCode?.toString();
|
|
315
|
+
const statusInfoText = statusCode >= 400 ? utils.colors.red(`[${statusInfo}]`) : utils.colors.green(`[${statusInfo}]`);
|
|
205
316
|
const req = res.request();
|
|
206
|
-
const duration = req.timing().responseEnd - req.timing().requestStart;
|
|
207
|
-
const durationText =
|
|
317
|
+
const duration = Math.round(req.timing().responseEnd - req.timing().requestStart);
|
|
318
|
+
const durationText = `${COLORFUL_SYMBOLS.line} ${getFormattedDuration(duration)} ${COLORFUL_SYMBOLS.line}`;
|
|
208
319
|
return {
|
|
320
|
+
/**
|
|
321
|
+
* 四舍五入 ms
|
|
322
|
+
*/
|
|
209
323
|
duration,
|
|
210
324
|
durationText,
|
|
211
325
|
statusCode,
|
|
212
326
|
statusText,
|
|
213
327
|
statusInfo,
|
|
328
|
+
statusInfoText,
|
|
214
329
|
linkText: utils.colors.dim(res.url())
|
|
215
330
|
};
|
|
216
331
|
}
|
|
@@ -352,92 +467,62 @@ function getMEODPUrlItemInfo(urlItem) {
|
|
|
352
467
|
};
|
|
353
468
|
}
|
|
354
469
|
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
const content = formatArgs(args);
|
|
383
|
-
consola__default.info(content);
|
|
384
|
-
MEODP.logger._log(COLORFUL_SYMBOLS.info, content);
|
|
385
|
-
},
|
|
386
|
-
warn: (...args) => {
|
|
387
|
-
const content = formatArgs(args);
|
|
388
|
-
consola__default.warn(content);
|
|
389
|
-
MEODP.logger._log(COLORFUL_SYMBOLS.warn, content);
|
|
390
|
-
},
|
|
391
|
-
error: (...args) => {
|
|
392
|
-
const content = formatArgs(args);
|
|
393
|
-
consola__default.log(COLORFUL_SYMBOLS.error, content);
|
|
394
|
-
MEODP.logger._log(COLORFUL_SYMBOLS.error, content);
|
|
395
|
-
MEODP.wLogger.error(content);
|
|
470
|
+
const defaultMEODPConfig = {
|
|
471
|
+
urls: [],
|
|
472
|
+
concurrency: 10,
|
|
473
|
+
log: {
|
|
474
|
+
type: "raw",
|
|
475
|
+
file: true
|
|
476
|
+
}
|
|
477
|
+
};
|
|
478
|
+
function defineConfig(config) {
|
|
479
|
+
return config;
|
|
480
|
+
}
|
|
481
|
+
async function runByConfig(config) {
|
|
482
|
+
const { urls, debug } = config;
|
|
483
|
+
consola__default.level = debug ? 5 : 3;
|
|
484
|
+
const queue = new PQueue__default({
|
|
485
|
+
concurrency: config.concurrency
|
|
486
|
+
});
|
|
487
|
+
if (config.log?.type === "progress") {
|
|
488
|
+
for (const urlItem of urls) {
|
|
489
|
+
const { type, url, emoji } = getMEODPUrlItemInfo(urlItem);
|
|
490
|
+
const bar = multiBar.create(1, 0, {
|
|
491
|
+
emoji,
|
|
492
|
+
url,
|
|
493
|
+
type,
|
|
494
|
+
error_count: 0
|
|
495
|
+
});
|
|
496
|
+
progressBarMap.set(url, bar);
|
|
396
497
|
}
|
|
397
|
-
|
|
498
|
+
const curBar = multiBar.create(1, 0, {
|
|
499
|
+
name: "CURRENT"
|
|
500
|
+
});
|
|
501
|
+
progressBarMap.set("CURRENT", curBar);
|
|
502
|
+
}
|
|
503
|
+
const browser = await getBrowser();
|
|
504
|
+
for (const urlItem of urls) {
|
|
505
|
+
await queue.add(async () => {
|
|
506
|
+
await checkMEODPUrl(urlItem);
|
|
507
|
+
});
|
|
508
|
+
}
|
|
509
|
+
await queue.onIdle();
|
|
510
|
+
if (config.log?.type === "progress") {
|
|
511
|
+
multiBar.stop();
|
|
512
|
+
}
|
|
513
|
+
await browser.close();
|
|
514
|
+
consola__default.debug("browser closed");
|
|
515
|
+
return true;
|
|
398
516
|
}
|
|
399
517
|
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
// winston.format.errors({ stack: true }),
|
|
409
|
-
// winston.format.json(),
|
|
410
|
-
// winston.format.simple(),
|
|
411
|
-
// winston.format.uncolorize(),
|
|
412
|
-
];
|
|
413
|
-
customFormats.push(
|
|
414
|
-
winston__default.format.printf(({ level, message, timestamp, service }) => {
|
|
415
|
-
const content = [
|
|
416
|
-
timestamp,
|
|
417
|
-
`[${service}]`,
|
|
418
|
-
level.toUpperCase(),
|
|
419
|
-
message
|
|
420
|
-
];
|
|
421
|
-
return content.join(" ");
|
|
422
|
-
})
|
|
423
|
-
);
|
|
424
|
-
const customTransports = [
|
|
425
|
-
new winston__default.transports.File({
|
|
426
|
-
filename: errorLogPath,
|
|
427
|
-
level: "error"
|
|
428
|
-
}),
|
|
429
|
-
new winston__default.transports.File({
|
|
430
|
-
filename: allLogPath
|
|
431
|
-
// level: 'info',
|
|
432
|
-
})
|
|
433
|
-
];
|
|
434
|
-
return winston__default.createLogger({
|
|
435
|
-
level: "info",
|
|
436
|
-
format: winston__default.format.combine(...customFormats),
|
|
437
|
-
defaultMeta: { service: "MEODP" },
|
|
438
|
-
transports: customTransports,
|
|
439
|
-
exitOnError: false
|
|
440
|
-
});
|
|
518
|
+
const defaultData = {
|
|
519
|
+
config: defaultMEODPConfig,
|
|
520
|
+
sites: {}
|
|
521
|
+
};
|
|
522
|
+
async function createLowDB(rootDir = process__default.cwd()) {
|
|
523
|
+
const dbJsonPath = path__default.resolve(rootDir, "logs/meodp/db.json");
|
|
524
|
+
const db = await node.JSONFilePreset(dbJsonPath, defaultData);
|
|
525
|
+
return db;
|
|
441
526
|
}
|
|
442
527
|
|
|
443
528
|
var __defProp = Object.defineProperty;
|
|
@@ -462,6 +547,9 @@ const _MEODP = class _MEODP {
|
|
|
462
547
|
await LocalLog.init();
|
|
463
548
|
_MEODP.logFolder = LocalLog.logFolder || path__default.resolve(process__default.cwd(), "logs/meodp");
|
|
464
549
|
_MEODP.wLogger = createWinstonLogger();
|
|
550
|
+
const db = await createLowDB();
|
|
551
|
+
_MEODP.db = db;
|
|
552
|
+
await db.update((data) => data.config = _MEODP.config);
|
|
465
553
|
}
|
|
466
554
|
/**
|
|
467
555
|
* filter link by ignoreLinks
|
|
@@ -510,6 +598,7 @@ __publicField(_MEODP, "browser");
|
|
|
510
598
|
__publicField(_MEODP, "logFolder");
|
|
511
599
|
__publicField(_MEODP, "logger", createMEODPLogger());
|
|
512
600
|
__publicField(_MEODP, "wLogger");
|
|
601
|
+
__publicField(_MEODP, "db");
|
|
513
602
|
let MEODP = _MEODP;
|
|
514
603
|
|
|
515
604
|
async function getBrowser() {
|
|
@@ -558,7 +647,6 @@ async function checkUrlNomoduleAssets(page) {
|
|
|
558
647
|
if (!nomoduleUrl) {
|
|
559
648
|
return;
|
|
560
649
|
}
|
|
561
|
-
const startTime = Date.now();
|
|
562
650
|
const newPage = await context.newPage();
|
|
563
651
|
const response = await newPage.goto(nomoduleUrl);
|
|
564
652
|
if (!response) {
|
|
@@ -569,7 +657,8 @@ async function checkUrlNomoduleAssets(page) {
|
|
|
569
657
|
statusInfo,
|
|
570
658
|
linkText
|
|
571
659
|
} = getFormattedDataFromResponse(response);
|
|
572
|
-
const
|
|
660
|
+
const req = response.request();
|
|
661
|
+
const duration = req.timing().responseEnd - req.timing().requestStart;
|
|
573
662
|
const durationTxt = utils.colors.dim(`\u2502${utils.colors.blue(`${duration.toString().padStart(4, " ")}${utils.colors.white("ms")}`)} \u2502`);
|
|
574
663
|
if (statusCode >= 400) {
|
|
575
664
|
MEODP.logger.inner(" ", COLORFUL_SYMBOLS.error, utils.colors.red(statusInfo), durationTxt, linkText);
|
|
@@ -587,9 +676,31 @@ async function checkSiteUrl(url, options) {
|
|
|
587
676
|
const browser = await getBrowser();
|
|
588
677
|
const page = await browser.newPage();
|
|
589
678
|
const bar = progressBarMap.get(options.urlItem.url);
|
|
590
|
-
const startTime = Date.now();
|
|
591
679
|
const isExternalLink = MEODP.isExternalLink(url, options.urlItem);
|
|
592
680
|
const log = LocalLog.createLog(options.urlItem);
|
|
681
|
+
const siteData = MEODP.db.data.sites[options.urlItem.url];
|
|
682
|
+
const siteLinkItem = {
|
|
683
|
+
url,
|
|
684
|
+
statusCode: 0,
|
|
685
|
+
checkStatus: "pending",
|
|
686
|
+
success: 0,
|
|
687
|
+
failed: 0,
|
|
688
|
+
ignored: 0,
|
|
689
|
+
timeout: 0,
|
|
690
|
+
duration: 0,
|
|
691
|
+
total: 0,
|
|
692
|
+
requests: []
|
|
693
|
+
};
|
|
694
|
+
if (MEODP.isIgnoredLink(url)) {
|
|
695
|
+
siteUrlMap.set(url, {
|
|
696
|
+
statusCode: 0,
|
|
697
|
+
checkStatus: "ignored"
|
|
698
|
+
});
|
|
699
|
+
MEODP.logger.inner(`${utils.colors.dim(`[Ignored] ${utils.colors.underline(url)}`)}`);
|
|
700
|
+
siteData.ignored.push(url);
|
|
701
|
+
await MEODP.db.write();
|
|
702
|
+
return;
|
|
703
|
+
}
|
|
593
704
|
if (!MEODP.config.checkExternalLinks && isExternalLink) {
|
|
594
705
|
let res = null;
|
|
595
706
|
try {
|
|
@@ -597,18 +708,36 @@ async function checkSiteUrl(url, options) {
|
|
|
597
708
|
waitUntil: "load"
|
|
598
709
|
});
|
|
599
710
|
} catch (e) {
|
|
711
|
+
siteLinkItem.timeout = 1;
|
|
600
712
|
MEODP.logger.error(e);
|
|
601
713
|
}
|
|
602
714
|
if (!res)
|
|
603
715
|
return;
|
|
604
|
-
const
|
|
716
|
+
const {
|
|
717
|
+
statusCode,
|
|
718
|
+
statusInfoText,
|
|
719
|
+
duration,
|
|
720
|
+
durationText
|
|
721
|
+
} = getFormattedDataFromResponse(res);
|
|
605
722
|
const checkStatus = statusCode < 400 ? "passed" : "failed";
|
|
606
723
|
siteUrlMap.set(url, {
|
|
607
724
|
response: res,
|
|
608
725
|
statusCode,
|
|
609
726
|
checkStatus
|
|
610
727
|
});
|
|
611
|
-
MEODP.logger.
|
|
728
|
+
MEODP.logger.inner(statusInfoText, utils.colors.cyan(url), durationText);
|
|
729
|
+
if (statusCode >= 400) {
|
|
730
|
+
MEODP.wLogger.error(` ${statusInfoText} ${url} ${durationText}`);
|
|
731
|
+
}
|
|
732
|
+
siteLinkItem.statusCode = statusCode;
|
|
733
|
+
siteLinkItem.checkStatus = checkStatus;
|
|
734
|
+
siteLinkItem.duration = duration;
|
|
735
|
+
siteLinkItem.total = 1;
|
|
736
|
+
siteLinkItem.success = checkStatus === "passed" ? 1 : 0;
|
|
737
|
+
siteLinkItem.failed = checkStatus === "failed" ? 1 : 0;
|
|
738
|
+
siteLinkItem.requests = [];
|
|
739
|
+
siteData.links.push(siteLinkItem);
|
|
740
|
+
await MEODP.db.write();
|
|
612
741
|
return;
|
|
613
742
|
}
|
|
614
743
|
const urlMap = registerPageEvents(page, options.urlItem);
|
|
@@ -617,20 +746,41 @@ async function checkSiteUrl(url, options) {
|
|
|
617
746
|
waitUntil: "networkidle"
|
|
618
747
|
});
|
|
619
748
|
const statusCode = res?.status() || 0;
|
|
749
|
+
const statusText = res?.statusText();
|
|
750
|
+
const req = res?.request();
|
|
751
|
+
const duration = Math.round((req?.timing()?.responseEnd || 0) - (req?.timing()?.requestStart || 0));
|
|
620
752
|
siteUrlMap.set(url, {
|
|
621
753
|
response: res,
|
|
622
754
|
statusCode,
|
|
623
755
|
checkStatus: "goto"
|
|
624
756
|
});
|
|
625
757
|
const { success, failed, total, ignored, timeout } = parseUrlMap(urlMap);
|
|
626
|
-
|
|
627
|
-
|
|
758
|
+
siteLinkItem.title = await page.title();
|
|
759
|
+
siteLinkItem.statusCode = statusCode;
|
|
760
|
+
siteLinkItem.statusText = statusText;
|
|
761
|
+
siteLinkItem.checkStatus = "goto";
|
|
762
|
+
siteLinkItem.duration = duration;
|
|
763
|
+
siteLinkItem.total = total.count;
|
|
764
|
+
siteLinkItem.success = success.count;
|
|
765
|
+
siteLinkItem.failed = failed.count;
|
|
766
|
+
siteLinkItem.timeout = timeout.count;
|
|
767
|
+
siteLinkItem.ignored = ignored.count;
|
|
768
|
+
siteLinkItem.requests = Array.from(urlMap.values()).map((value) => {
|
|
769
|
+
const res2 = value.response;
|
|
770
|
+
return {
|
|
771
|
+
failed: value.failed,
|
|
772
|
+
ignored: value.ignored,
|
|
773
|
+
url: res2?.url(),
|
|
774
|
+
statusCode: res2?.status(),
|
|
775
|
+
statusText: res2?.statusText()
|
|
776
|
+
};
|
|
777
|
+
});
|
|
628
778
|
const logInfo = [
|
|
629
779
|
COLORFUL_SYMBOLS.line,
|
|
630
780
|
" ",
|
|
631
781
|
utils.colors.green(`[${statusCode}${statusText ? ` ${statusText}` : ""}]`),
|
|
632
782
|
utils.colors.cyan(url),
|
|
633
|
-
utils.colors.dim(`(in ${duration}
|
|
783
|
+
utils.colors.dim(`(in ${duration}ms)`),
|
|
634
784
|
total.text,
|
|
635
785
|
success.text,
|
|
636
786
|
failed.text,
|
|
@@ -640,36 +790,41 @@ async function checkSiteUrl(url, options) {
|
|
|
640
790
|
MEODP.logger.log(...logInfo);
|
|
641
791
|
log(...logInfo);
|
|
642
792
|
log();
|
|
793
|
+
if (failed.count > 0) {
|
|
794
|
+
MEODP.wLogger.error(logInfo.join(" "));
|
|
795
|
+
}
|
|
643
796
|
if (MEODP.config.log?.type === "progress") {
|
|
644
797
|
bar?.update(success.count, {
|
|
645
798
|
value: utils.colors.green(success.count),
|
|
646
799
|
error_count: failed.count ? utils.colors.red(failed.count) : 0
|
|
647
800
|
});
|
|
648
|
-
} else {
|
|
649
801
|
}
|
|
650
802
|
} catch (e) {
|
|
651
803
|
MEODP.logger.error(e);
|
|
652
804
|
}
|
|
653
805
|
for (const [url2, info] of urlMap) {
|
|
654
806
|
if (!info.response && !info.ignored) {
|
|
655
|
-
MEODP.logger.log(COLORFUL_SYMBOLS.line, " ", COLORFUL_SYMBOLS.error,
|
|
807
|
+
MEODP.logger.log(COLORFUL_SYMBOLS.line, " ", COLORFUL_SYMBOLS.error, utils.colors.red("Timeout:"), utils.colors.underline(url2));
|
|
808
|
+
MEODP.wLogger.error(` Timeout: ${url2}`);
|
|
809
|
+
siteLinkItem.checkStatus = "timeout";
|
|
656
810
|
}
|
|
657
811
|
}
|
|
658
812
|
let noModuleAssetsPassed = true;
|
|
659
813
|
if (options.checkNoModule) {
|
|
660
814
|
noModuleAssetsPassed = await checkUrlNomoduleAssets(page);
|
|
661
815
|
}
|
|
662
|
-
const urlMapValues = Array.from(urlMap.values());
|
|
663
816
|
const siteUrlItem = siteUrlMap.get(url);
|
|
664
817
|
if (siteUrlItem) {
|
|
665
|
-
|
|
818
|
+
const isAllRequestsPassed = siteLinkItem.requests.filter((value) => !value.ignored).every((value) => value.statusCode && value.statusCode < 400);
|
|
819
|
+
if (isAllRequestsPassed && noModuleAssetsPassed) {
|
|
666
820
|
siteUrlItem.checkStatus = "passed";
|
|
667
|
-
const successCount = Array.from(siteUrlMap.values()).filter((value) => value.checkStatus === "passed").length;
|
|
668
|
-
bar?.update(successCount);
|
|
669
821
|
} else {
|
|
670
822
|
siteUrlItem.checkStatus = "failed";
|
|
671
823
|
}
|
|
824
|
+
siteLinkItem.checkStatus = siteUrlItem.checkStatus;
|
|
672
825
|
}
|
|
826
|
+
siteData.links.push(siteLinkItem);
|
|
827
|
+
await MEODP.db.write();
|
|
673
828
|
if (!isExternalLink) {
|
|
674
829
|
const queue = PQueueMap.get(url);
|
|
675
830
|
if (queue) {
|
|
@@ -690,6 +845,7 @@ async function checkSiteUrl(url, options) {
|
|
|
690
845
|
}
|
|
691
846
|
}
|
|
692
847
|
await page.close();
|
|
848
|
+
return siteLinkItem;
|
|
693
849
|
}
|
|
694
850
|
async function checkSite(props) {
|
|
695
851
|
const { url } = props;
|
|
@@ -706,11 +862,25 @@ async function checkSite(props) {
|
|
|
706
862
|
statusCode: 0,
|
|
707
863
|
checkStatus: "pending"
|
|
708
864
|
});
|
|
865
|
+
await MEODP.db.update((data) => {
|
|
866
|
+
data.sites[homeUrl] = {
|
|
867
|
+
name: props.name,
|
|
868
|
+
url: homeUrl,
|
|
869
|
+
checkStatus: "pending",
|
|
870
|
+
links: [],
|
|
871
|
+
ignored: []
|
|
872
|
+
};
|
|
873
|
+
});
|
|
709
874
|
bar?.setTotal(siteUrlMap.size);
|
|
710
|
-
await checkSiteUrl(homeUrl, {
|
|
875
|
+
const siteLinkItem = await checkSiteUrl(homeUrl, {
|
|
711
876
|
urlItem: props,
|
|
712
877
|
checkNoModule: true
|
|
713
878
|
});
|
|
879
|
+
await MEODP.db.update((data) => {
|
|
880
|
+
const siteItem = data.sites[homeUrl];
|
|
881
|
+
siteItem.title = siteLinkItem?.title;
|
|
882
|
+
siteItem.checkStatus = siteItem.links.every((link) => link.checkStatus === "passed") ? "passed" : "failed";
|
|
883
|
+
});
|
|
714
884
|
await queue.onIdle();
|
|
715
885
|
await page.close();
|
|
716
886
|
await context.close();
|
|
@@ -780,55 +950,7 @@ async function checkMEODPUrl(meodpUrl) {
|
|
|
780
950
|
const duration = Date.now() - startTime;
|
|
781
951
|
const bar = progressBarMap.get(meodpUrl.url);
|
|
782
952
|
bar?.stop();
|
|
783
|
-
MEODP.logger.success(
|
|
784
|
-
}
|
|
785
|
-
|
|
786
|
-
const defaultMEODPConfig = {
|
|
787
|
-
urls: [],
|
|
788
|
-
concurrency: 10,
|
|
789
|
-
log: {
|
|
790
|
-
type: "raw",
|
|
791
|
-
file: true
|
|
792
|
-
}
|
|
793
|
-
};
|
|
794
|
-
function defineConfig(config) {
|
|
795
|
-
return config;
|
|
796
|
-
}
|
|
797
|
-
async function runByConfig(config) {
|
|
798
|
-
const { urls, debug } = config;
|
|
799
|
-
consola__default.level = debug ? 5 : 3;
|
|
800
|
-
const queue = new PQueue__default({
|
|
801
|
-
concurrency: config.concurrency
|
|
802
|
-
});
|
|
803
|
-
if (config.log?.type === "progress") {
|
|
804
|
-
for (const urlItem of urls) {
|
|
805
|
-
const { type, url, emoji } = getMEODPUrlItemInfo(urlItem);
|
|
806
|
-
const bar = multiBar.create(1, 0, {
|
|
807
|
-
emoji,
|
|
808
|
-
url,
|
|
809
|
-
type,
|
|
810
|
-
error_count: 0
|
|
811
|
-
});
|
|
812
|
-
progressBarMap.set(url, bar);
|
|
813
|
-
}
|
|
814
|
-
const curBar = multiBar.create(1, 0, {
|
|
815
|
-
name: "CURRENT"
|
|
816
|
-
});
|
|
817
|
-
progressBarMap.set("CURRENT", curBar);
|
|
818
|
-
}
|
|
819
|
-
const browser = await getBrowser();
|
|
820
|
-
for (const urlItem of urls) {
|
|
821
|
-
await queue.add(async () => {
|
|
822
|
-
await checkMEODPUrl(urlItem);
|
|
823
|
-
});
|
|
824
|
-
}
|
|
825
|
-
await queue.onIdle();
|
|
826
|
-
if (config.log?.type === "progress") {
|
|
827
|
-
multiBar.stop();
|
|
828
|
-
}
|
|
829
|
-
await browser.close();
|
|
830
|
-
consola__default.debug("browser closed");
|
|
831
|
-
return true;
|
|
953
|
+
MEODP.logger.success(`\u{1F577}\uFE0F ${utils.colors.greenBright("[DONE]")} ${utils.colors.gray("in")} ${duration / 1e3}s.`);
|
|
832
954
|
}
|
|
833
955
|
|
|
834
956
|
exports.LocalLog = LocalLog;
|
|
@@ -839,6 +961,7 @@ exports.checkMEODPUrl = checkMEODPUrl;
|
|
|
839
961
|
exports.checkSite = checkSite;
|
|
840
962
|
exports.checkSiteUrl = checkSiteUrl;
|
|
841
963
|
exports.checkUrlNomoduleAssets = checkUrlNomoduleAssets;
|
|
964
|
+
exports.createLowDB = createLowDB;
|
|
842
965
|
exports.createMEODPLogger = createMEODPLogger;
|
|
843
966
|
exports.createWinstonLogger = createWinstonLogger;
|
|
844
967
|
exports.defaultMEODPConfig = defaultMEODPConfig;
|
|
@@ -847,6 +970,7 @@ exports.emojiMap = emojiMap;
|
|
|
847
970
|
exports.formatArgs = formatArgs;
|
|
848
971
|
exports.getBrowser = getBrowser;
|
|
849
972
|
exports.getFormattedDataFromResponse = getFormattedDataFromResponse;
|
|
973
|
+
exports.getFormattedDuration = getFormattedDuration;
|
|
850
974
|
exports.getMEODPUrlItemInfo = getMEODPUrlItemInfo;
|
|
851
975
|
exports.getSiteLinks = getSiteLinks;
|
|
852
976
|
exports.isLink = isLink;
|