@promise-inc/ps-guard 0.1.0 → 0.2.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/README.md CHANGED
@@ -7,6 +7,8 @@ Lighthouse-based performance guard. Enforce Web Vitals thresholds in CI and loca
7
7
  Running Lighthouse manually is tedious and inconsistent. `ps-guard` wraps Lighthouse into an opinionated CLI and API with:
8
8
 
9
9
  - **Threshold enforcement** — fail CI if LCP, CLS, INP, TTFB, or FCP exceed your limits
10
+ - **Sitemap support** — audit all pages from a sitemap.xml automatically
11
+ - **HTML reports** — coverage-style visual reports with score bars and details
10
12
  - **Presets** — built-in configs for Next.js, landing pages, and marketing sites
11
13
  - **Fix hints** — actionable suggestions when a metric fails
12
14
  - **JSON output** — pipe results to dashboards or custom reporters
@@ -31,6 +33,18 @@ npx ps-guard --url https://example.com --json
31
33
 
32
34
  # CI mode (no colors)
33
35
  npx ps-guard --url https://example.com --ci
36
+
37
+ # Audit all pages from sitemap
38
+ npx ps-guard --sitemap https://example.com/sitemap.xml
39
+
40
+ # Sitemap with max URLs
41
+ npx ps-guard --sitemap https://example.com/sitemap.xml --max-urls 20
42
+
43
+ # Generate HTML report
44
+ npx ps-guard --url https://example.com --html
45
+
46
+ # Sitemap + HTML report in custom directory
47
+ npx ps-guard --sitemap https://example.com/sitemap.xml --html --report ./reports/
34
48
  ```
35
49
 
36
50
  ### Programmatic
@@ -53,7 +67,11 @@ if (!result.passed) {
53
67
 
54
68
  | Option | Description | Default |
55
69
  |--------|-------------|---------|
56
- | `--url <url>` | URL to audit (required) | — |
70
+ | `--url <url>` | URL to audit | — |
71
+ | `--sitemap <url>` | Sitemap URL to audit all pages | — |
72
+ | `--max-urls <n>` | Max URLs from sitemap | `50` |
73
+ | `--html` | Generate HTML report | `false` |
74
+ | `--report <dir>` | Output directory for HTML report | `./ps-guard-report` |
57
75
  | `-p, --preset <name>` | Use a built-in preset | — |
58
76
  | `--device <mobile\|desktop>` | Device emulation | `mobile` |
59
77
  | `--retries <n>` | Retry attempts | `1` |
@@ -61,6 +79,55 @@ if (!result.passed) {
61
79
  | `--ci` | No colors, clean output | `false` |
62
80
  | `-h, --help` | Show help | — |
63
81
 
82
+ > **Note:** Either `--url` or `--sitemap` is required.
83
+
84
+ ## Sitemap Auditing
85
+
86
+ Audit all pages from a `sitemap.xml` in a single command. ps-guard fetches the sitemap, extracts all URLs, and runs Lighthouse sequentially (reusing a single Chrome instance for performance).
87
+
88
+ ```bash
89
+ ps-guard --sitemap https://example.com/sitemap.xml
90
+ ```
91
+
92
+ Features:
93
+ - Supports sitemap index files (recursive, max 2 levels)
94
+ - Deduplicates URLs automatically
95
+ - `--max-urls` limits the number of URLs (default: 50)
96
+ - Progress output shows score per URL in real time
97
+ - If one URL fails, the audit continues with remaining URLs
98
+
99
+ Example output:
100
+ ```
101
+ Scanning 42 URLs from sitemap...
102
+
103
+ [1/42] ✔ 94 https://example.com/
104
+ [2/42] ✖ 67 https://example.com/about
105
+ [3/42] ✔ 91 https://example.com/pricing
106
+ ...
107
+
108
+ ✖ 3 of 42 URLs failed (avg score: 85)
109
+ ```
110
+
111
+ ## HTML Report
112
+
113
+ Generate a self-contained HTML report with visual score bars, summary cards, and collapsible details per URL.
114
+
115
+ ```bash
116
+ # Single URL
117
+ ps-guard --url https://example.com --html
118
+
119
+ # Sitemap with report in custom directory
120
+ ps-guard --sitemap https://example.com/sitemap.xml --html --report ./reports/
121
+ ```
122
+
123
+ The report includes:
124
+ - Summary cards (average score, worst score, pass/fail counts)
125
+ - URL overview table with scores
126
+ - Collapsible detail sections per URL with metric bars
127
+ - Lighthouse color coding (green/orange/red)
128
+
129
+ The report is written to `./ps-guard-report/index.html` by default (override with `--report <dir>`).
130
+
64
131
  ## Configuration
65
132
 
66
133
  Create a `ps-guard.config.json` (or `.js`/`.ts`) in your project root:
package/dist/cli.js CHANGED
@@ -7,6 +7,10 @@ const validator_1 = require("./validator");
7
7
  const reporter_1 = require("./reporter");
8
8
  const registry_1 = require("./presets/registry");
9
9
  const output_1 = require("./utils/output");
10
+ const progress_1 = require("./utils/progress");
11
+ const sitemap_1 = require("./sitemap");
12
+ const orchestrator_1 = require("./orchestrator");
13
+ const report_html_1 = require("./report-html");
10
14
  function parseArgs(args) {
11
15
  let url;
12
16
  let preset;
@@ -14,7 +18,11 @@ function parseArgs(args) {
14
18
  let json = false;
15
19
  let ci = false;
16
20
  let help = false;
21
+ let html = false;
17
22
  let retries;
23
+ let sitemap;
24
+ let report;
25
+ let maxUrls;
18
26
  for (let i = 0; i < args.length; i++) {
19
27
  const arg = args[i];
20
28
  if (arg === "--url") {
@@ -41,6 +49,9 @@ function parseArgs(args) {
41
49
  else if (arg === "--help" || arg === "-h") {
42
50
  help = true;
43
51
  }
52
+ else if (arg === "--html") {
53
+ html = true;
54
+ }
44
55
  else if (arg === "--retries") {
45
56
  const val = parseInt(args[i + 1], 10);
46
57
  if (!isNaN(val) && val > 0) {
@@ -48,8 +59,23 @@ function parseArgs(args) {
48
59
  }
49
60
  i++;
50
61
  }
62
+ else if (arg === "--sitemap") {
63
+ sitemap = args[i + 1];
64
+ i++;
65
+ }
66
+ else if (arg === "--report") {
67
+ report = args[i + 1];
68
+ i++;
69
+ }
70
+ else if (arg === "--max-urls") {
71
+ const val = parseInt(args[i + 1], 10);
72
+ if (!isNaN(val) && val > 0) {
73
+ maxUrls = val;
74
+ }
75
+ i++;
76
+ }
51
77
  }
52
- return { url, preset, device, json, ci, help, retries };
78
+ return { url, preset, device, json, ci, help, html, retries, sitemap, report, maxUrls };
53
79
  }
54
80
  function printHelp() {
55
81
  console.log(`
@@ -58,16 +84,21 @@ function printHelp() {
58
84
  \x1b[1mUsage:\x1b[0m
59
85
  npx ps-guard --url https://example.com
60
86
  npx ps-guard --url https://example.com --preset nextjs
61
- npx ps-guard --url https://example.com --json
87
+ npx ps-guard --sitemap https://example.com/sitemap.xml
88
+ npx ps-guard --url https://example.com --html
62
89
 
63
90
  \x1b[1mOptions:\x1b[0m
64
- --url <url> URL to audit (required)
65
- -p, --preset <name> Use a built-in preset
91
+ --url <url> URL to audit
92
+ --sitemap <url> Sitemap URL to audit all pages
93
+ --max-urls <n> Max URLs from sitemap (default: 50)
94
+ --html Generate HTML report
95
+ --report <dir> Output directory for HTML report (default: ./ps-guard-report)
96
+ -p, --preset <name> Use a built-in preset
66
97
  --device <mobile|desktop> Device emulation (default: mobile)
67
- --retries <n> Number of retry attempts (default: 1)
68
- --json Output results as JSON
69
- --ci CI mode (no colors, clean output)
70
- -h, --help Show this help message
98
+ --retries <n> Number of retry attempts (default: 1)
99
+ --json Output results as JSON
100
+ --ci CI mode (no colors, clean output)
101
+ -h, --help Show this help message
71
102
 
72
103
  \x1b[1mPresets:\x1b[0m
73
104
  ${registry_1.presetNames.join(", ")}
@@ -91,6 +122,7 @@ async function main() {
91
122
  }
92
123
  if (parsed.ci) {
93
124
  (0, output_1.setCIMode)(true);
125
+ (0, progress_1.setProgressCIMode)(true);
94
126
  }
95
127
  try {
96
128
  const cwd = process.cwd();
@@ -99,17 +131,48 @@ async function main() {
99
131
  preset: parsed.preset,
100
132
  device: parsed.device,
101
133
  retries: parsed.retries,
134
+ sitemap: parsed.sitemap,
135
+ report: parsed.report,
136
+ html: parsed.html || undefined,
137
+ maxUrls: parsed.maxUrls,
102
138
  });
103
- const lighthouseResult = await (0, runner_1.runLighthouse)(config);
104
- const result = (0, validator_1.validateResults)(lighthouseResult.lhr, config);
105
- if (parsed.json) {
106
- (0, reporter_1.reportJSON)(result);
139
+ const isSitemapMode = Boolean(config.sitemap);
140
+ const outputDir = config.report ?? "./ps-guard-report";
141
+ const shouldHtml = config.html ?? parsed.html;
142
+ if (isSitemapMode) {
143
+ const entries = await (0, sitemap_1.fetchSitemap)(config.sitemap);
144
+ const urls = entries.map((e) => e.url);
145
+ const multiResult = await (0, orchestrator_1.runMultiAudit)({ urls, config });
146
+ if (shouldHtml) {
147
+ const filePath = (0, report_html_1.writeHtmlReport)(multiResult, outputDir);
148
+ console.log(`\n HTML report: ${filePath}\n`);
149
+ }
150
+ if (parsed.json) {
151
+ (0, reporter_1.reportMultiJSON)(multiResult);
152
+ }
153
+ else if (!shouldHtml) {
154
+ (0, reporter_1.reportMultiHuman)(multiResult);
155
+ }
156
+ if (!multiResult.passed) {
157
+ process.exit(1);
158
+ }
107
159
  }
108
160
  else {
109
- (0, reporter_1.reportHuman)(result);
110
- }
111
- if (!result.passed) {
112
- process.exit(1);
161
+ const lighthouseResult = await (0, runner_1.runLighthouse)(config);
162
+ const result = (0, validator_1.validateResults)(lighthouseResult.lhr, config);
163
+ if (shouldHtml) {
164
+ const filePath = (0, report_html_1.writeHtmlReport)(result, outputDir);
165
+ console.log(`\n HTML report: ${filePath}\n`);
166
+ }
167
+ if (parsed.json) {
168
+ (0, reporter_1.reportJSON)(result);
169
+ }
170
+ else if (!shouldHtml) {
171
+ (0, reporter_1.reportHuman)(result);
172
+ }
173
+ if (!result.passed) {
174
+ process.exit(1);
175
+ }
113
176
  }
114
177
  }
115
178
  catch (error) {
package/dist/cli.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAqB,MAAM,SAAS,CAAC;AAmDhE,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC,CAWlE;AAED,wBAAgB,UAAU,CACxB,GAAG,EAAE,MAAM,EACX,SAAS,GAAE,OAAO,CAAC,aAAa,CAAM,GACrC,aAAa,CA6Bf"}
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAqB,MAAM,SAAS,CAAC;AAmDhE,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC,CAWlE;AAED,wBAAgB,UAAU,CACxB,GAAG,EAAE,MAAM,EACX,SAAS,GAAE,OAAO,CAAC,aAAa,CAAM,GACrC,aAAa,CAoCf"}
package/dist/config.js CHANGED
@@ -97,8 +97,10 @@ function loadConfig(cwd, overrides = {}) {
97
97
  if (presetName) {
98
98
  presetConfig = resolvePreset(presetName);
99
99
  }
100
+ const sitemap = overrides.sitemap ?? fileConfig.sitemap;
101
+ const url = overrides.url ?? fileConfig.url ?? "";
100
102
  const merged = {
101
- url: overrides.url ?? fileConfig.url ?? "",
103
+ url,
102
104
  device: overrides.device ?? fileConfig.device ?? presetConfig.device ?? DEFAULT_CONFIG.device,
103
105
  minScore: overrides.minScore ?? fileConfig.minScore ?? DEFAULT_CONFIG.minScore,
104
106
  thresholds: {
@@ -110,9 +112,13 @@ function loadConfig(cwd, overrides = {}) {
110
112
  failOnError: overrides.failOnError ?? fileConfig.failOnError ?? DEFAULT_CONFIG.failOnError,
111
113
  retries: overrides.retries ?? fileConfig.retries ?? DEFAULT_CONFIG.retries,
112
114
  preset: presetName,
115
+ sitemap,
116
+ report: overrides.report ?? fileConfig.report,
117
+ html: overrides.html ?? fileConfig.html,
118
+ maxUrls: overrides.maxUrls ?? fileConfig.maxUrls,
113
119
  };
114
- if (!merged.url) {
115
- throw new Error("URL is required. Use --url <url> or set it in config file.");
120
+ if (!merged.url && !merged.sitemap) {
121
+ throw new Error("URL or sitemap is required. Use --url <url> or --sitemap <url>.");
116
122
  }
117
123
  return merged;
118
124
  }
@@ -1 +1 @@
1
- {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -1,11 +1,14 @@
1
1
  import type { PSGuardConfig, PSGuardResult } from "./types";
2
2
  export { loadConfig, resolvePreset } from "./config";
3
- export { runLighthouse } from "./runner";
3
+ export { runLighthouse, launchChrome, runSingleAudit, killChrome } from "./runner";
4
4
  export { parseMetrics } from "./parser";
5
5
  export { validateResults } from "./validator";
6
- export { reportHuman, reportJSON } from "./reporter";
6
+ export { reportHuman, reportJSON, reportMultiHuman, reportMultiJSON } from "./reporter";
7
7
  export { getHints } from "./hints";
8
8
  export { presets, presetNames } from "./presets";
9
- export type { PSGuardConfig, PSGuardThresholds, MetricResult, PSGuardResult, Preset, } from "./types";
9
+ export { fetchSitemap } from "./sitemap";
10
+ export { runMultiAudit } from "./orchestrator";
11
+ export { generateHtmlReport, writeHtmlReport } from "./report-html";
12
+ export type { PSGuardConfig, PSGuardThresholds, MetricResult, PSGuardResult, PSGuardMultiResult, SitemapEntry, Preset, CLIArgs, } from "./types";
10
13
  export declare function runPSGuard(url: string, options?: Partial<Omit<PSGuardConfig, "url">>): Promise<PSGuardResult>;
11
14
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAE5D,OAAO,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACrD,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AACxC,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAC9C,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AACrD,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AACnC,OAAO,EAAE,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAEjD,YAAY,EACV,aAAa,EACb,iBAAiB,EACjB,YAAY,EACZ,aAAa,EACb,MAAM,GACP,MAAM,SAAS,CAAC;AAEjB,wBAAsB,UAAU,CAC9B,GAAG,EAAE,MAAM,EACX,OAAO,GAAE,OAAO,CAAC,IAAI,CAAC,aAAa,EAAE,KAAK,CAAC,CAAM,GAChD,OAAO,CAAC,aAAa,CAAC,CAIxB"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAE5D,OAAO,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACrD,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AACnF,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AACxC,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAC9C,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AACxF,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AACnC,OAAO,EAAE,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AACjD,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAC/C,OAAO,EAAE,kBAAkB,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAEpE,YAAY,EACV,aAAa,EACb,iBAAiB,EACjB,YAAY,EACZ,aAAa,EACb,kBAAkB,EAClB,YAAY,EACZ,MAAM,EACN,OAAO,GACR,MAAM,SAAS,CAAC;AAEjB,wBAAsB,UAAU,CAC9B,GAAG,EAAE,MAAM,EACX,OAAO,GAAE,OAAO,CAAC,IAAI,CAAC,aAAa,EAAE,KAAK,CAAC,CAAM,GAChD,OAAO,CAAC,aAAa,CAAC,CAIxB"}
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.presetNames = exports.presets = exports.getHints = exports.reportJSON = exports.reportHuman = exports.validateResults = exports.parseMetrics = exports.runLighthouse = exports.resolvePreset = exports.loadConfig = void 0;
3
+ exports.writeHtmlReport = exports.generateHtmlReport = exports.runMultiAudit = exports.fetchSitemap = exports.presetNames = exports.presets = exports.getHints = exports.reportMultiJSON = exports.reportMultiHuman = exports.reportJSON = exports.reportHuman = exports.validateResults = exports.parseMetrics = exports.killChrome = exports.runSingleAudit = exports.launchChrome = exports.runLighthouse = exports.resolvePreset = exports.loadConfig = void 0;
4
4
  exports.runPSGuard = runPSGuard;
5
5
  const config_1 = require("./config");
6
6
  const runner_1 = require("./runner");
@@ -10,6 +10,9 @@ Object.defineProperty(exports, "loadConfig", { enumerable: true, get: function (
10
10
  Object.defineProperty(exports, "resolvePreset", { enumerable: true, get: function () { return config_2.resolvePreset; } });
11
11
  var runner_2 = require("./runner");
12
12
  Object.defineProperty(exports, "runLighthouse", { enumerable: true, get: function () { return runner_2.runLighthouse; } });
13
+ Object.defineProperty(exports, "launchChrome", { enumerable: true, get: function () { return runner_2.launchChrome; } });
14
+ Object.defineProperty(exports, "runSingleAudit", { enumerable: true, get: function () { return runner_2.runSingleAudit; } });
15
+ Object.defineProperty(exports, "killChrome", { enumerable: true, get: function () { return runner_2.killChrome; } });
13
16
  var parser_1 = require("./parser");
14
17
  Object.defineProperty(exports, "parseMetrics", { enumerable: true, get: function () { return parser_1.parseMetrics; } });
15
18
  var validator_2 = require("./validator");
@@ -17,11 +20,20 @@ Object.defineProperty(exports, "validateResults", { enumerable: true, get: funct
17
20
  var reporter_1 = require("./reporter");
18
21
  Object.defineProperty(exports, "reportHuman", { enumerable: true, get: function () { return reporter_1.reportHuman; } });
19
22
  Object.defineProperty(exports, "reportJSON", { enumerable: true, get: function () { return reporter_1.reportJSON; } });
23
+ Object.defineProperty(exports, "reportMultiHuman", { enumerable: true, get: function () { return reporter_1.reportMultiHuman; } });
24
+ Object.defineProperty(exports, "reportMultiJSON", { enumerable: true, get: function () { return reporter_1.reportMultiJSON; } });
20
25
  var hints_1 = require("./hints");
21
26
  Object.defineProperty(exports, "getHints", { enumerable: true, get: function () { return hints_1.getHints; } });
22
27
  var presets_1 = require("./presets");
23
28
  Object.defineProperty(exports, "presets", { enumerable: true, get: function () { return presets_1.presets; } });
24
29
  Object.defineProperty(exports, "presetNames", { enumerable: true, get: function () { return presets_1.presetNames; } });
30
+ var sitemap_1 = require("./sitemap");
31
+ Object.defineProperty(exports, "fetchSitemap", { enumerable: true, get: function () { return sitemap_1.fetchSitemap; } });
32
+ var orchestrator_1 = require("./orchestrator");
33
+ Object.defineProperty(exports, "runMultiAudit", { enumerable: true, get: function () { return orchestrator_1.runMultiAudit; } });
34
+ var report_html_1 = require("./report-html");
35
+ Object.defineProperty(exports, "generateHtmlReport", { enumerable: true, get: function () { return report_html_1.generateHtmlReport; } });
36
+ Object.defineProperty(exports, "writeHtmlReport", { enumerable: true, get: function () { return report_html_1.writeHtmlReport; } });
25
37
  async function runPSGuard(url, options = {}) {
26
38
  const config = (0, config_1.loadConfig)(process.cwd(), { url, ...options });
27
39
  const lighthouseResult = await (0, runner_1.runLighthouse)(config);
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAqBA,gCAOC;AA5BD,qCAAqD;AACrD,qCAA2D;AAC3D,2CAAkE;AAGlE,mCAAqD;AAA5C,oGAAA,UAAU,OAAA;AAAE,uGAAA,aAAa,OAAA;AAClC,mCAAyC;AAAhC,uGAAA,aAAa,OAAA;AACtB,mCAAwC;AAA/B,sGAAA,YAAY,OAAA;AACrB,yCAA8C;AAArC,4GAAA,eAAe,OAAA;AACxB,uCAAqD;AAA5C,uGAAA,WAAW,OAAA;AAAE,sGAAA,UAAU,OAAA;AAChC,iCAAmC;AAA1B,iGAAA,QAAQ,OAAA;AACjB,qCAAiD;AAAxC,kGAAA,OAAO,OAAA;AAAE,sGAAA,WAAW,OAAA;AAUtB,KAAK,UAAU,UAAU,CAC9B,GAAW,EACX,UAA+C,EAAE;IAEjD,MAAM,MAAM,GAAG,IAAA,mBAAW,EAAC,OAAO,CAAC,GAAG,EAAE,EAAE,EAAE,GAAG,EAAE,GAAG,OAAO,EAAE,CAAC,CAAC;IAC/D,MAAM,gBAAgB,GAAG,MAAM,IAAA,sBAAc,EAAC,MAAM,CAAC,CAAC;IACtD,OAAO,IAAA,2BAAgB,EAAC,gBAAgB,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;AACxD,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AA2BA,gCAOC;AAlCD,qCAAqD;AACrD,qCAA2D;AAC3D,2CAAkE;AAGlE,mCAAqD;AAA5C,oGAAA,UAAU,OAAA;AAAE,uGAAA,aAAa,OAAA;AAClC,mCAAmF;AAA1E,uGAAA,aAAa,OAAA;AAAE,sGAAA,YAAY,OAAA;AAAE,wGAAA,cAAc,OAAA;AAAE,oGAAA,UAAU,OAAA;AAChE,mCAAwC;AAA/B,sGAAA,YAAY,OAAA;AACrB,yCAA8C;AAArC,4GAAA,eAAe,OAAA;AACxB,uCAAwF;AAA/E,uGAAA,WAAW,OAAA;AAAE,sGAAA,UAAU,OAAA;AAAE,4GAAA,gBAAgB,OAAA;AAAE,2GAAA,eAAe,OAAA;AACnE,iCAAmC;AAA1B,iGAAA,QAAQ,OAAA;AACjB,qCAAiD;AAAxC,kGAAA,OAAO,OAAA;AAAE,sGAAA,WAAW,OAAA;AAC7B,qCAAyC;AAAhC,uGAAA,YAAY,OAAA;AACrB,+CAA+C;AAAtC,6GAAA,aAAa,OAAA;AACtB,6CAAoE;AAA3D,iHAAA,kBAAkB,OAAA;AAAE,8GAAA,eAAe,OAAA;AAarC,KAAK,UAAU,UAAU,CAC9B,GAAW,EACX,UAA+C,EAAE;IAEjD,MAAM,MAAM,GAAG,IAAA,mBAAW,EAAC,OAAO,CAAC,GAAG,EAAE,EAAE,EAAE,GAAG,EAAE,GAAG,OAAO,EAAE,CAAC,CAAC;IAC/D,MAAM,gBAAgB,GAAG,MAAM,IAAA,sBAAc,EAAC,MAAM,CAAC,CAAC;IACtD,OAAO,IAAA,2BAAgB,EAAC,gBAAgB,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;AACxD,CAAC"}
@@ -0,0 +1,10 @@
1
+ import type { PSGuardConfig, PSGuardMultiResult } from "./types";
2
+ interface OrchestratorOptions {
3
+ urls: string[];
4
+ config: PSGuardConfig;
5
+ maxUrls?: number;
6
+ silent?: boolean;
7
+ }
8
+ export declare function runMultiAudit(options: OrchestratorOptions): Promise<PSGuardMultiResult>;
9
+ export {};
10
+ //# sourceMappingURL=orchestrator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"orchestrator.d.ts","sourceRoot":"","sources":["../src/orchestrator.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,kBAAkB,EAAiB,MAAM,SAAS,CAAC;AAOhF,UAAU,mBAAmB;IAC3B,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,MAAM,EAAE,aAAa,CAAC;IACtB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED,wBAAsB,aAAa,CAAC,OAAO,EAAE,mBAAmB,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAoE7F"}
@@ -0,0 +1,69 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.runMultiAudit = runMultiAudit;
4
+ const runner_1 = require("./runner");
5
+ const validator_1 = require("./validator");
6
+ const progress_1 = require("./utils/progress");
7
+ const DEFAULT_MAX_URLS = 50;
8
+ async function runMultiAudit(options) {
9
+ const { config, silent } = options;
10
+ const maxUrls = options.maxUrls ?? config.maxUrls ?? DEFAULT_MAX_URLS;
11
+ const urls = options.urls.slice(0, maxUrls);
12
+ if (!silent) {
13
+ (0, progress_1.printScanStart)(urls.length);
14
+ }
15
+ const chrome = await (0, runner_1.launchChrome)();
16
+ const results = [];
17
+ try {
18
+ for (let i = 0; i < urls.length; i++) {
19
+ const url = urls[i];
20
+ try {
21
+ const lighthouseResult = await (0, runner_1.runSingleAudit)(chrome, url, config);
22
+ const result = (0, validator_1.validateResults)(lighthouseResult.lhr, { ...config, url });
23
+ results.push(result);
24
+ if (!silent) {
25
+ (0, progress_1.printUrlResult)(i + 1, urls.length, result.score, url, result.passed);
26
+ }
27
+ }
28
+ catch (error) {
29
+ const message = error instanceof Error ? error.message : String(error);
30
+ results.push({
31
+ passed: false,
32
+ score: 0,
33
+ minScore: config.minScore,
34
+ metrics: [],
35
+ url,
36
+ device: config.device,
37
+ });
38
+ if (!silent) {
39
+ (0, progress_1.printUrlError)(i + 1, urls.length, url, message);
40
+ }
41
+ }
42
+ }
43
+ }
44
+ finally {
45
+ await (0, runner_1.killChrome)(chrome);
46
+ }
47
+ const passedUrls = results.filter((r) => r.passed).length;
48
+ const failedUrls = results.length - passedUrls;
49
+ const scores = results.map((r) => r.score);
50
+ const averageScore = scores.length > 0
51
+ ? Math.round(scores.reduce((a, b) => a + b, 0) / scores.length)
52
+ : 0;
53
+ const worstScore = scores.length > 0 ? Math.min(...scores) : 0;
54
+ if (!silent) {
55
+ (0, progress_1.printMultiSummary)(passedUrls, failedUrls, averageScore);
56
+ }
57
+ return {
58
+ passed: failedUrls === 0,
59
+ totalUrls: results.length,
60
+ passedUrls,
61
+ failedUrls,
62
+ averageScore,
63
+ worstScore,
64
+ results,
65
+ device: config.device,
66
+ timestamp: new Date().toISOString(),
67
+ };
68
+ }
69
+ //# sourceMappingURL=orchestrator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"orchestrator.js","sourceRoot":"","sources":["../src/orchestrator.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ import type { PSGuardResult, PSGuardMultiResult } from "./types";
2
+ export declare function generateHtmlReport(input: PSGuardResult | PSGuardMultiResult): string;
3
+ export declare function writeHtmlReport(input: PSGuardResult | PSGuardMultiResult, outputDir: string): string;
4
+ //# sourceMappingURL=report-html.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"report-html.d.ts","sourceRoot":"","sources":["../src/report-html.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAE,kBAAkB,EAAgB,MAAM,SAAS,CAAC;AA4G/E,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,aAAa,GAAG,kBAAkB,GAAG,MAAM,CA4FpF;AAED,wBAAgB,eAAe,CAC7B,KAAK,EAAE,aAAa,GAAG,kBAAkB,EACzC,SAAS,EAAE,MAAM,GAChB,MAAM,CAWR"}
@@ -0,0 +1,237 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.generateHtmlReport = generateHtmlReport;
37
+ exports.writeHtmlReport = writeHtmlReport;
38
+ const fs = __importStar(require("node:fs"));
39
+ const path = __importStar(require("node:path"));
40
+ function scoreColor(score) {
41
+ if (score >= 90)
42
+ return "#0cce6b";
43
+ if (score >= 50)
44
+ return "#ffa400";
45
+ return "#ff4e42";
46
+ }
47
+ function metricColor(metric) {
48
+ return metric.passed ? "#0cce6b" : "#ff4e42";
49
+ }
50
+ function barWidth(value, limit) {
51
+ const ratio = Math.min(value / (limit * 1.5), 1);
52
+ return Math.round(ratio * 100);
53
+ }
54
+ function escapeHtml(text) {
55
+ return text
56
+ .replace(/&/g, "&amp;")
57
+ .replace(/</g, "&lt;")
58
+ .replace(/>/g, "&gt;")
59
+ .replace(/"/g, "&quot;");
60
+ }
61
+ function renderMetricRow(metric) {
62
+ const color = metricColor(metric);
63
+ const width = barWidth(metric.value, metric.limit);
64
+ const displayValue = metric.unit
65
+ ? `${metric.value}${metric.unit}`
66
+ : String(metric.value);
67
+ return `
68
+ <tr>
69
+ <td style="padding:8px 12px;border-bottom:1px solid #e5e7eb;font-weight:500;">${escapeHtml(metric.name)}</td>
70
+ <td style="padding:8px 12px;border-bottom:1px solid #e5e7eb;">
71
+ <div style="display:flex;align-items:center;gap:8px;">
72
+ <div style="flex:1;background:#f3f4f6;border-radius:4px;height:20px;overflow:hidden;">
73
+ <div style="width:${width}%;height:100%;background:${color};border-radius:4px;transition:width 0.3s;"></div>
74
+ </div>
75
+ <span style="color:${color};font-weight:600;min-width:70px;text-align:right;">${escapeHtml(displayValue)}</span>
76
+ </div>
77
+ </td>
78
+ <td style="padding:8px 12px;border-bottom:1px solid #e5e7eb;color:#6b7280;">${metric.limit}${metric.unit}</td>
79
+ <td style="padding:8px 12px;border-bottom:1px solid #e5e7eb;text-align:center;">
80
+ <span style="color:${color};font-size:18px;">${metric.passed ? "\u2714" : "\u2716"}</span>
81
+ </td>
82
+ </tr>`;
83
+ }
84
+ function renderUrlDetail(result, index) {
85
+ const color = scoreColor(result.score);
86
+ const metricsRows = result.metrics.map(renderMetricRow).join("");
87
+ return `
88
+ <div style="margin-bottom:16px;border:1px solid #e5e7eb;border-radius:8px;overflow:hidden;">
89
+ <div onclick="this.nextElementSibling.style.display=this.nextElementSibling.style.display==='none'?'block':'none';this.querySelector('.arrow').textContent=this.nextElementSibling.style.display==='none'?'\u25B6':'\u25BC'"
90
+ style="padding:12px 16px;background:#f9fafb;cursor:pointer;display:flex;align-items:center;justify-content:space-between;user-select:none;">
91
+ <div style="display:flex;align-items:center;gap:12px;">
92
+ <span style="color:${color};font-size:18px;">${result.passed ? "\u2714" : "\u2716"}</span>
93
+ <span style="font-weight:500;">#${index + 1}</span>
94
+ <a href="${escapeHtml(result.url)}" target="_blank" rel="noopener" style="color:#2563eb;text-decoration:none;word-break:break-all;">${escapeHtml(result.url)}</a>
95
+ </div>
96
+ <div style="display:flex;align-items:center;gap:12px;">
97
+ <span style="background:${color};color:#fff;padding:2px 10px;border-radius:12px;font-weight:700;font-size:14px;">${result.score}</span>
98
+ <span class="arrow" style="color:#6b7280;">\u25B6</span>
99
+ </div>
100
+ </div>
101
+ <div style="display:none;padding:16px;">
102
+ <table style="width:100%;border-collapse:collapse;">
103
+ <thead>
104
+ <tr style="text-align:left;">
105
+ <th style="padding:8px 12px;border-bottom:2px solid #e5e7eb;color:#6b7280;font-weight:600;width:80px;">Metric</th>
106
+ <th style="padding:8px 12px;border-bottom:2px solid #e5e7eb;color:#6b7280;font-weight:600;">Value</th>
107
+ <th style="padding:8px 12px;border-bottom:2px solid #e5e7eb;color:#6b7280;font-weight:600;width:80px;">Limit</th>
108
+ <th style="padding:8px 12px;border-bottom:2px solid #e5e7eb;color:#6b7280;font-weight:600;width:60px;text-align:center;">Status</th>
109
+ </tr>
110
+ </thead>
111
+ <tbody>
112
+ ${metricsRows}
113
+ </tbody>
114
+ </table>
115
+ </div>
116
+ </div>`;
117
+ }
118
+ function renderSummaryCard(label, value, color) {
119
+ return `
120
+ <div style="flex:1;min-width:140px;background:#fff;border:1px solid #e5e7eb;border-radius:8px;padding:16px;text-align:center;">
121
+ <div style="font-size:28px;font-weight:700;color:${color};">${value}</div>
122
+ <div style="font-size:13px;color:#6b7280;margin-top:4px;">${escapeHtml(label)}</div>
123
+ </div>`;
124
+ }
125
+ function wrapSingleResult(result) {
126
+ return {
127
+ passed: result.passed,
128
+ totalUrls: 1,
129
+ passedUrls: result.passed ? 1 : 0,
130
+ failedUrls: result.passed ? 0 : 1,
131
+ averageScore: result.score,
132
+ worstScore: result.score,
133
+ results: [result],
134
+ device: result.device,
135
+ timestamp: new Date().toISOString(),
136
+ };
137
+ }
138
+ function generateHtmlReport(input) {
139
+ const multi = "totalUrls" in input ? input : wrapSingleResult(input);
140
+ const avgColor = scoreColor(multi.averageScore);
141
+ const worstColor = scoreColor(multi.worstScore);
142
+ const passedColor = multi.failedUrls === 0 ? "#0cce6b" : "#ff4e42";
143
+ const urlDetails = multi.results
144
+ .map((result, index) => renderUrlDetail(result, index))
145
+ .join("");
146
+ const urlRows = multi.results
147
+ .map((result, index) => {
148
+ const color = scoreColor(result.score);
149
+ return `
150
+ <tr>
151
+ <td style="padding:8px 12px;border-bottom:1px solid #e5e7eb;">${index + 1}</td>
152
+ <td style="padding:8px 12px;border-bottom:1px solid #e5e7eb;">
153
+ <a href="${escapeHtml(result.url)}" target="_blank" rel="noopener" style="color:#2563eb;text-decoration:none;word-break:break-all;">${escapeHtml(result.url)}</a>
154
+ </td>
155
+ <td style="padding:8px 12px;border-bottom:1px solid #e5e7eb;text-align:center;">
156
+ <span style="background:${color};color:#fff;padding:2px 10px;border-radius:12px;font-weight:700;font-size:13px;">${result.score}</span>
157
+ </td>
158
+ <td style="padding:8px 12px;border-bottom:1px solid #e5e7eb;text-align:center;">
159
+ <span style="color:${color};font-size:16px;">${result.passed ? "\u2714" : "\u2716"}</span>
160
+ </td>
161
+ </tr>`;
162
+ })
163
+ .join("");
164
+ return `<!DOCTYPE html>
165
+ <html lang="en">
166
+ <head>
167
+ <meta charset="UTF-8">
168
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
169
+ <title>ps-guard Report</title>
170
+ <style>
171
+ * { box-sizing: border-box; margin: 0; padding: 0; }
172
+ body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; background: #f3f4f6; color: #1f2937; line-height: 1.5; }
173
+ .container { max-width: 960px; margin: 0 auto; padding: 24px 16px; }
174
+ h1 { font-size: 24px; margin-bottom: 4px; }
175
+ h2 { font-size: 18px; margin: 24px 0 12px; color: #374151; }
176
+ .subtitle { color: #6b7280; font-size: 14px; margin-bottom: 20px; }
177
+ .cards { display: flex; gap: 12px; flex-wrap: wrap; margin-bottom: 24px; }
178
+ .badge { display: inline-block; padding: 2px 8px; border-radius: 4px; font-size: 12px; font-weight: 600; }
179
+ </style>
180
+ </head>
181
+ <body>
182
+ <div class="container">
183
+ <div style="display:flex;align-items:center;justify-content:space-between;flex-wrap:wrap;gap:12px;margin-bottom:8px;">
184
+ <h1>ps-guard Report</h1>
185
+ <span class="badge" style="background:${passedColor};color:#fff;font-size:14px;padding:4px 12px;">
186
+ ${multi.passed ? "PASSED" : "FAILED"}
187
+ </span>
188
+ </div>
189
+ <p class="subtitle">
190
+ ${escapeHtml(multi.device)} &middot; ${multi.totalUrls} URL${multi.totalUrls > 1 ? "s" : ""} &middot; ${escapeHtml(multi.timestamp)}
191
+ </p>
192
+
193
+ <div class="cards">
194
+ ${renderSummaryCard("Avg Score", multi.averageScore, avgColor)}
195
+ ${renderSummaryCard("Worst Score", multi.worstScore, worstColor)}
196
+ ${renderSummaryCard("Passed", `${multi.passedUrls}/${multi.totalUrls}`, passedColor)}
197
+ ${renderSummaryCard("Failed", multi.failedUrls, multi.failedUrls > 0 ? "#ff4e42" : "#0cce6b")}
198
+ </div>
199
+
200
+ <h2>URL Overview</h2>
201
+ <div style="background:#fff;border:1px solid #e5e7eb;border-radius:8px;overflow-x:auto;margin-bottom:24px;">
202
+ <table style="width:100%;border-collapse:collapse;">
203
+ <thead>
204
+ <tr style="text-align:left;">
205
+ <th style="padding:8px 12px;border-bottom:2px solid #e5e7eb;color:#6b7280;font-weight:600;width:40px;">#</th>
206
+ <th style="padding:8px 12px;border-bottom:2px solid #e5e7eb;color:#6b7280;font-weight:600;">URL</th>
207
+ <th style="padding:8px 12px;border-bottom:2px solid #e5e7eb;color:#6b7280;font-weight:600;width:80px;text-align:center;">Score</th>
208
+ <th style="padding:8px 12px;border-bottom:2px solid #e5e7eb;color:#6b7280;font-weight:600;width:60px;text-align:center;">Status</th>
209
+ </tr>
210
+ </thead>
211
+ <tbody>
212
+ ${urlRows}
213
+ </tbody>
214
+ </table>
215
+ </div>
216
+
217
+ <h2>Details</h2>
218
+ ${urlDetails}
219
+
220
+ <p style="text-align:center;color:#9ca3af;font-size:12px;margin-top:32px;">
221
+ Generated by ps-guard &middot; ${escapeHtml(new Date().toISOString())}
222
+ </p>
223
+ </div>
224
+ </body>
225
+ </html>`;
226
+ }
227
+ function writeHtmlReport(input, outputDir) {
228
+ const html = generateHtmlReport(input);
229
+ const dir = path.resolve(outputDir);
230
+ if (!fs.existsSync(dir)) {
231
+ fs.mkdirSync(dir, { recursive: true });
232
+ }
233
+ const filePath = path.join(dir, "index.html");
234
+ fs.writeFileSync(filePath, html, "utf-8");
235
+ return filePath;
236
+ }
237
+ //# sourceMappingURL=report-html.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"report-html.js","sourceRoot":"","sources":["../src/report-html.ts"],"names":[],"mappings":"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"}
@@ -1,4 +1,6 @@
1
- import type { PSGuardResult } from "./types";
1
+ import type { PSGuardResult, PSGuardMultiResult } from "./types";
2
2
  export declare function reportHuman(result: PSGuardResult): void;
3
3
  export declare function reportJSON(result: PSGuardResult): void;
4
+ export declare function reportMultiHuman(multi: PSGuardMultiResult): void;
5
+ export declare function reportMultiJSON(multi: PSGuardMultiResult): void;
4
6
  //# sourceMappingURL=reporter.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"reporter.d.ts","sourceRoot":"","sources":["../src/reporter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAU7C,wBAAgB,WAAW,CAAC,MAAM,EAAE,aAAa,GAAG,IAAI,CAsBvD;AAED,wBAAgB,UAAU,CAAC,MAAM,EAAE,aAAa,GAAG,IAAI,CAEtD"}
1
+ {"version":3,"file":"reporter.d.ts","sourceRoot":"","sources":["../src/reporter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAC;AAUjE,wBAAgB,WAAW,CAAC,MAAM,EAAE,aAAa,GAAG,IAAI,CAsBvD;AAED,wBAAgB,UAAU,CAAC,MAAM,EAAE,aAAa,GAAG,IAAI,CAEtD;AAED,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,kBAAkB,GAAG,IAAI,CAIhE;AAED,wBAAgB,eAAe,CAAC,KAAK,EAAE,kBAAkB,GAAG,IAAI,CAE/D"}
package/dist/reporter.js CHANGED
@@ -2,6 +2,8 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.reportHuman = reportHuman;
4
4
  exports.reportJSON = reportJSON;
5
+ exports.reportMultiHuman = reportMultiHuman;
6
+ exports.reportMultiJSON = reportMultiJSON;
5
7
  const hints_1 = require("./hints");
6
8
  const output_1 = require("./utils/output");
7
9
  function reportHuman(result) {
@@ -25,4 +27,12 @@ function reportHuman(result) {
25
27
  function reportJSON(result) {
26
28
  console.log(JSON.stringify(result, null, 2));
27
29
  }
30
+ function reportMultiHuman(multi) {
31
+ for (const result of multi.results) {
32
+ reportHuman(result);
33
+ }
34
+ }
35
+ function reportMultiJSON(multi) {
36
+ console.log(JSON.stringify(multi, null, 2));
37
+ }
28
38
  //# sourceMappingURL=reporter.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"reporter.js","sourceRoot":"","sources":["../src/reporter.ts"],"names":[],"mappings":";;AAUA,kCAsBC;AAED,gCAEC;AAnCD,mCAAmC;AACnC,2CAMwB;AAExB,SAAgB,WAAW,CAAC,MAAqB;IAC/C,IAAA,oBAAW,EAAC,MAAM,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC;IACvC,IAAA,sBAAa,EAAC,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC;IAC7C,OAAO,CAAC,GAAG,EAAE,CAAC;IAEd,KAAK,MAAM,MAAM,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;QACpC,IAAA,uBAAc,EAAC,MAAM,CAAC,CAAC;QAEvB,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC;YACnB,MAAM,KAAK,GAAG,IAAA,gBAAQ,EAAC,MAAM,CAAC,IAAI,CAAC,CAAC;YACpC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;gBACzB,IAAA,kBAAS,EAAC,IAAI,CAAC,CAAC;YAClB,CAAC;QACH,CAAC;IACH,CAAC;IAED,MAAM,WAAW,GACf,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,MAAM;QAC9C,CAAC,MAAM,CAAC,KAAK,GAAG,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAC3C,MAAM,UAAU,GAAG,MAAM,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC;IAE7C,IAAA,qBAAY,EAAC,MAAM,CAAC,MAAM,EAAE,WAAW,EAAE,UAAU,CAAC,CAAC;AACvD,CAAC;AAED,SAAgB,UAAU,CAAC,MAAqB;IAC9C,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;AAC/C,CAAC"}
1
+ {"version":3,"file":"reporter.js","sourceRoot":"","sources":["../src/reporter.ts"],"names":[],"mappings":";;AAUA,kCAsBC;AAED,gCAEC;AAED,4CAIC;AAED,0CAEC;AA7CD,mCAAmC;AACnC,2CAMwB;AAExB,SAAgB,WAAW,CAAC,MAAqB;IAC/C,IAAA,oBAAW,EAAC,MAAM,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC;IACvC,IAAA,sBAAa,EAAC,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC;IAC7C,OAAO,CAAC,GAAG,EAAE,CAAC;IAEd,KAAK,MAAM,MAAM,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;QACpC,IAAA,uBAAc,EAAC,MAAM,CAAC,CAAC;QAEvB,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC;YACnB,MAAM,KAAK,GAAG,IAAA,gBAAQ,EAAC,MAAM,CAAC,IAAI,CAAC,CAAC;YACpC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;gBACzB,IAAA,kBAAS,EAAC,IAAI,CAAC,CAAC;YAClB,CAAC;QACH,CAAC;IACH,CAAC;IAED,MAAM,WAAW,GACf,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,MAAM;QAC9C,CAAC,MAAM,CAAC,KAAK,GAAG,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAC3C,MAAM,UAAU,GAAG,MAAM,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC;IAE7C,IAAA,qBAAY,EAAC,MAAM,CAAC,MAAM,EAAE,WAAW,EAAE,UAAU,CAAC,CAAC;AACvD,CAAC;AAED,SAAgB,UAAU,CAAC,MAAqB;IAC9C,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;AAC/C,CAAC;AAED,SAAgB,gBAAgB,CAAC,KAAyB;IACxD,KAAK,MAAM,MAAM,IAAI,KAAK,CAAC,OAAO,EAAE,CAAC;QACnC,WAAW,CAAC,MAAM,CAAC,CAAC;IACtB,CAAC;AACH,CAAC;AAED,SAAgB,eAAe,CAAC,KAAyB;IACvD,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;AAC9C,CAAC"}
package/dist/runner.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import type { PSGuardConfig } from "./types";
2
- interface LighthouseResult {
2
+ export interface LighthouseResult {
3
3
  lhr: {
4
4
  categories: {
5
5
  performance?: {
@@ -11,6 +11,12 @@ interface LighthouseResult {
11
11
  }>;
12
12
  };
13
13
  }
14
+ export interface ChromeInstance {
15
+ port: number;
16
+ kill: () => void | Promise<void>;
17
+ }
18
+ export declare function launchChrome(): Promise<ChromeInstance>;
19
+ export declare function runSingleAudit(chrome: ChromeInstance, url: string, config: PSGuardConfig): Promise<LighthouseResult>;
20
+ export declare function killChrome(chrome: ChromeInstance): Promise<void>;
14
21
  export declare function runLighthouse(config: PSGuardConfig): Promise<LighthouseResult>;
15
- export {};
16
22
  //# sourceMappingURL=runner.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"runner.d.ts","sourceRoot":"","sources":["../src/runner.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAE7C,UAAU,gBAAgB;IACxB,GAAG,EAAE;QACH,UAAU,EAAE;YACV,WAAW,CAAC,EAAE;gBAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;aAAE,CAAC;SACxC,CAAC;QACF,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE;YAAE,YAAY,CAAC,EAAE,MAAM,CAAA;SAAE,CAAC,CAAC;KACnD,CAAC;CACH;AAED,wBAAsB,aAAa,CAAC,MAAM,EAAE,aAAa,GAAG,OAAO,CAAC,gBAAgB,CAAC,CA6CpF"}
1
+ {"version":3,"file":"runner.d.ts","sourceRoot":"","sources":["../src/runner.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAE7C,MAAM,WAAW,gBAAgB;IAC/B,GAAG,EAAE;QACH,UAAU,EAAE;YACV,WAAW,CAAC,EAAE;gBAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;aAAE,CAAC;SACxC,CAAC;QACF,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE;YAAE,YAAY,CAAC,EAAE,MAAM,CAAA;SAAE,CAAC,CAAC;KACnD,CAAC;CACH;AAED,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAClC;AAwBD,wBAAsB,YAAY,IAAI,OAAO,CAAC,cAAc,CAAC,CAM5D;AAED,wBAAsB,cAAc,CAClC,MAAM,EAAE,cAAc,EACtB,GAAG,EAAE,MAAM,EACX,MAAM,EAAE,aAAa,GACpB,OAAO,CAAC,gBAAgB,CAAC,CAmB3B;AAED,wBAAsB,UAAU,CAAC,MAAM,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CAEtE;AAED,wBAAsB,aAAa,CAAC,MAAM,EAAE,aAAa,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAQpF"}
package/dist/runner.js CHANGED
@@ -33,15 +33,13 @@ var __importStar = (this && this.__importStar) || (function () {
33
33
  };
34
34
  })();
35
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.launchChrome = launchChrome;
37
+ exports.runSingleAudit = runSingleAudit;
38
+ exports.killChrome = killChrome;
36
39
  exports.runLighthouse = runLighthouse;
37
- async function runLighthouse(config) {
38
- const chromeLauncher = await Promise.resolve().then(() => __importStar(require("chrome-launcher")));
39
- const lighthouse = await Promise.resolve().then(() => __importStar(require("lighthouse")));
40
- const chrome = await chromeLauncher.launch({
41
- chromeFlags: ["--headless", "--no-sandbox", "--disable-gpu"],
42
- });
43
- const flags = {
44
- port: chrome.port,
40
+ function buildFlags(config, port) {
41
+ return {
42
+ port,
45
43
  output: "json",
46
44
  logLevel: "error",
47
45
  formFactor: config.device === "mobile" ? "mobile" : "desktop",
@@ -52,27 +50,48 @@ async function runLighthouse(config) {
52
50
  ? undefined
53
51
  : { cpuSlowdownMultiplier: 1, downloadThroughputKbps: 0, uploadThroughputKbps: 0, rttMs: 0, requestLatencyMs: 0, throughputKbps: 0 },
54
52
  };
55
- const lighthouseConfig = {
56
- extends: "lighthouse:default",
57
- settings: {
58
- onlyCategories: ["performance"],
59
- },
60
- };
53
+ }
54
+ const LIGHTHOUSE_CONFIG = {
55
+ extends: "lighthouse:default",
56
+ settings: {
57
+ onlyCategories: ["performance"],
58
+ },
59
+ };
60
+ async function launchChrome() {
61
+ const chromeLauncher = await Promise.resolve().then(() => __importStar(require("chrome-launcher")));
62
+ const chrome = await chromeLauncher.launch({
63
+ chromeFlags: ["--headless", "--no-sandbox", "--disable-gpu"],
64
+ });
65
+ return chrome;
66
+ }
67
+ async function runSingleAudit(chrome, url, config) {
68
+ const lighthouse = await Promise.resolve().then(() => __importStar(require("lighthouse")));
69
+ const flags = buildFlags(config, chrome.port);
61
70
  let lastError;
62
71
  for (let attempt = 0; attempt < config.retries; attempt++) {
63
72
  try {
64
73
  const runFn = lighthouse.default ?? lighthouse;
65
- const result = await runFn(config.url, flags, lighthouseConfig);
66
- await chrome.kill();
74
+ const result = await runFn(url, flags, LIGHTHOUSE_CONFIG);
67
75
  return result;
68
76
  }
69
77
  catch (error) {
70
78
  lastError = error;
71
79
  }
72
80
  }
73
- await chrome.kill();
74
81
  throw lastError instanceof Error
75
82
  ? lastError
76
83
  : new Error(`Lighthouse failed after ${config.retries} attempt(s)`);
77
84
  }
85
+ async function killChrome(chrome) {
86
+ await chrome.kill();
87
+ }
88
+ async function runLighthouse(config) {
89
+ const chrome = await launchChrome();
90
+ try {
91
+ return await runSingleAudit(chrome, config.url, config);
92
+ }
93
+ finally {
94
+ await killChrome(chrome);
95
+ }
96
+ }
78
97
  //# sourceMappingURL=runner.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"runner.js","sourceRoot":"","sources":["../src/runner.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAWA,sCA6CC;AA7CM,KAAK,UAAU,aAAa,CAAC,MAAqB;IACvD,MAAM,cAAc,GAAG,wDAAa,iBAAiB,GAAC,CAAC;IACvD,MAAM,UAAU,GAAG,wDAAa,YAAY,GAAC,CAAC;IAE9C,MAAM,MAAM,GAAG,MAAM,cAAc,CAAC,MAAM,CAAC;QACzC,WAAW,EAAE,CAAC,YAAY,EAAE,cAAc,EAAE,eAAe,CAAC;KAC7D,CAAC,CAAC;IAEH,MAAM,KAAK,GAAG;QACZ,IAAI,EAAE,MAAM,CAAC,IAAI;QACjB,MAAM,EAAE,MAAe;QACvB,QAAQ,EAAE,OAAgB;QAC1B,UAAU,EAAE,MAAM,CAAC,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,QAAiB,CAAC,CAAC,CAAC,SAAkB;QAC/E,eAAe,EAAE,MAAM,CAAC,MAAM,KAAK,QAAQ;YACzC,CAAC,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,iBAAiB,EAAE,CAAC,EAAE,QAAQ,EAAE,KAAK,EAAE;YAClF,CAAC,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,iBAAiB,EAAE,CAAC,EAAE,QAAQ,EAAE,KAAK,EAAE;QACtF,UAAU,EAAE,MAAM,CAAC,MAAM,KAAK,QAAQ;YACpC,CAAC,CAAC,SAAS;YACX,CAAC,CAAC,EAAE,qBAAqB,EAAE,CAAC,EAAE,sBAAsB,EAAE,CAAC,EAAE,oBAAoB,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,gBAAgB,EAAE,CAAC,EAAE,cAAc,EAAE,CAAC,EAAE;KACvI,CAAC;IAEF,MAAM,gBAAgB,GAAG;QACvB,OAAO,EAAE,oBAAoB;QAC7B,QAAQ,EAAE;YACR,cAAc,EAAE,CAAC,aAAa,CAAC;SAChC;KACF,CAAC;IAEF,IAAI,SAAkB,CAAC;IAEvB,KAAK,IAAI,OAAO,GAAG,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC,OAAO,EAAE,OAAO,EAAE,EAAE,CAAC;QAC1D,IAAI,CAAC;YACH,MAAM,KAAK,GAAG,UAAU,CAAC,OAAO,IAAI,UAAU,CAAC;YAC/C,MAAM,MAAM,GAAG,MAAO,KAAkB,CAAC,MAAM,CAAC,GAAG,EAAE,KAAK,EAAE,gBAAgB,CAAC,CAAC;YAC9E,MAAM,MAAM,CAAC,IAAI,EAAE,CAAC;YACpB,OAAO,MAA0B,CAAC;QACpC,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,SAAS,GAAG,KAAK,CAAC;QACpB,CAAC;IACH,CAAC;IAED,MAAM,MAAM,CAAC,IAAI,EAAE,CAAC;IACpB,MAAM,SAAS,YAAY,KAAK;QAC9B,CAAC,CAAC,SAAS;QACX,CAAC,CAAC,IAAI,KAAK,CAAC,2BAA2B,MAAM,CAAC,OAAO,aAAa,CAAC,CAAC;AACxE,CAAC"}
1
+ {"version":3,"file":"runner.js","sourceRoot":"","sources":["../src/runner.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { SitemapEntry } from "./types";
2
+ export declare function fetchSitemap(url: string): Promise<SitemapEntry[]>;
3
+ //# sourceMappingURL=sitemap.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sitemap.d.ts","sourceRoot":"","sources":["../src/sitemap.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAiD5C,wBAAsB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC,CAIvE"}
@@ -0,0 +1,47 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.fetchSitemap = fetchSitemap;
4
+ const FETCH_TIMEOUT_MS = 10_000;
5
+ const MAX_DEPTH = 2;
6
+ function extractLocs(xml) {
7
+ const matches = [];
8
+ const regex = /<loc>\s*(.*?)\s*<\/loc>/gi;
9
+ let match = regex.exec(xml);
10
+ while (match !== null) {
11
+ matches.push(match[1]);
12
+ match = regex.exec(xml);
13
+ }
14
+ return matches;
15
+ }
16
+ function isSitemapIndex(xml) {
17
+ return /<sitemapindex[\s>]/i.test(xml);
18
+ }
19
+ async function fetchXml(url) {
20
+ const controller = new AbortController();
21
+ const timeout = setTimeout(() => controller.abort(), FETCH_TIMEOUT_MS);
22
+ try {
23
+ const response = await fetch(url, { signal: controller.signal });
24
+ if (!response.ok) {
25
+ throw new Error(`Failed to fetch sitemap: ${response.status} ${response.statusText}`);
26
+ }
27
+ return await response.text();
28
+ }
29
+ finally {
30
+ clearTimeout(timeout);
31
+ }
32
+ }
33
+ async function parseSitemap(url, depth) {
34
+ const xml = await fetchXml(url);
35
+ const locs = extractLocs(xml);
36
+ if (isSitemapIndex(xml) && depth < MAX_DEPTH) {
37
+ const nested = await Promise.all(locs.map((loc) => parseSitemap(loc, depth + 1)));
38
+ return nested.flat();
39
+ }
40
+ return locs;
41
+ }
42
+ async function fetchSitemap(url) {
43
+ const urls = await parseSitemap(url, 0);
44
+ const unique = [...new Set(urls)];
45
+ return unique.map((u) => ({ url: u }));
46
+ }
47
+ //# sourceMappingURL=sitemap.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sitemap.js","sourceRoot":"","sources":["../src/sitemap.ts"],"names":[],"mappings":";;AAiDA,oCAIC;AAnDD,MAAM,gBAAgB,GAAG,MAAM,CAAC;AAChC,MAAM,SAAS,GAAG,CAAC,CAAC;AAEpB,SAAS,WAAW,CAAC,GAAW;IAC9B,MAAM,OAAO,GAAa,EAAE,CAAC;IAC7B,MAAM,KAAK,GAAG,2BAA2B,CAAC;IAC1C,IAAI,KAAK,GAAG,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAC5B,OAAO,KAAK,KAAK,IAAI,EAAE,CAAC;QACtB,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;QACvB,KAAK,GAAG,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAC1B,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,SAAS,cAAc,CAAC,GAAW;IACjC,OAAO,qBAAqB,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AACzC,CAAC;AAED,KAAK,UAAU,QAAQ,CAAC,GAAW;IACjC,MAAM,UAAU,GAAG,IAAI,eAAe,EAAE,CAAC;IACzC,MAAM,OAAO,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,KAAK,EAAE,EAAE,gBAAgB,CAAC,CAAC;IAEvE,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE,EAAE,MAAM,EAAE,UAAU,CAAC,MAAM,EAAE,CAAC,CAAC;QACjE,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;YACjB,MAAM,IAAI,KAAK,CAAC,4BAA4B,QAAQ,CAAC,MAAM,IAAI,QAAQ,CAAC,UAAU,EAAE,CAAC,CAAC;QACxF,CAAC;QACD,OAAO,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;IAC/B,CAAC;YAAS,CAAC;QACT,YAAY,CAAC,OAAO,CAAC,CAAC;IACxB,CAAC;AACH,CAAC;AAED,KAAK,UAAU,YAAY,CAAC,GAAW,EAAE,KAAa;IACpD,MAAM,GAAG,GAAG,MAAM,QAAQ,CAAC,GAAG,CAAC,CAAC;IAChC,MAAM,IAAI,GAAG,WAAW,CAAC,GAAG,CAAC,CAAC;IAE9B,IAAI,cAAc,CAAC,GAAG,CAAC,IAAI,KAAK,GAAG,SAAS,EAAE,CAAC;QAC7C,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,GAAG,CAC9B,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,YAAY,CAAC,GAAG,EAAE,KAAK,GAAG,CAAC,CAAC,CAAC,CAChD,CAAC;QACF,OAAO,MAAM,CAAC,IAAI,EAAE,CAAC;IACvB,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC;AAEM,KAAK,UAAU,YAAY,CAAC,GAAW;IAC5C,MAAM,IAAI,GAAG,MAAM,YAAY,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;IACxC,MAAM,MAAM,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC;IAClC,OAAO,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;AACzC,CAAC"}
package/dist/types.d.ts CHANGED
@@ -13,6 +13,10 @@ export interface PSGuardConfig {
13
13
  failOnError: boolean;
14
14
  retries: number;
15
15
  preset?: string;
16
+ sitemap?: string;
17
+ report?: string;
18
+ html?: boolean;
19
+ maxUrls?: number;
16
20
  }
17
21
  export interface MetricResult {
18
22
  name: string;
@@ -42,5 +46,23 @@ export interface CLIArgs {
42
46
  ci: boolean;
43
47
  help: boolean;
44
48
  retries?: number;
49
+ sitemap?: string;
50
+ report?: string;
51
+ html: boolean;
52
+ maxUrls?: number;
53
+ }
54
+ export interface SitemapEntry {
55
+ url: string;
56
+ }
57
+ export interface PSGuardMultiResult {
58
+ passed: boolean;
59
+ totalUrls: number;
60
+ passedUrls: number;
61
+ failedUrls: number;
62
+ averageScore: number;
63
+ worstScore: number;
64
+ results: PSGuardResult[];
65
+ device: "mobile" | "desktop";
66
+ timestamp: string;
45
67
  }
46
68
  //# sourceMappingURL=types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,iBAAiB;IAChC,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,aAAa;IAC5B,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,QAAQ,GAAG,SAAS,CAAC;IAC7B,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,iBAAiB,CAAC;IAC9B,WAAW,EAAE,OAAO,CAAC;IACrB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,OAAO,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,OAAO,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,YAAY,EAAE,CAAC;IACxB,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,QAAQ,GAAG,SAAS,CAAC;CAC9B;AAED,MAAM,WAAW,MAAM;IACrB,MAAM,EAAE,QAAQ,GAAG,SAAS,CAAC;IAC7B,UAAU,EAAE,iBAAiB,CAAC;IAC9B,eAAe,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAC3C;AAED,MAAM,WAAW,OAAO;IACtB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,QAAQ,GAAG,SAAS,CAAC;IAC9B,IAAI,EAAE,OAAO,CAAC;IACd,EAAE,EAAE,OAAO,CAAC;IACZ,IAAI,EAAE,OAAO,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,iBAAiB;IAChC,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,aAAa;IAC5B,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,QAAQ,GAAG,SAAS,CAAC;IAC7B,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,iBAAiB,CAAC;IAC9B,WAAW,EAAE,OAAO,CAAC;IACrB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,OAAO,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,OAAO,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,YAAY,EAAE,CAAC;IACxB,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,QAAQ,GAAG,SAAS,CAAC;CAC9B;AAED,MAAM,WAAW,MAAM;IACrB,MAAM,EAAE,QAAQ,GAAG,SAAS,CAAC;IAC7B,UAAU,EAAE,iBAAiB,CAAC;IAC9B,eAAe,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAC3C;AAED,MAAM,WAAW,OAAO;IACtB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,QAAQ,GAAG,SAAS,CAAC;IAC9B,IAAI,EAAE,OAAO,CAAC;IACd,EAAE,EAAE,OAAO,CAAC;IACZ,IAAI,EAAE,OAAO,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,OAAO,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,YAAY;IAC3B,GAAG,EAAE,MAAM,CAAC;CACb;AAED,MAAM,WAAW,kBAAkB;IACjC,MAAM,EAAE,OAAO,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,aAAa,EAAE,CAAC;IACzB,MAAM,EAAE,QAAQ,GAAG,SAAS,CAAC;IAC7B,SAAS,EAAE,MAAM,CAAC;CACnB"}
@@ -0,0 +1,6 @@
1
+ export declare function setProgressCIMode(enabled: boolean): void;
2
+ export declare function printScanStart(totalUrls: number): void;
3
+ export declare function printUrlResult(index: number, total: number, score: number, url: string, passed: boolean): void;
4
+ export declare function printUrlError(index: number, total: number, url: string, errorMessage: string): void;
5
+ export declare function printMultiSummary(passedUrls: number, failedUrls: number, averageScore: number): void;
6
+ //# sourceMappingURL=progress.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"progress.d.ts","sourceRoot":"","sources":["../../src/utils/progress.ts"],"names":[],"mappings":"AAIA,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAGxD;AAOD,wBAAgB,cAAc,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAItD;AAED,wBAAgB,cAAc,CAC5B,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,MAAM,EACb,GAAG,EAAE,MAAM,EACX,MAAM,EAAE,OAAO,GACd,IAAI,CAKN;AAED,wBAAgB,aAAa,CAC3B,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,MAAM,EACb,GAAG,EAAE,MAAM,EACX,YAAY,EAAE,MAAM,GACnB,IAAI,CAKN;AAED,wBAAgB,iBAAiB,CAC/B,UAAU,EAAE,MAAM,EAClB,UAAU,EAAE,MAAM,EAClB,YAAY,EAAE,MAAM,GACnB,IAAI,CASN"}
@@ -0,0 +1,47 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.setProgressCIMode = setProgressCIMode;
4
+ exports.printScanStart = printScanStart;
5
+ exports.printUrlResult = printUrlResult;
6
+ exports.printUrlError = printUrlError;
7
+ exports.printMultiSummary = printMultiSummary;
8
+ const output_1 = require("./output");
9
+ let ciMode = false;
10
+ function setProgressCIMode(enabled) {
11
+ ciMode = enabled;
12
+ (0, output_1.setCIMode)(enabled);
13
+ }
14
+ function color(code, text) {
15
+ if (ciMode)
16
+ return text;
17
+ return `\x1b[${code}m${text}\x1b[0m`;
18
+ }
19
+ function printScanStart(totalUrls) {
20
+ console.log();
21
+ console.log(color("1;36", `Scanning ${totalUrls} URLs from sitemap...`));
22
+ console.log();
23
+ }
24
+ function printUrlResult(index, total, score, url, passed) {
25
+ const counter = `[${index}/${total}]`;
26
+ const icon = passed ? color("32", "\u2714") : color("31", "\u2716");
27
+ const scoreStr = passed ? color("32", String(score)) : color("31", String(score));
28
+ console.log(`${counter} ${icon} ${scoreStr} ${url}`);
29
+ }
30
+ function printUrlError(index, total, url, errorMessage) {
31
+ const counter = `[${index}/${total}]`;
32
+ const icon = color("31", "\u2716");
33
+ console.log(`${counter} ${icon} ${color("31", "ERR")} ${url}`);
34
+ console.log(` ${color("2", errorMessage)}`);
35
+ }
36
+ function printMultiSummary(passedUrls, failedUrls, averageScore) {
37
+ console.log();
38
+ const total = passedUrls + failedUrls;
39
+ if (failedUrls === 0) {
40
+ console.log(color("1;32", `\u2714 All ${total} URLs passed (avg score: ${averageScore})`));
41
+ }
42
+ else {
43
+ console.log(color("1;31", `\u2716 ${failedUrls} of ${total} URLs failed (avg score: ${averageScore})`));
44
+ }
45
+ console.log();
46
+ }
47
+ //# sourceMappingURL=progress.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"progress.js","sourceRoot":"","sources":["../../src/utils/progress.ts"],"names":[],"mappings":";;AAIA,8CAGC;AAOD,wCAIC;AAED,wCAWC;AAED,sCAUC;AAED,8CAaC;AA1DD,qCAAqC;AAErC,IAAI,MAAM,GAAG,KAAK,CAAC;AAEnB,SAAgB,iBAAiB,CAAC,OAAgB;IAChD,MAAM,GAAG,OAAO,CAAC;IACjB,IAAA,kBAAS,EAAC,OAAO,CAAC,CAAC;AACrB,CAAC;AAED,SAAS,KAAK,CAAC,IAAY,EAAE,IAAY;IACvC,IAAI,MAAM;QAAE,OAAO,IAAI,CAAC;IACxB,OAAO,QAAQ,IAAI,IAAI,IAAI,SAAS,CAAC;AACvC,CAAC;AAED,SAAgB,cAAc,CAAC,SAAiB;IAC9C,OAAO,CAAC,GAAG,EAAE,CAAC;IACd,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,EAAE,YAAY,SAAS,uBAAuB,CAAC,CAAC,CAAC;IACzE,OAAO,CAAC,GAAG,EAAE,CAAC;AAChB,CAAC;AAED,SAAgB,cAAc,CAC5B,KAAa,EACb,KAAa,EACb,KAAa,EACb,GAAW,EACX,MAAe;IAEf,MAAM,OAAO,GAAG,IAAI,KAAK,IAAI,KAAK,GAAG,CAAC;IACtC,MAAM,IAAI,GAAG,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;IACpE,MAAM,QAAQ,GAAG,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;IAClF,OAAO,CAAC,GAAG,CAAC,GAAG,OAAO,IAAI,IAAI,IAAI,QAAQ,KAAK,GAAG,EAAE,CAAC,CAAC;AACxD,CAAC;AAED,SAAgB,aAAa,CAC3B,KAAa,EACb,KAAa,EACb,GAAW,EACX,YAAoB;IAEpB,MAAM,OAAO,GAAG,IAAI,KAAK,IAAI,KAAK,GAAG,CAAC;IACtC,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;IACnC,OAAO,CAAC,GAAG,CAAC,GAAG,OAAO,IAAI,IAAI,IAAI,KAAK,CAAC,IAAI,EAAE,KAAK,CAAC,KAAK,GAAG,EAAE,CAAC,CAAC;IAChE,OAAO,CAAC,GAAG,CAAC,UAAU,KAAK,CAAC,GAAG,EAAE,YAAY,CAAC,EAAE,CAAC,CAAC;AACpD,CAAC;AAED,SAAgB,iBAAiB,CAC/B,UAAkB,EAClB,UAAkB,EAClB,YAAoB;IAEpB,OAAO,CAAC,GAAG,EAAE,CAAC;IACd,MAAM,KAAK,GAAG,UAAU,GAAG,UAAU,CAAC;IACtC,IAAI,UAAU,KAAK,CAAC,EAAE,CAAC;QACrB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,EAAE,cAAc,KAAK,4BAA4B,YAAY,GAAG,CAAC,CAAC,CAAC;IAC7F,CAAC;SAAM,CAAC;QACN,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,EAAE,UAAU,UAAU,OAAO,KAAK,4BAA4B,YAAY,GAAG,CAAC,CAAC,CAAC;IAC1G,CAAC;IACD,OAAO,CAAC,GAAG,EAAE,CAAC;AAChB,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@promise-inc/ps-guard",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
4
  "description": "Lighthouse-based performance guard. Enforce Web Vitals thresholds in CI and locally.",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",