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.
@@ -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 dateFns = require('date-fns');
10
- const fs = require('fs-extra');
11
- const stripAnsi = require('strip-ansi');
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 fs__default = /*#__PURE__*/_interopDefaultCompat(fs);
25
- const stripAnsi__default = /*#__PURE__*/_interopDefaultCompat(stripAnsi);
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
- const logName = (urlItem.name || urlItem.url).replace("https://", "").replace("http://", "").replace(/\//g, "-");
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
- const formatter = (options, params, payload) => {
164
- const { value, total } = params;
165
- const formatTime = options.formatTime || _defaultFormatTime__default;
166
- const formatBar = options.formatBar || _defaultFormatBar__default;
167
- const bar = formatBar(params.progress, options);
168
- const stopTime = params.stopTime || Date.now();
169
- const elapsedTime = Math.round((stopTime - params.startTime) / 1e3);
170
- const duration_formatted = formatTime(elapsedTime, options, 1);
171
- consola__default.debug(duration_formatted);
172
- if (!payload.type) {
173
- options = Object.assign({}, options, cliProgress__default.Presets.rect);
174
- Options__default.assignDerivedOptions(options);
175
- const bar2 = formatBar(params.progress, options);
176
- const { site } = payload;
177
- const url = payload.url || "";
178
- return `${bar2} ${value}/${total} | ${utils.colors.yellow(site || "MEODP Item")} | ${utils.colors.cyan(url || "URL")}`;
179
- } else {
180
- const { error_count, emoji, url, type } = payload;
181
- const errorInfo = error_count ? `\u274C${error_count} ` : "";
182
- return `${bar} \u2705${utils.colors.green(value)}/${total} ${errorInfo}| ${duration_formatted} | ${emoji} ${utils.colors.yellow(type)} | ${utils.colors.cyan(url)}`;
183
- }
184
- };
185
- const multiBar = new cliProgress__default.MultiBar({
186
- hideCursor: true,
187
- // format: '{bar} {percentage}% | ✅{value}/{total} ❌{error_count} | {duration_formatted} | {name}',
188
- format: formatter,
189
- barsize: 20,
190
- autopadding: true,
191
- barCompleteChar: "\u2588",
192
- barIncompleteChar: "\u2591",
193
- // important! redraw everything to avoid "empty" completed bars
194
- forceRedraw: true
195
- }, cliProgress__default.Presets.rect);
196
- const progressBarMap = /* @__PURE__ */ new Map();
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 = utils.colors.dim(`\u2502${utils.colors.blue(`${duration.toString().padStart(4, " ")}${utils.colors.white("ms")}`)} \u2502`);
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
- function createMEODPLogger() {
356
- return {
357
- _log: (...args) => {
358
- const allLogPath = path__default.resolve(MEODP.logFolder, "all.log");
359
- LocalLog.log(allLogPath, stripAnsi__default(args.join(" ")));
360
- },
361
- log: (...args) => {
362
- const content = formatArgs(args);
363
- consola__default.log(content);
364
- MEODP.logger._log(content);
365
- },
366
- inner: (...args) => {
367
- const content = formatArgs(args);
368
- consola__default.log(COLORFUL_SYMBOLS.line, " ", content);
369
- MEODP.logger._log(COLORFUL_SYMBOLS.line, " ", content);
370
- },
371
- start: (...args) => {
372
- const content = formatArgs(args);
373
- consola__default.start(content);
374
- MEODP.logger._log(COLORFUL_SYMBOLS.start, content);
375
- },
376
- success: (...args) => {
377
- const content = formatArgs(args);
378
- consola__default.success(content);
379
- MEODP.logger._log(COLORFUL_SYMBOLS.success, content);
380
- },
381
- info: (...args) => {
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
- function createWinstonLogger() {
401
- const allLogPath = path__default.resolve(MEODP.logFolder, "all.log");
402
- const errorLogPath = path__default.resolve(MEODP.logFolder, "error.log");
403
- const customFormats = [
404
- winston__default.format.timestamp({
405
- format: "YYYY-MM-DD HH:mm:ss"
406
- })
407
- // winston.format.colorize(),
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 duration = Date.now() - startTime;
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 statusCode = res?.status() || 0;
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.log(COLORFUL_SYMBOLS.line, " ", utils.colors.green(`[${statusCode}]`), utils.colors.cyan(url), utils.colors.dim(`(in ${((Date.now() - startTime) / 1e3).toFixed(2)}s)`));
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
- const duration = (Date.now() - startTime) / 1e3;
627
- const statusText = res?.statusText();
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}s)`),
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, `Timeout: ${utils.colors.underline(url2)}`);
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
- if (urlMapValues.every((value) => value.response?.status() && value.response?.status() < 400) && noModuleAssetsPassed) {
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(`Done in ${duration / 1e3}s.`);
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;