@ekanos/cli 0.3.1 → 0.3.3
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 +13 -13
- package/dist/auth/credential-store.d.ts +1 -1
- package/dist/auth/credential-store.js +3 -2
- package/dist/auth/credential-store.js.map +1 -1
- package/dist/auth/device-flow.d.ts +1 -1
- package/dist/auth/device-flow.js +11 -10
- package/dist/auth/device-flow.js.map +1 -1
- package/dist/auth/{fusion-api.d.ts → ekanos-api.d.ts} +9 -9
- package/dist/auth/{fusion-api.js → ekanos-api.js} +28 -28
- package/dist/auth/ekanos-api.js.map +1 -0
- package/dist/auth/session.d.ts +5 -5
- package/dist/auth/session.js +8 -7
- package/dist/auth/session.js.map +1 -1
- package/dist/bin.js.map +1 -1
- package/dist/commands/dev.d.ts +2 -2
- package/dist/commands/dev.js.map +1 -1
- package/dist/commands/init.js +4 -0
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/login.d.ts +1 -1
- package/dist/commands/login.js +3 -3
- package/dist/commands/login.js.map +1 -1
- package/dist/commands/logout.js +1 -1
- package/dist/commands/logout.js.map +1 -1
- package/dist/commands/publish.d.ts +2 -2
- package/dist/commands/publish.js +3 -3
- package/dist/commands/publish.js.map +1 -1
- package/dist/commands/sources.js.map +1 -1
- package/dist/commands/status.js +5 -7
- package/dist/commands/status.js.map +1 -1
- package/dist/commands/test.js.map +1 -1
- package/dist/commands/upgrade.js +1 -1
- package/dist/commands/upgrade.js.map +1 -1
- package/dist/commands/use.js +1 -1
- package/dist/commands/use.js.map +1 -1
- package/dist/commands/validate.js.map +1 -1
- package/dist/commands/whoami.d.ts +1 -1
- package/dist/commands/whoami.js +1 -1
- package/dist/commands/whoami.js.map +1 -1
- package/dist/compatibility.js.map +1 -1
- package/dist/context.js.map +1 -1
- package/dist/delegate.js.map +1 -1
- package/dist/did-you-mean.js +26 -15
- package/dist/did-you-mean.js.map +1 -1
- package/dist/exit-codes.d.ts +10 -10
- package/dist/findings-renderer.js +6 -4
- package/dist/findings-renderer.js.map +1 -1
- package/dist/generated/fa-free-names.d.ts +1 -1
- package/dist/generated/fa-free-names.js +1 -1
- package/dist/generated/fa-free-names.js.map +1 -1
- package/dist/harness-scaffold.d.ts +1 -1
- package/dist/harness-scaffold.js +4 -2
- package/dist/harness-scaffold.js.map +1 -1
- package/dist/icon-findings.d.ts +1 -1
- package/dist/icon-findings.js +2 -2
- package/dist/icon-findings.js.map +1 -1
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/merge-manifest.js.map +1 -1
- package/dist/pack.js +1 -1
- package/dist/pack.js.map +1 -1
- package/dist/project-checks.js.map +1 -1
- package/dist/project.d.ts +7 -84
- package/dist/project.js +3 -3
- package/dist/project.js.map +1 -1
- package/dist/publish-api.d.ts +5 -5
- package/dist/publish-api.js +27 -33
- package/dist/publish-api.js.map +1 -1
- package/dist/safe-fs.js.map +1 -1
- package/dist/schema-skew.js.map +1 -1
- package/dist/source-locator.js.map +1 -1
- package/dist/sources-api.d.ts +3 -3
- package/dist/sources-api.js +11 -14
- package/dist/sources-api.js.map +1 -1
- package/dist/templates.js.map +1 -1
- package/dist/test-report.js.map +1 -1
- package/dist/toolchain-api.d.ts +4 -4
- package/dist/toolchain-api.js +1 -1
- package/dist/toolchain-api.js.map +1 -1
- package/dist/toolchain-resolve.js.map +1 -1
- package/dist/toolchain.d.ts +5 -5
- package/dist/ui.js +2 -8
- package/dist/ui.js.map +1 -1
- package/dist/update-notice.d.ts +1 -1
- package/dist/update-notice.js.map +1 -1
- package/dist/validate-findings.js.map +1 -1
- package/dist/wizard.js.map +1 -1
- package/package.json +15 -20
- package/templates/AGENTS.md.tmpl +13 -8
- package/templates/CLAUDE.md.tmpl +1 -1
- package/templates/claude-skill.md.tmpl +2 -2
- package/templates/harness/next.config.mjs.tmpl +1 -1
- package/templates/package.json.tmpl +6 -5
- package/templates/pnpm-workspace.yaml.tmpl +8 -0
- package/templates/skills/build-integration/SKILL.md +3 -3
- package/templates/skills/build-integration/references/api-wiring.md +2 -2
- package/templates/skills/build-integration/references/widget-design.md +1 -1
- package/dist/auth/fusion-api.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"findings-renderer.js","sourceRoot":"","sources":["../src/findings-renderer.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Finding } from '@ekanos/integration-schema';\nimport * as fs from 'node:fs';\nimport * as path from 'node:path';\n\nimport type { CliContext } from './context';\nimport type { GateFinding } from './publish-api';\nimport { ENCLOSING_NOTE } from './source-locator';\nimport type { BadgeKind, Ui } from './ui';\n\n/**\n * The shared findings block: one rendering used by `validate` (a failed run),\n * `publish` (a gate refusal), and `status --findings`, so a partner sees the\n * exact same shape wherever a finding shows up. This is the ONLY findings\n * renderer in the package — nothing else may hand-format a `Finding`/\n * `GateFinding` array for a human.\n *\n * Deliberately structural rather than importing `Finding` or `GateFinding`\n * directly as the parameter type: both already satisfy this shape (their\n * extra/missing fields are all optional), and a structural type keeps this\n * module from caring which of the two ships that array.\n */\nexport interface RenderableFinding {\n check: string;\n severity: 'error' | 'warn' | 'info';\n file?: string;\n line?: number;\n message: string;\n hint: string;\n /** `'gate' | 'ci' | 'host' | 'revocation'` on the wire — see `GateFinding`. */\n origin?: string;\n createdAt?: string;\n resolvedAt?: string | null;\n /**\n * Optional multi-line supplement rendered directly under the finding's\n * message — currently only `ekanos test`'s curated failures appendix sets\n * this (an assertion diff). Additive: neither `Finding` nor `GateFinding`\n * carries it, so every pre-existing caller renders byte-identically to\n * before. Lines are shown as-is except a leading `-`/`+` (unified-diff\n * style), which is colored red/green respectively.\n */\n detail?: string;\n}\n\n// Compile-time proof the two real shapes this renders are both assignable.\nconst _typeCheck: (f: Finding | GateFinding) => RenderableFinding = (f) => f;\nvoid _typeCheck;\n\nexport interface RenderFindingsOptions {\n /** Findings shown per group before an overflow line takes over. Default 10. */\n maxPerGroup?: number;\n /** Base for resolving a finding's `file` before reading it for a codeframe. Default `process.cwd()`. */\n cwd?: string;\n /** Injectable for `relativeTime` snapshot tests. Default `new Date()`. */\n now?: Date;\n}\n\nconst DEFAULT_MAX_PER_GROUP = 10;\n\nconst SEVERITY_RANK: Record<RenderableFinding['severity'], number> = {\n error: 0,\n warn: 1,\n info: 2,\n};\n\ninterface Group {\n check: string;\n findings: RenderableFinding[];\n /** Insertion order, for a stable tie-break when sorting groups. */\n order: number;\n}\n\n/**\n * `relativeTime('2026-09-01T10:00:00Z')` → `\"2h ago\"`. Deliberately coarse\n * (rounds to the nearest unit, one unit at a time) — this is a findings-list\n * badge, not an audit-log timestamp, and a partner scanning for \"is this\n * recent\" doesn't need sub-minute precision.\n */\nexport function relativeTime(iso: string, now: Date = new Date()): string {\n const then = new Date(iso).getTime();\n if (Number.isNaN(then)) return iso;\n\n const diffSec = Math.max(0, Math.round((now.getTime() - then) / 1000));\n\n if (diffSec < 5) return 'just now';\n if (diffSec < 60) return `${diffSec}s ago`;\n\n const diffMin = Math.round(diffSec / 60);\n if (diffMin < 60) return `${diffMin}m ago`;\n\n const diffHour = Math.round(diffMin / 60);\n if (diffHour < 24) return `${diffHour}h ago`;\n\n const diffDay = Math.round(diffHour / 24);\n if (diffDay < 30) return `${diffDay}d ago`;\n\n const diffMonth = Math.round(diffDay / 30);\n if (diffMonth < 12) return `${diffMonth}mo ago`;\n\n const diffYear = Math.round(diffMonth / 12);\n return `${diffYear}y ago`;\n}\n\n/**\n * A message beginning with a zod-style dot-path (`components.widgets[2].id: …`,\n * the shape `collectDefinitionFindings` produces — see the `Finding` doc\n * comment in `@ekanos/integration-schema`). Captures the path and the rest\n * separately so the renderer can dim the path instead of shouting the whole\n * sentence in one uniform color.\n */\nconst DOT_PATH_MESSAGE =\n /^([A-Za-z0-9_]+(?:\\.[A-Za-z0-9_]+|\\[\\d+\\])*): ([^]+)$/;\n\n/**\n * Render one finding's message: a leading dot-path identical to the\n * finding's own `file` is pure duplication (the path would just repeat what\n * `file:line` already told the reader) and is dropped; any other dot-path\n * prefix is kept but dimmed, so the sentence itself reads at full contrast.\n * A message with no dot-path prefix passes through untouched.\n *\n * A trailing `source-locator.ts` `ENCLOSING_NOTE` (plain text in the data —\n * see that module's doc comment on why it never carries color itself) is\n * peeled off before the dot-path handling above and dimmed on its own, then\n * reattached — so it stays visually secondary to the message itself in\n * exactly the case where the frame it accompanies points at the enclosing\n * object rather than the missing key.\n */\nfunction renderMessage(ui: Ui, finding: RenderableFinding): string {\n const enclosingSuffix = ` ${ENCLOSING_NOTE}`;\n const hasEnclosingNote = finding.message.endsWith(enclosingSuffix);\n const message = hasEnclosingNote\n ? finding.message.slice(0, -enclosingSuffix.length)\n : finding.message;\n\n const match = DOT_PATH_MESSAGE.exec(message);\n const rendered = (() => {\n if (!match) return message;\n\n const [, dotPath, rest] = match;\n if (dotPath === finding.file) return rest ?? message;\n\n return `${ui.dim(dotPath ?? '')}: ${rest ?? ''}`;\n })();\n\n return hasEnclosingNote ? `${rendered} ${ui.dim(ENCLOSING_NOTE)}` : rendered;\n}\n\nfunction severityColor(\n ui: Ui,\n severity: RenderableFinding['severity'],\n): (text: string) => string {\n if (severity === 'error') return ui.err;\n if (severity === 'warn') return ui.warn;\n return ui.dim;\n}\n\nfunction severityGlyph(\n ui: Ui,\n severity: RenderableFinding['severity'],\n): string {\n if (severity === 'warn') return ui.glyphs.warn;\n if (severity === 'info') return ui.glyphs.info;\n return ui.glyphs.err;\n}\n\nfunction ellipsis(ui: Ui): string {\n return ui.glyphs.ok === '✓' ? '…' : '...';\n}\n\n/** Attempts a codeframe for `finding`; `null` when it isn't renderable (no line, or the file can't be read locally). */\nfunction tryCodeframe(\n ui: Ui,\n finding: RenderableFinding,\n cwd: string,\n): string | null {\n if (finding.file === undefined || finding.line === undefined) return null;\n\n const resolved = path.resolve(cwd, finding.file);\n if (!fs.existsSync(resolved)) return null;\n\n try {\n const source = fs.readFileSync(resolved, 'utf8');\n return ui.codeframe({ file: finding.file, line: finding.line, source });\n } catch {\n // Best-effort decoration — an unreadable file (permissions, a race with\n // a concurrent edit) just means no codeframe, never a renderer failure.\n return null;\n }\n}\n\nfunction originBadgeKind(_origin: string): BadgeKind {\n return 'dim';\n}\n\n/**\n * Renders a finding's `detail` block, one line per source line: a\n * unified-diff `-` prefix is red, a `+` prefix is green, everything else\n * (context lines, \"Expected\"/\"Received\" headers, an overflow note) is dim.\n * `---`/`+++` file-header lines never appear here — `test-report.ts` never\n * emits them — but are guarded against anyway since this is the one place\n * that would mis-color them.\n */\nfunction renderDetailLines(ui: Ui, detail: string): string[] {\n return detail.split('\\n').map((line) => {\n if (line.startsWith('-') && !line.startsWith('---')) return ui.err(line);\n if (line.startsWith('+') && !line.startsWith('+++')) return ui.ok(line);\n return ui.dim(line);\n });\n}\n\nfunction buildGroupHeader(\n ui: Ui,\n group: Group,\n opts: Required<Pick<RenderFindingsOptions, 'now'>>,\n): string {\n const errorCount = group.findings.filter(\n (f) => f.severity === 'error',\n ).length;\n const warnCount = group.findings.filter((f) => f.severity === 'warn').length;\n const infoCount = group.findings.filter((f) => f.severity === 'info').length;\n\n const worst = group.findings[0]?.severity ?? 'info';\n const color = severityColor(ui, worst);\n const glyph = severityGlyph(ui, worst);\n\n const parts: string[] = [];\n if (errorCount > 0)\n parts.push(`${errorCount} error${errorCount === 1 ? '' : 's'}`);\n if (warnCount > 0)\n parts.push(`${warnCount} warning${warnCount === 1 ? '' : 's'}`);\n if (infoCount > 0) parts.push(`${infoCount} info`);\n\n // The representative for the group's origin badge is the first (i.e.\n // worst-severity, then earliest) finding that carries one — a check\n // almost always shares one origin, and this avoids a badge per line.\n const withOrigin = group.findings.find((f) => f.origin !== undefined);\n const badge =\n withOrigin?.origin === undefined\n ? ''\n : ` ${ui.badge(\n withOrigin.createdAt\n ? `${withOrigin.origin} · ${relativeTime(withOrigin.createdAt, opts.now)}`\n : withOrigin.origin,\n originBadgeKind(withOrigin.origin),\n )}`;\n\n return `${color(`${glyph} ${group.check}`)} · ${parts.join(', ')}${badge}`;\n}\n\nfunction buildGroupBody(\n ui: Ui,\n group: Group,\n opts: Required<Pick<RenderFindingsOptions, 'maxPerGroup' | 'cwd'>>,\n): string[] {\n const uniqueHints = [...new Set(group.findings.map((f) => f.hint))];\n const [firstHint] = uniqueHints;\n const dedupedHint =\n uniqueHints.length === 1 && firstHint !== undefined ? firstHint : null;\n\n const visible = group.findings.slice(0, opts.maxPerGroup);\n const overflow = group.findings.length - visible.length;\n\n const lines: string[] = [];\n let codeframeRendered = false;\n\n for (const finding of visible) {\n const location =\n finding.file !== undefined\n ? ui.accent(\n finding.line !== undefined\n ? `${finding.file}:${finding.line}`\n : finding.file,\n )\n : null;\n const message = renderMessage(ui, finding);\n\n lines.push(` ${ui.dim('│')}${location ? ` ${location}` : ''} ${message}`);\n\n if (finding.detail !== undefined) {\n lines.push(\n ...renderDetailLines(ui, finding.detail).map((line) => ` ${line}`),\n );\n }\n\n if (dedupedHint === null) {\n lines.push(` ${ui.hint(finding.hint)}`);\n }\n\n if (!codeframeRendered) {\n const frame = tryCodeframe(ui, finding, opts.cwd);\n if (frame !== null) {\n codeframeRendered = true;\n lines.push(\n frame\n .split('\\n')\n .map((line) => ` ${line}`)\n .join('\\n'),\n );\n }\n }\n }\n\n if (overflow > 0) {\n lines.push(\n ` ${ui.dim(`${ellipsis(ui)} and ${overflow} more in this group`)}`,\n );\n }\n\n if (dedupedHint !== null) {\n lines.push(` ${ui.hint(dedupedHint)}`);\n }\n\n return lines;\n}\n\n/**\n * Pure formatter — no I/O beyond an optional codeframe file read, no\n * printing. Kept separate from `renderFindings` so tests can assert exact\n * strings against a `Ui` built with a known color/glyph decision, without\n * constructing a full `CliContext`.\n */\nexport function formatFindings(\n ui: Ui,\n findings: readonly RenderableFinding[],\n options: RenderFindingsOptions = {},\n): string {\n if (findings.length === 0) return '';\n\n const maxPerGroup = options.maxPerGroup ?? DEFAULT_MAX_PER_GROUP;\n const cwd = options.cwd ?? process.cwd();\n const now = options.now ?? new Date();\n\n const groupsByCheck = new Map<string, Group>();\n findings.forEach((finding, index) => {\n const existing = groupsByCheck.get(finding.check);\n if (existing) {\n existing.findings.push(finding);\n return;\n }\n groupsByCheck.set(finding.check, {\n check: finding.check,\n findings: [finding],\n order: index,\n });\n });\n\n const groups = [...groupsByCheck.values()];\n for (const group of groups) {\n group.findings.sort(\n (a, b) => SEVERITY_RANK[a.severity] - SEVERITY_RANK[b.severity],\n );\n }\n groups.sort((a, b) => {\n const worstA = SEVERITY_RANK[a.findings[0]?.severity ?? 'info'];\n const worstB = SEVERITY_RANK[b.findings[0]?.severity ?? 'info'];\n return worstA - worstB || a.order - b.order;\n });\n\n const blocks = groups.map((group) => {\n const header = buildGroupHeader(ui, group, { now });\n const body = buildGroupBody(ui, group, { maxPerGroup, cwd });\n return [header, ...body].join('\\n');\n });\n\n const totalErrors = findings.filter((f) => f.severity === 'error').length;\n const totalWarnings = findings.filter((f) => f.severity === 'warn').length;\n const totalInfo = findings.filter((f) => f.severity === 'info').length;\n\n const summaryParts: string[] = [];\n if (totalErrors > 0)\n summaryParts.push(`${totalErrors} error${totalErrors === 1 ? '' : 's'}`);\n if (totalWarnings > 0)\n summaryParts.push(\n `${totalWarnings} warning${totalWarnings === 1 ? '' : 's'}`,\n );\n if (totalInfo > 0 && totalErrors === 0 && totalWarnings === 0) {\n summaryParts.push(`${totalInfo} info`);\n }\n\n const summaryColor =\n totalErrors > 0 ? ui.err : totalWarnings > 0 ? ui.warn : ui.dim;\n const summaryGlyph =\n totalErrors > 0\n ? ui.glyphs.err\n : totalWarnings > 0\n ? ui.glyphs.warn\n : ui.glyphs.info;\n const checksCount = groups.length;\n\n const summary = summaryColor(\n `${summaryGlyph} ${summaryParts.join(', ')} across ${checksCount} check${\n checksCount === 1 ? '' : 's'\n }`,\n );\n\n return [...blocks, summary].join('\\n\\n');\n}\n\n/** Render the shared findings block to `ctx`'s human-mode output (stderr). A no-op for an empty findings array. */\nexport function renderFindings(\n ctx: CliContext,\n findings: readonly RenderableFinding[],\n options: RenderFindingsOptions = {},\n): void {\n const block = formatFindings(ctx.ui, findings, options);\n if (block !== '') ctx.log(block);\n}\n"]}
|
|
1
|
+
{"version":3,"file":"findings-renderer.js","sourceRoot":"","sources":["../src/findings-renderer.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Finding } from '@ekanos/integration-schema';\nimport * as fs from 'node:fs';\nimport * as path from 'node:path';\n\nimport type { CliContext } from './context';\nimport type { GateFinding } from './publish-api';\nimport { ENCLOSING_NOTE } from './source-locator';\nimport type { BadgeKind, Ui } from './ui';\n\n/**\n * The shared findings block: one rendering used by `validate` (a failed run),\n * `publish` (a gate refusal), and `status --findings`, so a partner sees the\n * exact same shape wherever a finding shows up. This is the ONLY findings\n * renderer in the package — nothing else may hand-format a `Finding`/\n * `GateFinding` array for a human.\n *\n * Deliberately structural rather than importing `Finding` or `GateFinding`\n * directly as the parameter type: both already satisfy this shape (their\n * extra/missing fields are all optional), and a structural type keeps this\n * module from caring which of the two ships that array.\n */\nexport interface RenderableFinding {\n check: string;\n severity: 'error' | 'warn' | 'info';\n file?: string;\n line?: number;\n message: string;\n hint: string;\n /** `'gate' | 'ci' | 'host' | 'revocation'` on the wire — see `GateFinding`. */\n origin?: string;\n createdAt?: string;\n resolvedAt?: string | null;\n /**\n * Optional multi-line supplement rendered directly under the finding's\n * message — currently only `ekanos test`'s curated failures appendix sets\n * this (an assertion diff). Additive: neither `Finding` nor `GateFinding`\n * carries it, so every pre-existing caller renders byte-identically to\n * before. Lines are shown as-is except a leading `-`/`+` (unified-diff\n * style), which is colored red/green respectively.\n */\n detail?: string;\n}\n\n// Compile-time proof the two real shapes this renders are both assignable.\nconst _typeCheck: (f: Finding | GateFinding) => RenderableFinding = (f) => f;\nvoid _typeCheck;\n\nexport interface RenderFindingsOptions {\n /** Findings shown per group before an overflow line takes over. Default 10. */\n maxPerGroup?: number;\n /** Base for resolving a finding's `file` before reading it for a codeframe. Default `process.cwd()`. */\n cwd?: string;\n /** Injectable for `relativeTime` snapshot tests. Default `new Date()`. */\n now?: Date;\n}\n\nconst DEFAULT_MAX_PER_GROUP = 10;\n\nconst SEVERITY_RANK: Record<RenderableFinding['severity'], number> = {\n error: 0,\n warn: 1,\n info: 2,\n};\n\ninterface Group {\n check: string;\n findings: RenderableFinding[];\n /** Insertion order, for a stable tie-break when sorting groups. */\n order: number;\n}\n\n/**\n * `relativeTime('2026-09-01T10:00:00Z')` → `\"2h ago\"`. Deliberately coarse\n * (rounds to the nearest unit, one unit at a time) — this is a findings-list\n * badge, not an audit-log timestamp, and a partner scanning for \"is this\n * recent\" doesn't need sub-minute precision.\n */\nexport function relativeTime(iso: string, now: Date = new Date()): string {\n const then = new Date(iso).getTime();\n if (Number.isNaN(then)) return iso;\n\n const diffSec = Math.max(0, Math.round((now.getTime() - then) / 1000));\n\n if (diffSec < 5) return 'just now';\n if (diffSec < 60) return `${diffSec}s ago`;\n\n const diffMin = Math.round(diffSec / 60);\n if (diffMin < 60) return `${diffMin}m ago`;\n\n const diffHour = Math.round(diffMin / 60);\n if (diffHour < 24) return `${diffHour}h ago`;\n\n const diffDay = Math.round(diffHour / 24);\n if (diffDay < 30) return `${diffDay}d ago`;\n\n const diffMonth = Math.round(diffDay / 30);\n if (diffMonth < 12) return `${diffMonth}mo ago`;\n\n const diffYear = Math.round(diffMonth / 12);\n return `${diffYear}y ago`;\n}\n\n/**\n * A message beginning with a zod-style dot-path (`components.widgets[2].id: …`,\n * the shape `collectDefinitionFindings` produces — see the `Finding` doc\n * comment in `@ekanos/integration-schema`). Captures the path and the rest\n * separately so the renderer can dim the path instead of shouting the whole\n * sentence in one uniform color.\n */\nconst DOT_PATH_MESSAGE =\n /^([A-Za-z0-9_]+(?:\\.[A-Za-z0-9_]+|\\[\\d+\\])*): ([^]+)$/;\n\n/**\n * Render one finding's message: a leading dot-path identical to the\n * finding's own `file` is pure duplication (the path would just repeat what\n * `file:line` already told the reader) and is dropped; any other dot-path\n * prefix is kept but dimmed, so the sentence itself reads at full contrast.\n * A message with no dot-path prefix passes through untouched.\n *\n * A trailing `source-locator.ts` `ENCLOSING_NOTE` (plain text in the data —\n * see that module's doc comment on why it never carries color itself) is\n * peeled off before the dot-path handling above and dimmed on its own, then\n * reattached — so it stays visually secondary to the message itself in\n * exactly the case where the frame it accompanies points at the enclosing\n * object rather than the missing key.\n */\nfunction renderMessage(ui: Ui, finding: RenderableFinding): string {\n const enclosingSuffix = ` ${ENCLOSING_NOTE}`;\n const hasEnclosingNote = finding.message.endsWith(enclosingSuffix);\n const message = hasEnclosingNote\n ? finding.message.slice(0, -enclosingSuffix.length)\n : finding.message;\n\n const match = DOT_PATH_MESSAGE.exec(message);\n const rendered = (() => {\n if (!match) return message;\n\n const [, dotPath, rest] = match;\n if (dotPath === finding.file) return rest ?? message;\n\n return `${ui.dim(dotPath ?? '')}: ${rest ?? ''}`;\n })();\n\n return hasEnclosingNote ? `${rendered} ${ui.dim(ENCLOSING_NOTE)}` : rendered;\n}\n\nfunction severityColor(\n ui: Ui,\n severity: RenderableFinding['severity'],\n): (text: string) => string {\n if (severity === 'error') return ui.err;\n if (severity === 'warn') return ui.warn;\n return ui.dim;\n}\n\nfunction severityGlyph(\n ui: Ui,\n severity: RenderableFinding['severity'],\n): string {\n if (severity === 'warn') return ui.glyphs.warn;\n if (severity === 'info') return ui.glyphs.info;\n return ui.glyphs.err;\n}\n\nfunction ellipsis(ui: Ui): string {\n return ui.glyphs.ok === '✓' ? '…' : '...';\n}\n\n/** Attempts a codeframe for `finding`; `null` when it isn't renderable (no line, or the file can't be read locally). */\nfunction tryCodeframe(\n ui: Ui,\n finding: RenderableFinding,\n cwd: string,\n): string | null {\n if (finding.file === undefined || finding.line === undefined) return null;\n\n const resolved = path.resolve(cwd, finding.file);\n if (!fs.existsSync(resolved)) return null;\n\n try {\n const source = fs.readFileSync(resolved, 'utf8');\n return ui.codeframe({ file: finding.file, line: finding.line, source });\n } catch {\n // Best-effort decoration — an unreadable file (permissions, a race with\n // a concurrent edit) just means no codeframe, never a renderer failure.\n return null;\n }\n}\n\nfunction originBadgeKind(_origin: string): BadgeKind {\n return 'dim';\n}\n\n/**\n * Renders a finding's `detail` block, one line per source line: a\n * unified-diff `-` prefix is red, a `+` prefix is green, everything else\n * (context lines, \"Expected\"/\"Received\" headers, an overflow note) is dim.\n * `---`/`+++` file-header lines never appear here — `test-report.ts` never\n * emits them — but are guarded against anyway since this is the one place\n * that would mis-color them.\n */\nfunction renderDetailLines(ui: Ui, detail: string): string[] {\n return detail.split('\\n').map((line) => {\n if (line.startsWith('-') && !line.startsWith('---')) return ui.err(line);\n if (line.startsWith('+') && !line.startsWith('+++')) return ui.ok(line);\n return ui.dim(line);\n });\n}\n\nfunction buildGroupHeader(\n ui: Ui,\n group: Group,\n opts: Required<Pick<RenderFindingsOptions, 'now'>>,\n): string {\n const errorCount = group.findings.filter(\n (f) => f.severity === 'error',\n ).length;\n const warnCount = group.findings.filter((f) => f.severity === 'warn').length;\n const infoCount = group.findings.filter((f) => f.severity === 'info').length;\n\n const worst = group.findings[0]?.severity ?? 'info';\n const color = severityColor(ui, worst);\n const glyph = severityGlyph(ui, worst);\n\n const parts: string[] = [];\n if (errorCount > 0)\n parts.push(`${errorCount} error${errorCount === 1 ? '' : 's'}`);\n if (warnCount > 0)\n parts.push(`${warnCount} warning${warnCount === 1 ? '' : 's'}`);\n if (infoCount > 0) parts.push(`${infoCount} info`);\n\n // The representative for the group's origin badge is the first (i.e.\n // worst-severity, then earliest) finding that carries one — a check\n // almost always shares one origin, and this avoids a badge per line.\n const withOrigin = group.findings.find((f) => f.origin !== undefined);\n const badge =\n withOrigin?.origin === undefined\n ? ''\n : ` ${ui.badge(\n withOrigin.createdAt\n ? `${withOrigin.origin} · ${relativeTime(withOrigin.createdAt, opts.now)}`\n : withOrigin.origin,\n originBadgeKind(withOrigin.origin),\n )}`;\n\n return `${color(`${glyph} ${group.check}`)} · ${parts.join(', ')}${badge}`;\n}\n\nfunction buildGroupBody(\n ui: Ui,\n group: Group,\n opts: Required<Pick<RenderFindingsOptions, 'maxPerGroup' | 'cwd'>>,\n): string[] {\n const uniqueHints = [...new Set(group.findings.map((f) => f.hint))];\n const [firstHint] = uniqueHints;\n const dedupedHint =\n uniqueHints.length === 1 && firstHint !== undefined ? firstHint : null;\n\n const visible = group.findings.slice(0, opts.maxPerGroup);\n const overflow = group.findings.length - visible.length;\n\n const lines: string[] = [];\n let codeframeRendered = false;\n\n for (const finding of visible) {\n const location =\n finding.file !== undefined\n ? ui.accent(\n finding.line !== undefined\n ? `${finding.file}:${finding.line}`\n : finding.file,\n )\n : null;\n const message = renderMessage(ui, finding);\n\n lines.push(` ${ui.dim('│')}${location ? ` ${location}` : ''} ${message}`);\n\n if (finding.detail !== undefined) {\n lines.push(\n ...renderDetailLines(ui, finding.detail).map((line) => ` ${line}`),\n );\n }\n\n if (dedupedHint === null) {\n lines.push(` ${ui.hint(finding.hint)}`);\n }\n\n if (!codeframeRendered) {\n const frame = tryCodeframe(ui, finding, opts.cwd);\n if (frame !== null) {\n codeframeRendered = true;\n lines.push(\n frame\n .split('\\n')\n .map((line) => ` ${line}`)\n .join('\\n'),\n );\n }\n }\n }\n\n if (overflow > 0) {\n lines.push(\n ` ${ui.dim(`${ellipsis(ui)} and ${overflow} more in this group`)}`,\n );\n }\n\n if (dedupedHint !== null) {\n lines.push(` ${ui.hint(dedupedHint)}`);\n }\n\n return lines;\n}\n\n/**\n * Pure formatter — no I/O beyond an optional codeframe file read, no\n * printing. Kept separate from `renderFindings` so tests can assert exact\n * strings against a `Ui` built with a known color/glyph decision, without\n * constructing a full `CliContext`.\n */\nexport function formatFindings(\n ui: Ui,\n findings: readonly RenderableFinding[],\n options: RenderFindingsOptions = {},\n): string {\n if (findings.length === 0) return '';\n\n const maxPerGroup = options.maxPerGroup ?? DEFAULT_MAX_PER_GROUP;\n const cwd = options.cwd ?? process.cwd();\n const now = options.now ?? new Date();\n\n const groupsByCheck = new Map<string, Group>();\n findings.forEach((finding, index) => {\n const existing = groupsByCheck.get(finding.check);\n if (existing) {\n existing.findings.push(finding);\n return;\n }\n groupsByCheck.set(finding.check, {\n check: finding.check,\n findings: [finding],\n order: index,\n });\n });\n\n const groups = [...groupsByCheck.values()];\n for (const group of groups) {\n group.findings.sort(\n (a, b) => SEVERITY_RANK[a.severity] - SEVERITY_RANK[b.severity],\n );\n }\n groups.sort((a, b) => {\n const worstA = SEVERITY_RANK[a.findings[0]?.severity ?? 'info'];\n const worstB = SEVERITY_RANK[b.findings[0]?.severity ?? 'info'];\n return worstA - worstB || a.order - b.order;\n });\n\n const blocks = groups.map((group) => {\n const header = buildGroupHeader(ui, group, { now });\n const body = buildGroupBody(ui, group, { maxPerGroup, cwd });\n return [header, ...body].join('\\n');\n });\n\n const totalErrors = findings.filter((f) => f.severity === 'error').length;\n const totalWarnings = findings.filter((f) => f.severity === 'warn').length;\n const totalInfo = findings.filter((f) => f.severity === 'info').length;\n\n const summaryParts: string[] = [];\n if (totalErrors > 0)\n summaryParts.push(`${totalErrors} error${totalErrors === 1 ? '' : 's'}`);\n if (totalWarnings > 0)\n summaryParts.push(\n `${totalWarnings} warning${totalWarnings === 1 ? '' : 's'}`,\n );\n if (totalInfo > 0 && totalErrors === 0 && totalWarnings === 0) {\n summaryParts.push(`${totalInfo} info`);\n }\n\n const summaryColor =\n totalErrors > 0 ? ui.err : totalWarnings > 0 ? ui.warn : ui.dim;\n const summaryGlyph =\n totalErrors > 0\n ? ui.glyphs.err\n : totalWarnings > 0\n ? ui.glyphs.warn\n : ui.glyphs.info;\n const checksCount = groups.length;\n\n const summary = summaryColor(\n `${summaryGlyph} ${summaryParts.join(', ')} across ${checksCount} check${\n checksCount === 1 ? '' : 's'\n }`,\n );\n\n return [...blocks, summary].join('\\n\\n');\n}\n\n/** Render the shared findings block to `ctx`'s human-mode output (stderr). A no-op for an empty findings array. */\nexport function renderFindings(\n ctx: CliContext,\n findings: readonly RenderableFinding[],\n options: RenderFindingsOptions = {},\n): void {\n const block = formatFindings(ctx.ui, findings, options);\n if (block !== '') ctx.log(block);\n}\n"]}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export declare const FA_FREE_VERSION = "7.3.1";
|
|
2
|
-
/** Every icon name Font Awesome Free ships — NOT
|
|
2
|
+
/** Every icon name Font Awesome Free ships — NOT Ekanos's set (Pro, a superset). */
|
|
3
3
|
export declare const FA_FREE_ICON_NAMES: ReadonlySet<string>;
|
|
4
4
|
/**
|
|
5
5
|
* Hand-curated Pro-only name → nearest Free alternative, sourced from
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
// Regenerated by this package's generate-fa-free-names script; drift against
|
|
15
15
|
// the host's icon set is pinned by fa-free-names-drift.test.ts.
|
|
16
16
|
export const FA_FREE_VERSION = '7.3.1';
|
|
17
|
-
/** Every icon name Font Awesome Free ships — NOT
|
|
17
|
+
/** Every icon name Font Awesome Free ships — NOT Ekanos's set (Pro, a superset). */
|
|
18
18
|
export const FA_FREE_ICON_NAMES = new Set([
|
|
19
19
|
'11ty',
|
|
20
20
|
'42-group',
|