meodp 0.0.9 → 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.
Files changed (61) hide show
  1. package/README.md +230 -21
  2. package/bin/index.mjs +10 -2
  3. package/dist/check/cli.cjs +257 -0
  4. package/dist/check/cli.d.cts +5 -0
  5. package/dist/check/cli.d.mts +5 -0
  6. package/dist/check/cli.d.ts +5 -0
  7. package/dist/check/cli.mjs +249 -0
  8. package/dist/check/index.cjs +29 -0
  9. package/dist/check/index.d.cts +44 -0
  10. package/dist/check/index.d.mts +44 -0
  11. package/dist/check/index.d.ts +44 -0
  12. package/dist/check/index.mjs +13 -0
  13. package/dist/cli/index.cjs +2 -2
  14. package/dist/cli/index.d.cts +1 -1
  15. package/dist/cli/index.d.mts +1 -1
  16. package/dist/cli/index.d.ts +1 -1
  17. package/dist/cli/index.mjs +2 -2
  18. package/dist/cli/main.cjs +272 -0
  19. package/dist/cli/main.d.cts +4 -0
  20. package/dist/cli/main.d.mts +4 -0
  21. package/dist/cli/main.d.ts +4 -0
  22. package/dist/cli/main.mjs +266 -0
  23. package/dist/config/index.cjs +7 -0
  24. package/dist/config/index.d.cts +47 -0
  25. package/dist/config/index.d.mts +47 -0
  26. package/dist/config/index.d.ts +47 -0
  27. package/dist/config/index.mjs +5 -0
  28. package/dist/notify/cli.cjs +107 -0
  29. package/dist/notify/cli.d.cts +3 -0
  30. package/dist/notify/cli.d.mts +3 -0
  31. package/dist/notify/cli.d.ts +3 -0
  32. package/dist/notify/cli.mjs +101 -0
  33. package/dist/notify/email.cjs +38 -0
  34. package/dist/notify/email.d.cts +29 -0
  35. package/dist/notify/email.d.mts +29 -0
  36. package/dist/notify/email.d.ts +29 -0
  37. package/dist/notify/email.mjs +35 -0
  38. package/dist/notify/feishu.cjs +162 -0
  39. package/dist/notify/feishu.d.cts +74 -0
  40. package/dist/notify/feishu.d.mts +74 -0
  41. package/dist/notify/feishu.d.ts +74 -0
  42. package/dist/notify/feishu.mjs +157 -0
  43. package/dist/notify/index.cjs +64 -0
  44. package/dist/notify/index.d.cts +27 -0
  45. package/dist/notify/index.d.mts +27 -0
  46. package/dist/notify/index.d.ts +27 -0
  47. package/dist/notify/index.mjs +62 -0
  48. package/dist/shared/meodp.2b00b0ae.cjs +228 -0
  49. package/dist/shared/meodp.4f1da070.d.cts +41 -0
  50. package/dist/shared/meodp.63483e20.cjs +30 -0
  51. package/dist/shared/meodp.80ff918d.mjs +465 -0
  52. package/dist/shared/meodp.8369c4c1.d.ts +41 -0
  53. package/dist/shared/meodp.93e06e00.d.cts +64 -0
  54. package/dist/shared/meodp.93e06e00.d.mts +64 -0
  55. package/dist/shared/meodp.93e06e00.d.ts +64 -0
  56. package/dist/shared/meodp.9c706389.mjs +220 -0
  57. package/dist/shared/meodp.a704f8db.d.mts +41 -0
  58. package/dist/shared/meodp.c4c70565.cjs +477 -0
  59. package/dist/shared/meodp.f96d0510.mjs +24 -0
  60. package/package.json +104 -31
  61. package/bin/index.ts +0 -6
@@ -0,0 +1,249 @@
1
+ import { readFile, realpath } from 'node:fs/promises';
2
+ import { hostname } from 'node:os';
3
+ import { resolve, join, extname } from 'node:path';
4
+ import process from 'node:process';
5
+ import { parseArgs } from 'node:util';
6
+ import { load } from 'js-yaml';
7
+ import { l as loadProjectConfig } from '../shared/meodp.f96d0510.mjs';
8
+ import { p as planReporters, c as checkSitemap, a as checkLinks, w as writeReporters, n as normalizeTargets, b as waitForReport } from '../shared/meodp.80ff918d.mjs';
9
+ import { r as readReport, s as saveReport } from '../shared/meodp.9c706389.mjs';
10
+ import 'c12';
11
+ import 'node:timers/promises';
12
+ import 'linkinator';
13
+ import 'node:buffer';
14
+ import 'node:zlib';
15
+ import 'fast-xml-parser';
16
+ import 'node:crypto';
17
+
18
+ const help = `Usage: meodp check <links.json|links.yml> [options]
19
+
20
+ Check only the listed HTTP(S) URLs, with no browser or recursive resource scan.
21
+ Input: an array of URL strings or objects with url and optional name.
22
+ This makes network requests. To render saved data instead, use meodp report.
23
+
24
+ --config <file> Load a project config (default: meodp.config.ts)
25
+ --output <directory> Default report directory (default: reports/meodp)
26
+ --reporter <names> json, markdown, html; comma-separated or repeated
27
+ Without a selection, write report.json, report.md, report.html
28
+ --history <file> Read previous observations and save the completed report
29
+ --observer <name> Identify this network/environment (default: hostname)
30
+ --concurrency <n> Concurrent sites (default: 5)
31
+ --timeout <ms> Timeout per HTTP request (default: 10000)
32
+ --retries <n> Retries for transport/5xx failures (default: 1)
33
+ --max-redirects <n> Follow at most n redirects (default: 5)
34
+ --fail-on <policy> unavailable (default), review, or none
35
+ -h, --help Show this help
36
+
37
+ Exit codes: 0 = policy passed; 1 = findings match --fail-on; 2 = input/execution error.
38
+ Restricted results and redirects require review; they do not prove a dead site.
39
+ `;
40
+ async function runCheckCli(args = process.argv.slice(3)) {
41
+ return runScanCli("links", args);
42
+ }
43
+ async function runSitemapCli(args = process.argv.slice(3)) {
44
+ return runScanCli("sitemap", args);
45
+ }
46
+ async function runScanCli(mode, args) {
47
+ try {
48
+ const { values, positionals } = parseArgs({
49
+ args,
50
+ allowPositionals: true,
51
+ options: {
52
+ "config": { type: "string" },
53
+ "reporter": { type: "string", multiple: true },
54
+ "output": { type: "string" },
55
+ "history": { type: "string" },
56
+ "observer": { type: "string" },
57
+ "concurrency": { type: "string" },
58
+ "timeout": { type: "string" },
59
+ "retries": { type: "string" },
60
+ "max-redirects": { type: "string" },
61
+ "fail-on": { type: "string" },
62
+ "help": { type: "boolean", short: "h" },
63
+ ...mode === "sitemap" ? {
64
+ "discover": { type: "boolean" },
65
+ "max-urls": { type: "string" },
66
+ "max-sitemaps": { type: "string" },
67
+ "max-sitemap-bytes": { type: "string" }
68
+ } : {}
69
+ }
70
+ });
71
+ if (values.help) {
72
+ console.log(mode === "links" ? help : `Usage: meodp sitemap <sitemap-url> [options]
73
+
74
+ Read an XML sitemap or nested index, then check each listed page via HTTP.
75
+ --discover Treat the URL as a site: read robots.txt or /sitemap.xml
76
+ --max-urls <n> Reject discovery above n unique pages (default: 10000)
77
+ --max-sitemaps <n> Limit sitemap documents (default: 100)
78
+ --max-sitemap-bytes <n> Limit each downloaded/decompressed document (default: 10485760)
79
+
80
+ ${help.slice(help.indexOf(" --config"))}`);
81
+ return 0;
82
+ }
83
+ const project = await loadProjectConfig(values.config);
84
+ const configured = (mode === "links" ? project.config.check : project.config.sitemap) ?? {};
85
+ const input = positionals[0] ?? (configured.input ? mode === "links" ? project.path(configured.input) : configured.input : void 0);
86
+ if (!input || positionals.length > 1)
87
+ throw new Error(`Provide exactly one ${mode === "links" ? "JSON or YAML input file" : "HTTP(S) URL"}. Use --help for examples.`);
88
+ const selection = selectReporters(values.reporter, configured.reporter ?? project.config.reporter);
89
+ const outputDir = resolve(values.output ?? (configured.output ? project.path(configured.output) : "reports/meodp"));
90
+ const reporterOptions = { outputDir, cwd: project.path(".") };
91
+ const reporter = typeof selection === "string" ? [selection] : [...selection ?? ["json", "markdown", ["html", { outputFile: join(outputDir, "report.html") }]]];
92
+ if (configured.site)
93
+ reporter.push(["html", { outputFolder: project.path(configured.site) }]);
94
+ const plan = planReporters(reporter, reporterOptions);
95
+ const failOn = values["fail-on"] ?? configured.failOn ?? "unavailable";
96
+ if (!["none", "unavailable", "review"].includes(failOn))
97
+ throw new Error("--fail-on must be none, unavailable, or review");
98
+ const numeric = (value) => typeof value === "string" ? Number(value) : void 0;
99
+ const history = values.history ?? (configured.history ? project.path(configured.history) : void 0);
100
+ const seed = configured.historySeed ? project.path(configured.historySeed) : void 0;
101
+ await protectInputs(plan, [
102
+ ...mode === "links" ? [{ file: input, jsonOnly: false }] : [],
103
+ ...[history, seed].filter((file) => !!file).map((file) => ({ file, jsonOnly: true }))
104
+ ], history);
105
+ let previousReport = history ? await readReport(history) : void 0;
106
+ if (!previousReport && seed)
107
+ previousReport = await readReport(seed);
108
+ const observer = values.observer ?? configured.observer;
109
+ if (previousReport && configured.observerMismatch === "reset" && previousReport.observer !== (observer ?? hostname()))
110
+ previousReport = void 0;
111
+ const options = {
112
+ observer,
113
+ previousReport,
114
+ concurrency: numeric(values.concurrency) ?? configured.concurrency,
115
+ timeoutMs: numeric(values.timeout) ?? configured.timeoutMs,
116
+ retries: numeric(values.retries) ?? configured.retries,
117
+ maxRedirects: numeric(values["max-redirects"]) ?? configured.maxRedirects,
118
+ onResult(result) {
119
+ console.log(`[${result.status}] ${result.httpStatus ?? result.reason} ${result.url}`);
120
+ }
121
+ };
122
+ const report = mode === "sitemap" ? await checkSitemap(input, {
123
+ ...options,
124
+ discover: values.discover === void 0 ? configured.discover : values.discover === true,
125
+ maxUrls: numeric(values["max-urls"]) ?? configured.maxUrls,
126
+ maxSitemaps: numeric(values["max-sitemaps"]) ?? configured.maxSitemaps,
127
+ maxSitemapBytes: numeric(values["max-sitemap-bytes"]) ?? configured.maxSitemapBytes
128
+ }) : await checkLinks(await readTargets(input), options);
129
+ const outputs = await writeReporters(report, reporter, reporterOptions);
130
+ for (const output of outputs)
131
+ console.log(`${output.reporter}: ${output.files.join(", ")}`);
132
+ if (history)
133
+ await saveReport(report, history);
134
+ console.log(`${report.summary.total} URLs: ${report.summary.reachable} reachable, ${report.summary.restricted} restricted, ${report.summary.unavailable} unavailable`);
135
+ if (failOn === "none")
136
+ return 0;
137
+ const findings = report.summary.unavailable > 0 || failOn === "review" && (report.summary.restricted > 0 || report.summary.redirected > 0);
138
+ return findings ? 1 : 0;
139
+ } catch (error) {
140
+ console.error(`meodp ${mode === "links" ? "check" : "sitemap"}: ${error instanceof Error ? error.message : String(error)}`);
141
+ return 2;
142
+ }
143
+ }
144
+ async function readTargets(input) {
145
+ const extension = extname(input).toLowerCase();
146
+ if (![".json", ".yml", ".yaml"].includes(extension))
147
+ throw new Error("Input file must use .json, .yml, or .yaml");
148
+ const source = await readFile(input, "utf8");
149
+ return normalizeTargets(extension === ".json" ? JSON.parse(source) : load(source));
150
+ }
151
+ async function runReportCli(args = process.argv.slice(3)) {
152
+ try {
153
+ const { values, positionals } = parseArgs({
154
+ args,
155
+ allowPositionals: true,
156
+ options: {
157
+ "config": { type: "string" },
158
+ "reporter": { type: "string", multiple: true },
159
+ "verify": { type: "boolean" },
160
+ "output": { type: "string" },
161
+ "data-url": { type: "string" },
162
+ "help": { type: "boolean", short: "h" }
163
+ }
164
+ });
165
+ if (values.help) {
166
+ console.log(`Usage: meodp report [report.json] [--reporter json,markdown,html] [--output reports/site]
167
+
168
+ Render saved data through selected reporters without making any site-check requests.
169
+ --reporter accepts json, markdown, html; repeat it or separate names with commas.
170
+ With no configured selection, export the HTML static viewer.
171
+ HTML folders with input write index.html and report.json. The hosted viewer loads
172
+ report.json on each visit; opening index.html as a local file uses its embedded snapshot.
173
+ Without input, only HTML is available: an empty viewer with file upload and URL loading.
174
+ --config loads a project config; CLI arguments override config values.
175
+ --verify waits for report.verify.url to serve this report and the matching viewer.
176
+ --data-url overrides the data source loaded by the hosted viewer (cross-origin needs CORS).
177
+ -h, --help shows this help. To collect fresh observations, use meodp check.
178
+ Exit codes: 0 = exported; 2 = invalid input or execution error.`);
179
+ return 0;
180
+ }
181
+ if (positionals.length > 1)
182
+ throw new Error("Provide at most one report.json file. Use --help for examples.");
183
+ const project = await loadProjectConfig(values.config);
184
+ const configured = project.config.report ?? {};
185
+ const input = positionals[0] ?? (configured.input ? project.path(configured.input) : void 0);
186
+ const report = input ? await readReport(input) : void 0;
187
+ if (input && !report)
188
+ throw new Error(`Report not found: ${input}`);
189
+ const reporter = selectReporters(values.reporter, configured.reporter ?? project.config.reporter) ?? "html";
190
+ if (values.verify) {
191
+ if (!report || !configured.verify)
192
+ throw new Error("Verification requires a saved report and report.verify.url in the config.");
193
+ await waitForReport(report, configured.verify);
194
+ console.log("The public status page is serving the expected report.");
195
+ return 0;
196
+ }
197
+ const selected = values["data-url"] === void 0 ? reporter : (typeof reporter === "string" ? [reporter] : reporter).map((entry) => {
198
+ const [name, options] = typeof entry === "string" ? [entry] : entry;
199
+ return name === "html" ? ["html", { ...options, dataUrl: values["data-url"] }] : entry;
200
+ });
201
+ const reporterOptions = {
202
+ cwd: project.path("."),
203
+ outputDir: resolve(values.output ?? (configured.output ? project.path(configured.output) : "reports/site")),
204
+ dataUrl: values["data-url"] ?? configured.dataUrl
205
+ };
206
+ await protectInputs(planReporters(selected, reporterOptions), input ? [{ file: input, jsonOnly: true }] : []);
207
+ const outputs = await writeReporters(report, selected, reporterOptions);
208
+ for (const output of outputs)
209
+ console.log(`${output.reporter}: ${output.files.join(", ")}`);
210
+ return 0;
211
+ } catch (error) {
212
+ console.error(`meodp report: ${error instanceof Error ? error.message : String(error)}`);
213
+ return 2;
214
+ }
215
+ }
216
+ function selectReporters(cli, configured) {
217
+ if (cli === void 0)
218
+ return configured;
219
+ const names = [...new Set(cli.flatMap((value) => value.split(",").map((name) => name.trim())))];
220
+ if (names.some((name) => !["json", "markdown", "html"].includes(name)))
221
+ throw new TypeError("--reporter must select json, markdown, or html.");
222
+ return names;
223
+ }
224
+ async function protectInputs(plan, inputs, history) {
225
+ const identity = async (file) => {
226
+ try {
227
+ return await realpath(file);
228
+ } catch (error) {
229
+ if (error && typeof error === "object" && "code" in error && error.code === "ENOENT")
230
+ return resolve(file);
231
+ throw error;
232
+ }
233
+ };
234
+ const writes = plan.flatMap((item) => [
235
+ { file: item.file, reporter: item.reporter },
236
+ ...item.json ? [{ file: item.json, reporter: "json" }] : []
237
+ ]);
238
+ if (history)
239
+ writes.push({ file: history, reporter: "json" });
240
+ for (const input of inputs) {
241
+ const source = await identity(input.file);
242
+ for (const output of writes) {
243
+ if (await identity(output.file) === source && (!input.jsonOnly || output.reporter !== "json"))
244
+ throw new Error(`Reporter/history output would overwrite input ${input.file}; choose another output path.`);
245
+ }
246
+ }
247
+ }
248
+
249
+ export { runCheckCli, runReportCli, runSitemapCli };
@@ -0,0 +1,29 @@
1
+ 'use strict';
2
+
3
+ const check_index = require('../shared/meodp.c4c70565.cjs');
4
+ const report = require('../shared/meodp.2b00b0ae.cjs');
5
+ require('node:timers/promises');
6
+ require('linkinator');
7
+ require('node:os');
8
+ require('node:fs/promises');
9
+ require('node:path');
10
+ require('node:process');
11
+ require('node:buffer');
12
+ require('node:util');
13
+ require('node:zlib');
14
+ require('fast-xml-parser');
15
+ require('node:crypto');
16
+
17
+
18
+
19
+ exports.checkLinks = check_index.checkLinks;
20
+ exports.checkSitemap = check_index.checkSitemap;
21
+ exports.readSitemapUrls = check_index.readSitemapUrls;
22
+ exports.waitForReport = check_index.waitForReport;
23
+ exports.writeReporters = check_index.writeReporters;
24
+ exports.formatReport = report.formatReport;
25
+ exports.parseReport = report.parseReport;
26
+ exports.readReport = report.readReport;
27
+ exports.saveReport = report.saveReport;
28
+ exports.writeReportSite = report.writeReportSite;
29
+ exports.writeReports = report.writeReports;
@@ -0,0 +1,44 @@
1
+ import { L as LinkTarget, a as CheckOptions, C as CheckReport, S as SitemapOptions, A as Availability, b as LinkObservation } from '../shared/meodp.93e06e00.cjs';
2
+ export { F as FailureReason } from '../shared/meodp.93e06e00.cjs';
3
+ import { b as ReportSiteOptions } from '../shared/meodp.4f1da070.cjs';
4
+ export { H as HtmlReporterOptions, a as ReportVerificationOptions, R as ReporterConfig, c as ReporterDescription, d as ReporterName, e as ReporterOptions, f as ReporterOutput, g as waitForReport, w as writeReporters } from '../shared/meodp.4f1da070.cjs';
5
+
6
+ /** Check only the supplied URLs. HTTP failures become observations; invalid input rejects. */
7
+ declare function checkLinks(input: readonly (string | LinkTarget)[], options?: CheckOptions): Promise<CheckReport>;
8
+
9
+ declare function formatReport(report: CheckReport, format?: 'json' | 'markdown' | 'html'): string;
10
+ declare function writeReports(report: CheckReport, directory: string): Promise<{
11
+ json: string;
12
+ markdown: string;
13
+ html: string;
14
+ }>;
15
+ /** Export a portable static site. Hosting refreshes the sidecar; file:// uses the embedded snapshot. */
16
+ declare function writeReportSite(report: CheckReport | undefined, directory: string, options?: ReportSiteOptions): Promise<{
17
+ index: string;
18
+ json?: string;
19
+ }>;
20
+ /** A missing file starts history; malformed or incompatible history is an error. */
21
+ declare function readReport(path: string): Promise<CheckReport | undefined>;
22
+ /** Write history only after a completed run; replace it atomically. */
23
+ declare function saveReport(report: CheckReport, path: string): Promise<void>;
24
+
25
+ /** Shared by the Node reader and the static viewer; report files are untrusted input. */
26
+ declare function parseReport(data: unknown): CheckReport;
27
+
28
+ /** Read and validate a complete, deduplicated page list without requesting the pages. */
29
+ declare function readSitemapUrls(source: string, options?: SitemapOptions): Promise<string[]>;
30
+ /** Check sitemap-listed pages using the same linkinator adapter, history, and report schema as checkLinks. */
31
+ declare function checkSitemap(source: string, options?: SitemapOptions): Promise<{
32
+ startedAt: string;
33
+ schemaVersion: 1;
34
+ observer: string;
35
+ completedAt: string;
36
+ summary: Record<Availability, number> & {
37
+ total: number;
38
+ redirected: number;
39
+ recovered: number;
40
+ };
41
+ results: LinkObservation[];
42
+ }>;
43
+
44
+ export { Availability, CheckOptions, CheckReport, LinkObservation, LinkTarget, ReportSiteOptions, SitemapOptions, checkLinks, checkSitemap, formatReport, parseReport, readReport, readSitemapUrls, saveReport, writeReportSite, writeReports };
@@ -0,0 +1,44 @@
1
+ import { L as LinkTarget, a as CheckOptions, C as CheckReport, S as SitemapOptions, A as Availability, b as LinkObservation } from '../shared/meodp.93e06e00.mjs';
2
+ export { F as FailureReason } from '../shared/meodp.93e06e00.mjs';
3
+ import { b as ReportSiteOptions } from '../shared/meodp.a704f8db.mjs';
4
+ export { H as HtmlReporterOptions, a as ReportVerificationOptions, R as ReporterConfig, c as ReporterDescription, d as ReporterName, e as ReporterOptions, f as ReporterOutput, g as waitForReport, w as writeReporters } from '../shared/meodp.a704f8db.mjs';
5
+
6
+ /** Check only the supplied URLs. HTTP failures become observations; invalid input rejects. */
7
+ declare function checkLinks(input: readonly (string | LinkTarget)[], options?: CheckOptions): Promise<CheckReport>;
8
+
9
+ declare function formatReport(report: CheckReport, format?: 'json' | 'markdown' | 'html'): string;
10
+ declare function writeReports(report: CheckReport, directory: string): Promise<{
11
+ json: string;
12
+ markdown: string;
13
+ html: string;
14
+ }>;
15
+ /** Export a portable static site. Hosting refreshes the sidecar; file:// uses the embedded snapshot. */
16
+ declare function writeReportSite(report: CheckReport | undefined, directory: string, options?: ReportSiteOptions): Promise<{
17
+ index: string;
18
+ json?: string;
19
+ }>;
20
+ /** A missing file starts history; malformed or incompatible history is an error. */
21
+ declare function readReport(path: string): Promise<CheckReport | undefined>;
22
+ /** Write history only after a completed run; replace it atomically. */
23
+ declare function saveReport(report: CheckReport, path: string): Promise<void>;
24
+
25
+ /** Shared by the Node reader and the static viewer; report files are untrusted input. */
26
+ declare function parseReport(data: unknown): CheckReport;
27
+
28
+ /** Read and validate a complete, deduplicated page list without requesting the pages. */
29
+ declare function readSitemapUrls(source: string, options?: SitemapOptions): Promise<string[]>;
30
+ /** Check sitemap-listed pages using the same linkinator adapter, history, and report schema as checkLinks. */
31
+ declare function checkSitemap(source: string, options?: SitemapOptions): Promise<{
32
+ startedAt: string;
33
+ schemaVersion: 1;
34
+ observer: string;
35
+ completedAt: string;
36
+ summary: Record<Availability, number> & {
37
+ total: number;
38
+ redirected: number;
39
+ recovered: number;
40
+ };
41
+ results: LinkObservation[];
42
+ }>;
43
+
44
+ export { Availability, CheckOptions, CheckReport, LinkObservation, LinkTarget, ReportSiteOptions, SitemapOptions, checkLinks, checkSitemap, formatReport, parseReport, readReport, readSitemapUrls, saveReport, writeReportSite, writeReports };
@@ -0,0 +1,44 @@
1
+ import { L as LinkTarget, a as CheckOptions, C as CheckReport, S as SitemapOptions, A as Availability, b as LinkObservation } from '../shared/meodp.93e06e00.js';
2
+ export { F as FailureReason } from '../shared/meodp.93e06e00.js';
3
+ import { b as ReportSiteOptions } from '../shared/meodp.8369c4c1.js';
4
+ export { H as HtmlReporterOptions, a as ReportVerificationOptions, R as ReporterConfig, c as ReporterDescription, d as ReporterName, e as ReporterOptions, f as ReporterOutput, g as waitForReport, w as writeReporters } from '../shared/meodp.8369c4c1.js';
5
+
6
+ /** Check only the supplied URLs. HTTP failures become observations; invalid input rejects. */
7
+ declare function checkLinks(input: readonly (string | LinkTarget)[], options?: CheckOptions): Promise<CheckReport>;
8
+
9
+ declare function formatReport(report: CheckReport, format?: 'json' | 'markdown' | 'html'): string;
10
+ declare function writeReports(report: CheckReport, directory: string): Promise<{
11
+ json: string;
12
+ markdown: string;
13
+ html: string;
14
+ }>;
15
+ /** Export a portable static site. Hosting refreshes the sidecar; file:// uses the embedded snapshot. */
16
+ declare function writeReportSite(report: CheckReport | undefined, directory: string, options?: ReportSiteOptions): Promise<{
17
+ index: string;
18
+ json?: string;
19
+ }>;
20
+ /** A missing file starts history; malformed or incompatible history is an error. */
21
+ declare function readReport(path: string): Promise<CheckReport | undefined>;
22
+ /** Write history only after a completed run; replace it atomically. */
23
+ declare function saveReport(report: CheckReport, path: string): Promise<void>;
24
+
25
+ /** Shared by the Node reader and the static viewer; report files are untrusted input. */
26
+ declare function parseReport(data: unknown): CheckReport;
27
+
28
+ /** Read and validate a complete, deduplicated page list without requesting the pages. */
29
+ declare function readSitemapUrls(source: string, options?: SitemapOptions): Promise<string[]>;
30
+ /** Check sitemap-listed pages using the same linkinator adapter, history, and report schema as checkLinks. */
31
+ declare function checkSitemap(source: string, options?: SitemapOptions): Promise<{
32
+ startedAt: string;
33
+ schemaVersion: 1;
34
+ observer: string;
35
+ completedAt: string;
36
+ summary: Record<Availability, number> & {
37
+ total: number;
38
+ redirected: number;
39
+ recovered: number;
40
+ };
41
+ results: LinkObservation[];
42
+ }>;
43
+
44
+ export { Availability, CheckOptions, CheckReport, LinkObservation, LinkTarget, ReportSiteOptions, SitemapOptions, checkLinks, checkSitemap, formatReport, parseReport, readReport, readSitemapUrls, saveReport, writeReportSite, writeReports };
@@ -0,0 +1,13 @@
1
+ export { a as checkLinks, c as checkSitemap, r as readSitemapUrls, b as waitForReport, w as writeReporters } from '../shared/meodp.80ff918d.mjs';
2
+ export { f as formatReport, p as parseReport, r as readReport, s as saveReport, a as writeReportSite, w as writeReports } from '../shared/meodp.9c706389.mjs';
3
+ import 'node:timers/promises';
4
+ import 'linkinator';
5
+ import 'node:os';
6
+ import 'node:fs/promises';
7
+ import 'node:path';
8
+ import 'node:process';
9
+ import 'node:buffer';
10
+ import 'node:util';
11
+ import 'node:zlib';
12
+ import 'fast-xml-parser';
13
+ import 'node:crypto';
@@ -235,8 +235,8 @@ const cli = yargs__default(helpers.hideBin(process__default$1.argv)).scriptName(
235
235
  await output(argv.type);
236
236
  }
237
237
  ).alias("h", "help").alias("v", "version").showHelpOnFail(false).help();
238
- function run() {
239
- cli.parse();
238
+ async function run(args = helpers.hideBin(process__default$1.argv), scriptName = "meodp") {
239
+ await cli.scriptName(scriptName).parseAsync(args);
240
240
  }
241
241
 
242
242
  exports.__DEV__ = __DEV__;
@@ -6,6 +6,6 @@ declare const __DEV__ = false;
6
6
  */
7
7
  declare function debug(name: string, ...args: any[]): void;
8
8
  declare const cli: yargs.Argv<{}>;
9
- declare function run(): void;
9
+ declare function run(args?: string[], scriptName?: string): Promise<void>;
10
10
 
11
11
  export { __DEV__, cli, debug, run };
@@ -6,6 +6,6 @@ declare const __DEV__ = false;
6
6
  */
7
7
  declare function debug(name: string, ...args: any[]): void;
8
8
  declare const cli: yargs.Argv<{}>;
9
- declare function run(): void;
9
+ declare function run(args?: string[], scriptName?: string): Promise<void>;
10
10
 
11
11
  export { __DEV__, cli, debug, run };
@@ -6,6 +6,6 @@ declare const __DEV__ = false;
6
6
  */
7
7
  declare function debug(name: string, ...args: any[]): void;
8
8
  declare const cli: yargs.Argv<{}>;
9
- declare function run(): void;
9
+ declare function run(args?: string[], scriptName?: string): Promise<void>;
10
10
 
11
11
  export { __DEV__, cli, debug, run };
@@ -224,8 +224,8 @@ const cli = yargs(hideBin(process$1.argv)).scriptName("meodp").usage("$0 \u68C0\
224
224
  await output(argv.type);
225
225
  }
226
226
  ).alias("h", "help").alias("v", "version").showHelpOnFail(false).help();
227
- function run() {
228
- cli.parse();
227
+ async function run(args = hideBin(process$1.argv), scriptName = "meodp") {
228
+ await cli.scriptName(scriptName).parseAsync(args);
229
229
  }
230
230
 
231
231
  export { __DEV__, cli, debug, run };