@goflag/cli 0.1.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.
@@ -0,0 +1,589 @@
1
+ type Severity = "error" | "warning" | "info";
2
+
3
+ /**
4
+ * Hreflang reciprocity + matrix derivation (Phase 7.4 / 7.5).
5
+ *
6
+ * Given a set of crawled `Page`s, builds two derived views:
7
+ *
8
+ * 1. A locale → route grid (`I18nMatrix`) the UI renders as a
9
+ * green/red heatmap. Routes are derived from the canonical or
10
+ * hreflang group, locales from the URL pathname segment when it
11
+ * looks like a known BCP 47 tag (`/fr`, `/en-us`, …).
12
+ *
13
+ * 2. Per-page reciprocity findings (`reciprocityIssues`) — when
14
+ * `/fr/about` declares an `<link rel="alternate" hreflang="en">`
15
+ * pointing at `/en/about`, but `/en/about` does not advertise
16
+ * `/fr/about` back, that's a Google-flagged broken cluster.
17
+ *
18
+ * Both helpers are pure: they accept a `Page[]` and return data, no
19
+ * I/O. The crawler in `crawl.ts` calls them once after the BFS
20
+ * finishes to populate the inspect-cache i18n payload.
21
+ *
22
+ * Locale code validity: we accept anything that matches BCP 47's
23
+ * basic shape (`[a-z]{2,3}(-[A-Z]{2})?`) plus `x-default`. Anything
24
+ * else flags as `locale.invalid`.
25
+ */
26
+
27
+ type ReciprocityCode = "missing-back-link" | "self-mismatch" | "x-default-missing" | "locale.invalid";
28
+ interface ReciprocityIssue {
29
+ code: ReciprocityCode;
30
+ /** URL of the page where the issue is observed. */
31
+ url: string;
32
+ /** Locale tag involved in the issue (or `x-default`). */
33
+ locale?: string;
34
+ /** Sister URL involved when the issue is cross-page. */
35
+ peerUrl?: string;
36
+ message: string;
37
+ }
38
+ interface I18nCell {
39
+ /** Absolute URL serving this (route, locale) cell. `null` when
40
+ * no page in the crawl filled this cell. */
41
+ url: string | null;
42
+ /** True when the page was actually inspected (vs. discovered only). */
43
+ inspected: boolean;
44
+ }
45
+ interface I18nMatrix {
46
+ /** Stable locale axis, `x-default` first when present, then BCP 47
47
+ * tags sorted alphabetically. */
48
+ locales: string[];
49
+ /** Stable route axis. Each route is a "canonical pathname" derived
50
+ * by stripping the leading locale segment. Sorted alphabetically. */
51
+ routes: string[];
52
+ /** `cells[route][locale]` lookup. Always populated for every
53
+ * (route, locale) pair, with `url: null` for missing alternates. */
54
+ cells: Record<string, Record<string, I18nCell>>;
55
+ }
56
+
57
+ /** The outcome of probing a single URL. */
58
+ type LinkVerdict = "ok" | "redirect" | "broken" | "blocked" | "warning" | "skipped";
59
+
60
+ /**
61
+ * Baseline comparison.
62
+ *
63
+ * Every finding already carries a `fingerprint` id derived from the *identity*
64
+ * of the problem rather than its transient details, and page URLs are
65
+ * normalised to origin-independent routes — so the same defect fingerprints
66
+ * identically on localhost, staging and production. That machinery was built
67
+ * for exactly this and had no consumer.
68
+ *
69
+ * What it changes is what the tool *is*. Without a baseline the CI gate is
70
+ * binary: any finding fails, which is unusable on a site that is not clean
71
+ * yet, so teams either never turn it on or learn to ignore it. With one, the
72
+ * gate becomes "no *new* findings" — a promise a real codebase can keep while
73
+ * the backlog is worked down.
74
+ *
75
+ * Pure function of two reports. No I/O; the CLI reads the baseline file.
76
+ */
77
+
78
+ /** Which part of the report a finding came from. */
79
+ type FindingKind = "brokenLink" | "unreachablePage" | "translationHole" | "reciprocity" | "seo" | "site";
80
+ /** One finding, flattened out of its report section for comparison. */
81
+ interface DiffEntry {
82
+ id: string;
83
+ kind: FindingKind;
84
+ /**
85
+ * Severity used for the exit-code decision. Rule findings carry their own;
86
+ * the rest are mapped to match the verdict logic in `build.ts` — a broken
87
+ * link or an unreachable page is an error, a translation gap is a warning.
88
+ */
89
+ severity: Severity;
90
+ /** One-line description, for the rendered diff. */
91
+ summary: string;
92
+ /** Page the finding sits on, when it has one. */
93
+ pageUrl?: string;
94
+ }
95
+ interface ReportDiff {
96
+ /** Where and when the baseline was taken, echoed for the report header. */
97
+ baseline: {
98
+ url: string;
99
+ finishedAt: string;
100
+ };
101
+ /** Findings present now and absent from the baseline — what should fail CI. */
102
+ added: DiffEntry[];
103
+ /** Findings in the baseline that are gone. Worth showing: progress is data too. */
104
+ resolved: DiffEntry[];
105
+ /** Findings present in both. */
106
+ unchanged: number;
107
+ }
108
+
109
+ /**
110
+ * The Goflag report — the single source of truth.
111
+ *
112
+ * Everything the CLI prints is a pure function of this object. It is fully
113
+ * JSON-serializable so `goflag <url> --json` and `--report out.json` emit it
114
+ * verbatim, and CI can diff / gate on it.
115
+ */
116
+
117
+ type Verdict = "green" | "yellow" | "red";
118
+ /** A page that was crawled, with just what the report needs. */
119
+ interface ReportPage {
120
+ url: string;
121
+ status: number;
122
+ /** Locale inferred from the leading path segment, or null when unprefixed. */
123
+ locale: string | null;
124
+ }
125
+ /** One problematic link, mapped back to the page that references it. */
126
+ interface BrokenLink {
127
+ /** Stable fingerprint of this finding (see `./fingerprint.ts`). */
128
+ id: string;
129
+ /** The page the link was found on. */
130
+ pageUrl: string;
131
+ /** The link target (canonical URL that was probed). */
132
+ href: string;
133
+ /** Final HTTP status (`0` = network error). */
134
+ status: number;
135
+ verdict: LinkVerdict;
136
+ /** Human-readable reason (network reason, "soft-404", "429 rate-limited", ...). */
137
+ reason?: string;
138
+ }
139
+ /** A route present in some locales but missing in others. */
140
+ interface TranslationHole {
141
+ /** Stable fingerprint of this finding (see `./fingerprint.ts`). */
142
+ id: string;
143
+ /** Canonical route (locale segment stripped), e.g. `/about`. */
144
+ route: string;
145
+ /** Locales that serve this route. */
146
+ presentLocales: string[];
147
+ /** Locales that are missing a translation for this route. */
148
+ missingLocales: string[];
149
+ }
150
+ /** A reciprocity / hreflang finding, carrying a stable fingerprint. */
151
+ type ReportReciprocityIssue = ReciprocityIssue & {
152
+ /** Stable fingerprint of this finding (see `./fingerprint.ts`). */
153
+ id: string;
154
+ };
155
+ /** A crawled page that returned a non-2xx status (errored / unreachable). */
156
+ interface UnreachablePage {
157
+ /** Stable fingerprint of this finding (see `./fingerprint.ts`). */
158
+ id: string;
159
+ url: string;
160
+ /** HTTP status (`0` = network error). */
161
+ status: number;
162
+ }
163
+ /**
164
+ * One cross-page finding — a policy that needed the whole site to evaluate
165
+ * (hreflang coverage, `<head>` vs sitemap agreement). Same shape as `SeoIssue`
166
+ * so consumers render them identically; `ruleId` says which registry it came
167
+ * from.
168
+ */
169
+ interface SiteIssue {
170
+ /** Stable fingerprint of this finding (see `./fingerprint.ts`). */
171
+ id: string;
172
+ /** Page the finding is attributed to. */
173
+ pageUrl: string;
174
+ ruleId: string;
175
+ severity: Severity;
176
+ message: string;
177
+ /** Why this rule exists (the rule's one-line summary). */
178
+ why?: string;
179
+ /** A copy-pasteable fix snippet, when the rule offers one. */
180
+ fix?: string;
181
+ }
182
+ /** How the audit established which locales the site serves. */
183
+ interface LocaleAxisReport {
184
+ locales: string[];
185
+ /** `none` when nothing declared an axis — goflag does not guess one. */
186
+ source: "explicit" | "sitemap" | "none";
187
+ multilingual: boolean;
188
+ /**
189
+ * Locale-looking prefixes seen in the crawl, with the evidence for and
190
+ * against each. Only populated when `source` is `none`; a suggestion for
191
+ * `--locales`, never promoted automatically.
192
+ */
193
+ candidates?: Array<{
194
+ tag: string;
195
+ pages: number;
196
+ isKnownLanguage: boolean;
197
+ htmlLangAgrees?: boolean;
198
+ observedLangs: string[];
199
+ }>;
200
+ }
201
+ /** One SEO metadata finding on a specific page. */
202
+ interface SeoIssue {
203
+ /** Stable fingerprint of this finding (see `./fingerprint.ts`). */
204
+ id: string;
205
+ pageUrl: string;
206
+ ruleId: string;
207
+ severity: Severity;
208
+ message: string;
209
+ /** Why this rule exists (the rule's one-line summary). */
210
+ why?: string;
211
+ /** A copy-pasteable fix snippet, when the rule offers one. */
212
+ fix?: string;
213
+ }
214
+ interface GoflagReport {
215
+ /** The base URL the audit started from (normalized). */
216
+ url: string;
217
+ /** ISO timestamp when the audit finished. */
218
+ finishedAt: string;
219
+ summary: {
220
+ brokenLinks: number;
221
+ missingTranslations: number;
222
+ seoIssues: number;
223
+ /** Cross-page findings (hreflang coverage, head↔sitemap agreement). */
224
+ siteIssues: number;
225
+ unreachablePages: number;
226
+ verdict: Verdict;
227
+ };
228
+ /** Which locales the site serves, and how the audit found out. */
229
+ localeAxis: LocaleAxisReport;
230
+ pages: ReportPage[];
231
+ /** Crawled pages that returned a non-2xx status. */
232
+ unreachablePages: UnreachablePage[];
233
+ brokenLinks: BrokenLink[];
234
+ missingTranslations: {
235
+ /** Routes present in one locale but absent in another. */
236
+ holes: TranslationHole[];
237
+ /** hreflang reciprocity / x-default / invalid-locale findings. */
238
+ reciprocity: ReportReciprocityIssue[];
239
+ };
240
+ seoIssues: SeoIssue[];
241
+ /** Findings from the cross-page rule registry (`SITE_RULES`). */
242
+ siteIssues: SiteIssue[];
243
+ /** Comparison against a stored baseline, when `--baseline` was given. */
244
+ diff?: ReportDiff;
245
+ diagnostics: {
246
+ pagesCrawled: number;
247
+ pagesScanned: number;
248
+ pagesFailed: number;
249
+ truncated: boolean;
250
+ warnings: string[];
251
+ /** Translation gaps suppressed by `--ignore-holes`, when any. */
252
+ ignoredHoles?: number;
253
+ /**
254
+ * Pages excluded from the rule layer because they declare a canonical
255
+ * pointing at another crawled page — the site's own statement that they
256
+ * are duplicates. Reported so a shrinking finding count is explicable.
257
+ */
258
+ duplicatePages?: number;
259
+ /** Sitemap discovery outcome, when discovery ran. */
260
+ sitemap?: {
261
+ found: boolean;
262
+ sitemapUrl?: string;
263
+ urlCount: number;
264
+ /** URLs the sitemap declared that the crawl never reached. */
265
+ uncrawled: number;
266
+ };
267
+ };
268
+ }
269
+
270
+ /**
271
+ * Report orchestrator.
272
+ *
273
+ * One crawl feeds all three checks:
274
+ * - the crawled `Page[]` drives SEO lint + the i18n matrix, and
275
+ * - a synthetic `SiteDiscovery` built from the same page set drives the
276
+ * link audit.
277
+ *
278
+ * Everything funnels into a single `GoflagReport` (see `./types.ts`).
279
+ */
280
+
281
+ /**
282
+ * The phase of the audit a progress event belongs to:
283
+ * - "crawl": BFS-visiting + inspecting pages (SEO + i18n input).
284
+ * - "scan": re-reading each page's HTML to extract its links.
285
+ * - "links": probing each unique link target.
286
+ */
287
+ type AuditPhase = "crawl" | "scan" | "links";
288
+ /** A single progress tick, emitted as the audit advances. */
289
+ interface ProgressEvent {
290
+ phase: AuditPhase;
291
+ /** Items completed in the current phase. */
292
+ done: number;
293
+ /** Best-effort total for the phase (the crawl total grows as links are discovered). */
294
+ total: number;
295
+ /** The URL just processed, when the phase tracks one (crawl). */
296
+ url?: string;
297
+ /** HTTP status of `url`, when known (crawl). */
298
+ status?: number;
299
+ }
300
+ interface AuditOptions {
301
+ /** BFS crawl depth. `0` = entry only. Defaults to 2. */
302
+ depth?: number;
303
+ /** Hard cap on pages crawled. Defaults to 200. */
304
+ maxPages?: number;
305
+ /** Glob include filter on the URL pathname. */
306
+ include?: string[];
307
+ /** Glob exclude filter on the URL pathname. */
308
+ exclude?: string[];
309
+ /** Probe external (off-origin) links too. Defaults to true. */
310
+ checkExternal?: boolean;
311
+ /** Skip Chromium: static HTML only (no SPA rendering). Defaults to false. */
312
+ static?: boolean;
313
+ /** Allow self-signed / invalid TLS (localhost, tunnels). */
314
+ allowInsecureTls?: boolean;
315
+ /** Per-request timeout in ms. Defaults to 8_000. */
316
+ timeoutMs?: number;
317
+ /** Caller-driven cancellation. */
318
+ signal?: AbortSignal;
319
+ /** Progress callback for a live CLI. */
320
+ onProgress?: (event: ProgressEvent) => void;
321
+ /**
322
+ * Locales the site serves, when the operator knows better than we can infer
323
+ * (`--locales fr,en,pt-br`). Strongest input to the locale axis.
324
+ */
325
+ locales?: string[];
326
+ /**
327
+ * Routes (locale-free, glob-matched) that are deliberately not translated
328
+ * everywhere, so their gaps are not reported as missing translations.
329
+ * Suppression is counted in `diagnostics.ignoredHoles` — a silenced finding
330
+ * that leaves no trace reads as "nothing was wrong".
331
+ */
332
+ ignoreHoles?: string[];
333
+ /**
334
+ * Skip sitemap discovery and seed the crawl from `<url>` alone. Defaults to
335
+ * false — discovery is on by default because crawl-only discovery is exactly
336
+ * what made hreflang checks silently vacuous.
337
+ */
338
+ noSitemap?: boolean;
339
+ }
340
+ /**
341
+ * Routes present in some locales but absent in others. A "hole" is exactly
342
+ * the "missing translation page" the tool exists to find. `x-default` is a
343
+ * fallback pointer, not a real translation, so it never counts as a locale
344
+ * that must be filled.
345
+ *
346
+ * `ignoreRoutes` globs out routes the operator has declared intentionally
347
+ * partial. A site has no markup for "this page does not exist here on
348
+ * purpose", so a deliberate gap and a forgotten one are indistinguishable from
349
+ * outside — only the operator can tell them apart. Without a way to say so, the
350
+ * report can never reach zero on a site with a jurisdiction-specific legal
351
+ * page, and a report that can never be clean teaches its reader to ignore it.
352
+ *
353
+ * Globs match the locale-free route (`/legal`, `/blog/**`), using the same
354
+ * matcher as `--include`/`--exclude`.
355
+ */
356
+ declare function deriveTranslationHoles(matrix: I18nMatrix, ignoreRoutes?: readonly string[]): TranslationHole[];
357
+ /**
358
+ * The severity at or above which findings should fail the process.
359
+ *
360
+ * `warning` is the historical behaviour (any finding fails). `error` lets a
361
+ * team adopt goflag on a site that is not clean yet: warnings stay visible in
362
+ * the report while only hard errors block a merge. `never` reports without
363
+ * ever failing, for exploratory runs.
364
+ */
365
+ type FailOn = "warning" | "error" | "never";
366
+ /**
367
+ * Map a report to a process exit code:
368
+ * 0 = clean (or below the failure threshold), 1 = findings at/above it.
369
+ * Used by the CLI as a CI gate.
370
+ *
371
+ * `red` always fails unless `never`: a red verdict also covers broken links,
372
+ * unreachable pages and a blind link scan — states where "no findings" would
373
+ * be a lie rather than a pass.
374
+ */
375
+ declare function exitCode(report: GoflagReport, failOn?: FailOn): number;
376
+ /** Run the full audit and return the report. Never throws for site-level failures. */
377
+ declare function runAudit(inputUrl: string, options?: AuditOptions): Promise<GoflagReport>;
378
+
379
+ /**
380
+ * Render a `GoflagReport` as a human-readable terminal report.
381
+ *
382
+ * Pure function of the report — no I/O. Colour is disabled automatically
383
+ * when stdout is not a TTY or `NO_COLOR` is set.
384
+ */
385
+
386
+ interface RenderOptions$1 {
387
+ color?: boolean;
388
+ }
389
+ declare function renderTerminal(report: GoflagReport, options?: RenderOptions$1): string;
390
+
391
+ /**
392
+ * Roll a full `GoflagReport` up into a compact `GoflagSummary`.
393
+ *
394
+ * The full report lists every finding on every page — great for a baseline
395
+ * file or a diff, but noisy for a human skim and expensive for an LLM agent
396
+ * to read. The summary deduplicates:
397
+ *
398
+ * - broken links by target (one entry per broken URL, with the pages that
399
+ * link to it),
400
+ * - SEO issues by rule (one entry per rule, carrying its `why`/`fix` once,
401
+ * with a sample of affected pages),
402
+ * - reciprocity findings by code.
403
+ *
404
+ * It is a pure function of the report — `goflag <url> --summary` and
405
+ * `--summary --json` both derive their output from this, so the rollup logic
406
+ * lives in exactly one place.
407
+ */
408
+
409
+ /** How many example pages/URLs a rolled-up entry keeps before it says "+N more". */
410
+ declare const SAMPLE_LIMIT = 5;
411
+ /** One broken target, with every page that links to it collapsed together. */
412
+ interface RollupLink {
413
+ href: string;
414
+ verdict: LinkVerdict;
415
+ status: number;
416
+ reason?: string;
417
+ /** How many (page → link) references share this target + verdict. */
418
+ count: number;
419
+ /** Up to {@link SAMPLE_LIMIT} pages that reference it. */
420
+ pages: string[];
421
+ /** References beyond the sample. */
422
+ morePages: number;
423
+ }
424
+ /** One SEO rule, collapsed across every page it fired on. */
425
+ interface RollupSeo {
426
+ ruleId: string;
427
+ severity: Severity;
428
+ why?: string;
429
+ fix?: string;
430
+ /** A representative message (from the first occurrence). */
431
+ sample: string;
432
+ count: number;
433
+ pages: string[];
434
+ morePages: number;
435
+ }
436
+ /** One reciprocity code, collapsed across every page it fired on. */
437
+ interface RollupReciprocity {
438
+ code: ReciprocityCode;
439
+ count: number;
440
+ sample: string;
441
+ pages: string[];
442
+ morePages: number;
443
+ }
444
+ interface GoflagSummary {
445
+ url: string;
446
+ finishedAt: string;
447
+ verdict: Verdict;
448
+ totals: {
449
+ brokenLinks: number;
450
+ missingTranslations: number;
451
+ seoIssues: number;
452
+ siteIssues: number;
453
+ unreachablePages: number;
454
+ pagesCrawled: number;
455
+ pagesScanned: number;
456
+ pagesFailed: number;
457
+ };
458
+ unreachablePages: UnreachablePage[];
459
+ brokenLinks: RollupLink[];
460
+ translations: {
461
+ holes: TranslationHole[];
462
+ reciprocity: RollupReciprocity[];
463
+ };
464
+ seoIssues: RollupSeo[];
465
+ /** Cross-page findings, rolled up by rule exactly like `seoIssues`. */
466
+ siteIssues: RollupSeo[];
467
+ truncated: boolean;
468
+ warnings: string[];
469
+ }
470
+ declare function summarize(report: GoflagReport): GoflagSummary;
471
+
472
+ /**
473
+ * Render a `GoflagSummary` as a compact, deduplicated terminal report.
474
+ *
475
+ * Where `renderTerminal` lists every finding grouped by page, this lists each
476
+ * distinct problem once with a count and a small sample of affected pages —
477
+ * the view you want for a large crawl or a quick "is it green?" check. Pure
478
+ * function of the summary; no I/O.
479
+ */
480
+
481
+ interface RenderOptions {
482
+ color?: boolean;
483
+ }
484
+ declare function renderSummaryTerminal(summary: GoflagSummary, options?: RenderOptions): string;
485
+
486
+ /**
487
+ * Stable finding fingerprints.
488
+ *
489
+ * Every finding in the report carries an `id` — a short, deterministic key
490
+ * derived from the *identity* of the problem, not its transient details
491
+ * (status codes, character counts, wording). This is what lets an agent (or
492
+ * a CI baseline) say "finding `seo-1a2b3c4d5e` is still open" across runs,
493
+ * and — because page URLs are normalized to origin-independent routes — even
494
+ * across environments (localhost vs. staging vs. prod).
495
+ *
496
+ * Pure, no I/O. `createHash` is the only dependency.
497
+ */
498
+ /**
499
+ * Normalize a same-origin URL to a stable, origin-independent route key so a
500
+ * finding on `http://localhost:3000/en/about` and `https://site.com/en/about`
501
+ * fingerprints the same. Drops the origin, collapses a trailing slash, keeps
502
+ * the query string (it can change what page you get).
503
+ */
504
+ declare function routeKey(rawUrl: string): string;
505
+ /**
506
+ * Normalize a link target for fingerprinting. Unlike {@link routeKey} this
507
+ * keeps the origin, because a broken link's identity includes *where* it
508
+ * points (two different external hosts are two different findings). Only the
509
+ * trailing slash is normalized away.
510
+ */
511
+ declare function targetKey(rawUrl: string): string;
512
+ /**
513
+ * Build a finding id: `<category>-<10 hex chars>`. The parts are joined with
514
+ * a NUL separator (which can't appear in a URL or rule id) before hashing, so
515
+ * distinct tuples never collide by concatenation.
516
+ */
517
+ declare function fingerprint(category: string, ...parts: string[]): string;
518
+
519
+ /**
520
+ * Live progress logger for the CLI.
521
+ *
522
+ * Everything here writes to a *side* stream (stderr by default) so the JSON
523
+ * report on stdout is never polluted. Three modes:
524
+ *
525
+ * - "compact" (default): a single, in-place status line — spinner +
526
+ * progress bar + "done/total" + the current page. On a non-TTY (CI,
527
+ * pipes) it degrades to throttled plain lines so logs stay readable.
528
+ * - "verbose": one line per page as it is analyzed (status + URL), plus
529
+ * phase headers. No spinner; lines scroll.
530
+ * - "quiet": nothing at all.
531
+ *
532
+ * The logger is fed `ProgressEvent`s (see `./build.ts`) via `onProgress`,
533
+ * and the CLI calls `note()` for banners/warnings and `stop()` at the end.
534
+ */
535
+
536
+ type LogMode = "compact" | "verbose" | "quiet";
537
+ interface WriteStreamLike {
538
+ write(chunk: string): boolean;
539
+ isTTY?: boolean;
540
+ columns?: number;
541
+ }
542
+ interface LoggerOptions {
543
+ /** Destination stream. Defaults to `process.stderr`. */
544
+ stream?: WriteStreamLike;
545
+ /** Emit ANSI colour. Defaults to `stream.isTTY`. */
546
+ color?: boolean;
547
+ /** Display mode. Defaults to "compact". */
548
+ mode?: LogMode;
549
+ /** Spinner tick interval in ms. `0` disables the animating timer (tests). */
550
+ spinnerIntervalMs?: number;
551
+ /** Minimum gap between plain progress lines on a non-TTY. Defaults to 250. */
552
+ throttleMs?: number;
553
+ /** Injectable clock (tests). */
554
+ now?: () => number;
555
+ }
556
+ declare class Logger {
557
+ private readonly stream;
558
+ private readonly color;
559
+ private readonly mode;
560
+ private readonly isTTY;
561
+ private readonly spinnerIntervalMs;
562
+ private readonly throttleMs;
563
+ private readonly now;
564
+ private timer;
565
+ private frame;
566
+ private last;
567
+ private lineOpen;
568
+ private lastPlainAt;
569
+ private headerShown;
570
+ constructor(options?: LoggerOptions);
571
+ private paint;
572
+ /** Print a standalone line (banner, warning). Survives around the spinner. */
573
+ note(message: string): void;
574
+ /** Feed one progress tick. */
575
+ onProgress: (event: ProgressEvent) => void;
576
+ /** Stop the spinner and clear the status line so the report starts clean. */
577
+ stop(): void;
578
+ private ensureTimer;
579
+ private render;
580
+ private composeLine;
581
+ private bar;
582
+ private verboseLine;
583
+ private statusTag;
584
+ private plainThrottled;
585
+ private clearLine;
586
+ private truncate;
587
+ }
588
+
589
+ export { type AuditOptions, type AuditPhase, type BrokenLink, type GoflagReport, type GoflagSummary, type LogMode, Logger, type LoggerOptions, type ProgressEvent, type ReportPage, type ReportReciprocityIssue, type RollupLink, type RollupReciprocity, type RollupSeo, SAMPLE_LIMIT, type SeoIssue, type TranslationHole, type UnreachablePage, type Verdict, deriveTranslationHoles, exitCode, fingerprint, renderSummaryTerminal, renderTerminal, routeKey, runAudit, summarize, targetKey };
package/dist/index.js ADDED
@@ -0,0 +1,28 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ Logger,
4
+ SAMPLE_LIMIT,
5
+ deriveTranslationHoles,
6
+ exitCode,
7
+ fingerprint,
8
+ renderSummaryTerminal,
9
+ renderTerminal,
10
+ routeKey,
11
+ runAudit,
12
+ summarize,
13
+ targetKey
14
+ } from "./chunk-75OFMTOC.js";
15
+ export {
16
+ Logger,
17
+ SAMPLE_LIMIT,
18
+ deriveTranslationHoles,
19
+ exitCode,
20
+ fingerprint,
21
+ renderSummaryTerminal,
22
+ renderTerminal,
23
+ routeKey,
24
+ runAudit,
25
+ summarize,
26
+ targetKey
27
+ };
28
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}