cascivo 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 @@
1
+ {"version":3,"file":"audit-AHr4MDMK.mjs","names":[],"sources":["../src/utils/contract-pure.ts","../src/audit-ai/css-literals.ts","../src/audit-ai/jsx-props.ts","../src/audit-ai/raw-strings.ts","../src/audit-ai/required-props.ts","../src/utils/contract.ts","../src/commands/audit.ts"],"sourcesContent":["export interface PropInfo {\n name: string\n type: string\n required: boolean\n}\n\nexport interface ComponentInfo {\n props: PropInfo[]\n /** True if any prop has required: true */\n hasRequiredProps: boolean\n /** Props that have required: true */\n requiredProps: string[]\n /** True if the component declares user-facing chrome text (intent.content) */\n hasContent: boolean\n}\n\nexport interface Contract {\n /** Map from normalized color/size value → token names */\n tokensByValue: Map<string, string[]>\n /** Map from component name (PascalCase) → component info */\n components: Map<string, ComponentInfo>\n}\n\ninterface TokenEntry {\n name: string\n resolvedDefault: string | null\n}\n\ninterface CatalogFile {\n tokens: TokenEntry[]\n}\n\ninterface RegistryPropMeta {\n name: string\n type?: string\n required?: boolean\n}\n\ninterface RegistryComponentMeta {\n name: string\n props?: RegistryPropMeta[]\n}\n\ninterface RegistryEntry {\n meta?: RegistryComponentMeta\n}\n\ninterface RegistryFile {\n components: RegistryEntry[]\n}\n\ninterface ContextComponentEntry {\n name: string\n intent?: { content?: unknown }\n}\n\ninterface ContextFile {\n components: ContextComponentEntry[]\n}\n\nexport interface BuildContractInput {\n catalog: CatalogFile\n registry: RegistryFile\n context: ContextFile\n}\n\n/** Normalize a color/size value for catalog comparison: lowercase, strip spaces. */\nexport function normalizeValue(value: string): string {\n return value.toLowerCase().replace(/\\s+/g, '')\n}\n\n/** Pure builder — assemble a Contract from already-parsed JSON. Testable without fs. */\nexport function buildContract(input: BuildContractInput): Contract {\n const tokensByValue = new Map<string, string[]>()\n for (const token of input.catalog.tokens) {\n if (token.resolvedDefault == null) continue\n const key = normalizeValue(token.resolvedDefault)\n const list = tokensByValue.get(key)\n if (list) list.push(token.name)\n else tokensByValue.set(key, [token.name])\n }\n\n const contentNames = new Set<string>()\n for (const c of input.context.components) {\n if (c.intent?.content) contentNames.add(c.name)\n }\n\n const components = new Map<string, ComponentInfo>()\n for (const entry of input.registry.components) {\n const meta = entry.meta\n if (!meta?.name) continue\n const props: PropInfo[] = (meta.props ?? []).map((p) => ({\n name: p.name,\n type: p.type ?? 'unknown',\n required: p.required === true,\n }))\n const requiredProps = props.filter((p) => p.required).map((p) => p.name)\n components.set(meta.name, {\n props,\n requiredProps,\n hasRequiredProps: requiredProps.length > 0,\n hasContent: contentNames.has(meta.name),\n })\n }\n\n return { tokensByValue, components }\n}\n","import type { Contract } from '../utils/contract-pure.js'\nimport { normalizeValue } from '../utils/contract-pure.js'\n\nexport interface LiteralFinding {\n file: string\n line: number\n property: string\n value: string\n level: 'error' | 'info'\n rule: 'hardcoded-value'\n /** only when exactly one catalog match */\n suggestedToken?: string\n /** when multiple catalog matches → info */\n allMatches?: string[]\n}\n\n/** Visual CSS properties whose literal values should be tokens. */\nconst VISUAL_PROPS = new Set([\n 'color',\n 'background',\n 'background-color',\n 'border-color',\n 'box-shadow',\n 'border-radius',\n 'font-size',\n 'gap',\n 'padding',\n 'margin',\n 'width',\n 'height',\n])\n\n/** Inline-style camelCase → kebab-case for the props we care about. */\nconst INLINE_PROP_MAP: Record<string, string> = {\n color: 'color',\n background: 'background',\n backgroundColor: 'background-color',\n borderColor: 'border-color',\n boxShadow: 'box-shadow',\n borderRadius: 'border-radius',\n fontSize: 'font-size',\n gap: 'gap',\n padding: 'padding',\n margin: 'margin',\n width: 'width',\n height: 'height',\n}\n\n/** A literal value worth checking: hex, oklch/rgb/hsl(a), or px/rem number. */\nfunction isLiteralValue(value: string): boolean {\n const v = value.trim()\n if (v.includes('var(')) return false\n if (/^#[0-9a-fA-F]{3,8}$/.test(v)) return true\n if (/^(oklch|oklab|rgb|rgba|hsl|hsla)\\(/i.test(v)) return true\n if (/^-?\\d*\\.?\\d+(px|rem)$/.test(v)) return true\n return false\n}\n\nfunction classify(\n value: string,\n contract: Contract,\n): Pick<LiteralFinding, 'level' | 'suggestedToken' | 'allMatches'> | null {\n const matches = contract.tokensByValue.get(normalizeValue(value))\n if (!matches || matches.length === 0) return null\n const first = matches[0]\n if (matches.length === 1 && first) return { level: 'error', suggestedToken: first }\n return { level: 'info', allMatches: matches }\n}\n\n/**\n * Detect literal color/size values in CSS declarations and TSX inline styles\n * that exactly match a known cascade token. Heuristic, line-based — no full\n * CSS/JS parse. Values with no catalog match are NOT flagged (arbitrary brand\n * values are allowed).\n */\nexport function findCssLiteralViolations(\n source: string,\n filename: string,\n contract: Contract,\n): LiteralFinding[] {\n const findings: LiteralFinding[] = []\n const lines = source.split('\\n')\n\n // CSS declaration: `property: value;` (also matches the kebab props inside style=\"...\")\n const cssDecl = /(^|[;{\\s])([a-z-]+)\\s*:\\s*([^;}{]+?)\\s*(?=[;}]|$)/gi\n // Inline JSX style object: `color: '#fff'` or `color: \"#fff\"`\n const inlineDecl = /([A-Za-z][A-Za-z]*)\\s*:\\s*(['\"])([^'\"]+)\\2/g\n\n for (let i = 0; i < lines.length; i++) {\n const line = lines[i]\n if (line === undefined) continue\n const seen = new Set<string>()\n\n for (const m of line.matchAll(cssDecl)) {\n if (m[2] === undefined || m[3] === undefined) continue\n const prop = m[2].toLowerCase()\n const rawValue = m[3].trim()\n if (!VISUAL_PROPS.has(prop)) continue\n if (!isLiteralValue(rawValue)) continue\n const cls = classify(rawValue, contract)\n if (!cls) continue\n const key = `${prop}|${rawValue}`\n seen.add(key)\n findings.push({\n file: filename,\n line: i + 1,\n property: prop,\n value: rawValue,\n rule: 'hardcoded-value',\n ...cls,\n })\n }\n\n for (const m of line.matchAll(inlineDecl)) {\n if (m[1] === undefined || m[3] === undefined) continue\n const prop = INLINE_PROP_MAP[m[1]]\n if (!prop) continue\n const rawValue = m[3].trim()\n if (!isLiteralValue(rawValue)) continue\n const key = `${prop}|${rawValue}`\n if (seen.has(key)) continue\n const cls = classify(rawValue, contract)\n if (!cls) continue\n findings.push({\n file: filename,\n line: i + 1,\n property: prop,\n value: rawValue,\n rule: 'hardcoded-value',\n ...cls,\n })\n }\n }\n\n return findings\n}\n","import type { Contract } from '../utils/contract-pure.js'\n\nexport interface PropFinding {\n file: string\n line: number\n component: string\n prop: string\n level: 'error' | 'info'\n rule: 'unknown-prop' | 'spread-suppressed'\n message: string\n}\n\n/** Props always allowed on any cascade component (DOM passthrough / React intrinsics). */\nconst PASSTHROUGH = new Set(['className', 'style', 'id', 'ref', 'key', 'children'])\n\nfunction isPassthrough(prop: string): boolean {\n if (PASSTHROUGH.has(prop)) return true\n if (prop.startsWith('data-')) return true\n if (prop.startsWith('aria-')) return true\n if (/^on[A-Z]/.test(prop)) return true\n return false\n}\n\n/** Names imported from @cascivo/react in this source. */\nexport function importedCascadeComponents(source: string): Set<string> {\n const names = new Set<string>()\n const importRe = /import\\s*\\{([^}]*)\\}\\s*from\\s*['\"]@cascivo\\/react['\"]/g\n for (const m of source.matchAll(importRe)) {\n const group = m[1]\n if (group === undefined) continue\n for (const raw of group.split(',')) {\n const name = raw\n .trim()\n .split(/\\s+as\\s+/)[0]\n ?.trim()\n if (name) names.add(name)\n }\n }\n return names\n}\n\n/** Find each opening tag for `comp`, returning its attribute substring + start index. */\nexport interface OpeningTag {\n attrs: string\n index: number\n hasSpread: boolean\n}\n\nexport function findOpeningTags(source: string, comp: string): OpeningTag[] {\n const tags: OpeningTag[] = []\n const re = new RegExp(`<${comp}(?=[\\\\s/>])`, 'g')\n for (const m of source.matchAll(re)) {\n const start = m.index ?? 0\n // Walk forward to the matching '>' that closes the opening tag, respecting\n // nested braces (JSX expressions) and quoted strings.\n let i = start + m[0].length\n let depth = 0\n let quote = ''\n let attrs = ''\n let closed = false\n for (; i < source.length; i++) {\n const ch = source[i]\n if (quote) {\n if (ch === quote) quote = ''\n attrs += ch\n continue\n }\n if (ch === '\"' || ch === \"'\" || ch === '`') {\n quote = ch\n attrs += ch\n continue\n }\n if (ch === '{') depth++\n else if (ch === '}') depth--\n else if (ch === '>' && depth === 0) {\n closed = true\n break\n }\n attrs += ch\n }\n if (!closed) continue\n const cleanAttrs = attrs.replace(/\\/$/, '')\n tags.push({ attrs: cleanAttrs, index: start, hasSpread: /\\{\\s*\\.\\.\\./.test(cleanAttrs) })\n }\n return tags\n}\n\n/** Extract top-level attribute names from an opening-tag attribute string. */\nexport function extractAttrNames(attrs: string): string[] {\n const names: string[] = []\n let depth = 0\n let quote = ''\n let token = ''\n const flush = () => {\n const name = token.trim().split('=')[0]?.trim()\n if (name && /^[A-Za-z]/.test(name)) names.push(name)\n token = ''\n }\n for (let i = 0; i < attrs.length; i++) {\n const ch = attrs[i]\n if (ch === undefined) continue\n if (quote) {\n if (ch === quote) quote = ''\n continue\n }\n if (ch === '\"' || ch === \"'\" || ch === '`') {\n quote = ch\n continue\n }\n if (ch === '{') {\n depth++\n continue\n }\n if (ch === '}') {\n depth--\n continue\n }\n if (depth > 0) continue\n if (ch === '=') {\n flush()\n // skip the value: handled by quote/brace state on next chars; reset token\n token = ''\n continue\n }\n if (/\\s/.test(ch)) {\n if (token.trim()) flush()\n continue\n }\n token += ch\n }\n if (token.trim()) flush()\n return names\n}\n\nexport function lineOf(source: string, index: number): number {\n let line = 1\n for (let i = 0; i < index && i < source.length; i++) {\n if (source[i] === '\\n') line++\n }\n return line\n}\n\n/**\n * Check JSX usages of imported cascade components for unknown props.\n * Heuristic — regex/brace-aware scan, not a full AST. Elements using a spread\n * (`{...rest}`) are reported as info and skipped (props can't be statically known).\n */\nexport function findJsxPropViolations(\n source: string,\n filename: string,\n contract: Contract,\n): PropFinding[] {\n const findings: PropFinding[] = []\n const tracked = importedCascadeComponents(source)\n\n for (const comp of tracked) {\n const info = contract.components.get(comp)\n if (!info) continue\n const known = new Set(info.props.map((p) => p.name))\n\n for (const tag of findOpeningTags(source, comp)) {\n const line = lineOf(source, tag.index)\n if (tag.hasSpread) {\n findings.push({\n file: filename,\n line,\n component: comp,\n prop: '...',\n level: 'info',\n rule: 'spread-suppressed',\n message: `<${comp}> uses a spread — prop checks skipped`,\n })\n continue\n }\n for (const name of extractAttrNames(tag.attrs)) {\n if (isPassthrough(name)) continue\n if (known.has(name)) continue\n findings.push({\n file: filename,\n line,\n component: comp,\n prop: name,\n level: 'error',\n rule: 'unknown-prop',\n message: `<${comp}> has unknown prop \"${name}\"`,\n })\n }\n }\n }\n\n return findings\n}\n","import type { Contract } from '../utils/contract-pure.js'\nimport { findOpeningTags, importedCascadeComponents, lineOf } from './jsx-props.js'\n\nexport interface RawStringFinding {\n file: string\n line: number\n component: string\n text: string\n level: 'warn'\n rule: 'raw-string'\n message: string\n}\n\n/** Looks like English prose worth flagging: ≥2 whitespace-separated words, letters/spaces only. */\nfunction looksLikeProse(text: string): boolean {\n const trimmed = text.trim()\n if (!/^[A-Za-z][A-Za-z\\s]*$/.test(trimmed)) return false\n return trimmed.split(/\\s+/).length >= 2\n}\n\n/**\n * Conservative raw-string check: for cascade components that own user-facing\n * chrome text (intent.content), warn when a literal multi-word English child\n * appears, suggesting the labels prop / i18n. Never errors. Only inspects the\n * immediate text directly after the opening tag (no nested element traversal).\n */\nexport function findRawStringViolations(\n source: string,\n filename: string,\n contract: Contract,\n): RawStringFinding[] {\n const findings: RawStringFinding[] = []\n const tracked = importedCascadeComponents(source)\n\n for (const comp of tracked) {\n const info = contract.components.get(comp)\n if (!info?.hasContent) continue\n\n for (const tag of findOpeningTags(source, comp)) {\n // Locate the end of this opening tag in the source.\n const openEnd = source.indexOf('>', tag.index)\n if (openEnd === -1) continue\n if (source[openEnd - 1] === '/') continue // self-closing, no children\n\n // Grab text up to the next tag/expression boundary.\n const after = source.slice(openEnd + 1)\n const stop = after.search(/[<{]/)\n const child = (stop === -1 ? after : after.slice(0, stop)).trim()\n if (!child || !looksLikeProse(child)) continue\n\n findings.push({\n file: filename,\n line: lineOf(source, openEnd),\n component: comp,\n text: child,\n level: 'warn',\n rule: 'raw-string',\n message: `<${comp}> raw text \"${child}\" — use the labels prop / i18n`,\n })\n }\n }\n\n return findings\n}\n","import type { Contract } from '../utils/contract-pure.js'\nimport {\n extractAttrNames,\n findOpeningTags,\n importedCascadeComponents,\n lineOf,\n} from './jsx-props.js'\n\nexport interface RequiredPropFinding {\n file: string\n line: number\n component: string\n prop: string\n level: 'error'\n rule: 'missing-prop'\n message: string\n}\n\n/**\n * Flag cascade elements that omit a prop the component marks required.\n * Elements using a spread are skipped (the prop may arrive via the spread).\n */\nexport function findRequiredPropViolations(\n source: string,\n filename: string,\n contract: Contract,\n): RequiredPropFinding[] {\n const findings: RequiredPropFinding[] = []\n const tracked = importedCascadeComponents(source)\n\n for (const comp of tracked) {\n const info = contract.components.get(comp)\n if (!info?.hasRequiredProps) continue\n\n for (const tag of findOpeningTags(source, comp)) {\n if (tag.hasSpread) continue\n const present = new Set(extractAttrNames(tag.attrs))\n const line = lineOf(source, tag.index)\n for (const req of info.requiredProps) {\n if (present.has(req)) continue\n findings.push({\n file: filename,\n line,\n component: comp,\n prop: req,\n level: 'error',\n rule: 'missing-prop',\n message: `<${comp}> requires \"${req}\"`,\n })\n }\n }\n }\n\n return findings\n}\n","import { existsSync, readFileSync } from 'node:fs'\nimport { dirname, join } from 'node:path'\nimport { fileURLToPath } from 'node:url'\n\nexport type { BuildContractInput, ComponentInfo, Contract, PropInfo } from './contract-pure.js'\nexport { buildContract, normalizeValue } from './contract-pure.js'\nimport type { Contract } from './contract-pure.js'\nimport { buildContract } from './contract-pure.js'\n\nconst HERE = dirname(fileURLToPath(import.meta.url))\n\n/** Walk up from a start directory looking for the apps/docs/public dir. */\nfunction findDocsPublic(startDir: string): string | null {\n let dir = startDir\n for (let i = 0; i < 10; i++) {\n const candidate = join(dir, 'apps', 'docs', 'public')\n if (existsSync(candidate)) return candidate\n dir = join(dir, '..')\n }\n return null\n}\n\n/** Walk up from a start directory looking for registry.json at the repo root. */\nfunction findRegistry(startDir: string): string | null {\n let dir = startDir\n for (let i = 0; i < 10; i++) {\n const candidate = join(dir, 'registry.json')\n if (existsSync(candidate)) return candidate\n dir = join(dir, '..')\n }\n return null\n}\n\n/**\n * Load the published cascade contract from local generated artifacts:\n * - token catalog (apps/docs/public/tokens.catalog.json) → value→token map\n * - registry.json (repo root) → component prop index\n * - context bundle (apps/docs/public/context.json) → which components have chrome text\n */\nexport async function loadContract(options?: {\n catalogPath?: string\n contextPath?: string\n registryPath?: string\n}): Promise<Contract> {\n const docsPublic = findDocsPublic(HERE) ?? findDocsPublic(process.cwd())\n const catalogPath =\n options?.catalogPath ?? (docsPublic ? join(docsPublic, 'tokens.catalog.json') : null)\n const contextPath = options?.contextPath ?? (docsPublic ? join(docsPublic, 'context.json') : null)\n const registryPath = options?.registryPath ?? findRegistry(HERE) ?? findRegistry(process.cwd())\n\n if (!catalogPath || !existsSync(catalogPath)) {\n throw new Error('token catalog not found (apps/docs/public/tokens.catalog.json)')\n }\n if (!registryPath || !existsSync(registryPath)) {\n throw new Error('registry.json not found')\n }\n if (!contextPath || !existsSync(contextPath)) {\n throw new Error('context bundle not found (apps/docs/public/context.json)')\n }\n\n const catalog = JSON.parse(readFileSync(catalogPath, 'utf8')) as Parameters<\n typeof buildContract\n >[0]['catalog']\n const registry = JSON.parse(readFileSync(registryPath, 'utf8')) as Parameters<\n typeof buildContract\n >[0]['registry']\n const context = JSON.parse(readFileSync(contextPath, 'utf8')) as Parameters<\n typeof buildContract\n >[0]['context']\n\n return buildContract({ catalog, registry, context })\n}\n","import { existsSync, readdirSync, readFileSync, statSync, writeFileSync } from 'node:fs'\nimport { extname, join } from 'node:path'\nimport type { LiteralFinding } from '../audit-ai/css-literals.js'\nimport { findCssLiteralViolations } from '../audit-ai/css-literals.js'\nimport type { PropFinding } from '../audit-ai/jsx-props.js'\nimport { findJsxPropViolations } from '../audit-ai/jsx-props.js'\nimport type { RawStringFinding } from '../audit-ai/raw-strings.js'\nimport { findRawStringViolations } from '../audit-ai/raw-strings.js'\nimport type { RequiredPropFinding } from '../audit-ai/required-props.js'\nimport { findRequiredPropViolations } from '../audit-ai/required-props.js'\nimport type { CascadeConfig } from '../utils/config.js'\nimport type { Contract } from '../utils/contract.js'\nimport { loadContract } from '../utils/contract.js'\n\nexport type Finding = LiteralFinding | PropFinding | RequiredPropFinding | RawStringFinding\n\nconst SKIP_DIRS = new Set(['node_modules', 'dist', '.git', 'build', '.next', 'coverage'])\n\nfunction collectFiles(paths: string[]): string[] {\n const out: string[] = []\n const walk = (p: string) => {\n if (!existsSync(p)) return\n const s = statSync(p)\n if (s.isDirectory()) {\n const base = p.split('/').pop() ?? ''\n if (SKIP_DIRS.has(base)) return\n for (const entry of readdirSync(p)) walk(join(p, entry))\n return\n }\n const ext = extname(p)\n if (ext === '.css' || ext === '.tsx' || ext === '.ts') out.push(p)\n }\n for (const p of paths) walk(p)\n return out\n}\n\nfunction findingsFor(file: string, source: string, contract: Contract): Finding[] {\n const ext = extname(file)\n const findings: Finding[] = []\n if (ext === '.css') {\n findings.push(...findCssLiteralViolations(source, file, contract))\n } else if (ext === '.tsx' || ext === '.ts') {\n findings.push(...findCssLiteralViolations(source, file, contract))\n findings.push(...findJsxPropViolations(source, file, contract))\n findings.push(...findRequiredPropViolations(source, file, contract))\n findings.push(...findRawStringViolations(source, file, contract))\n }\n return findings\n}\n\nfunction detail(f: Finding): string {\n switch (f.rule) {\n case 'hardcoded-value':\n if (f.suggestedToken) return `${f.value} → var(${f.suggestedToken})`\n return `${f.value} → ${f.allMatches?.join(' | ') ?? '(ambiguous)'}`\n case 'unknown-prop':\n return `<${f.component} ${f.prop}>`\n case 'spread-suppressed':\n return `<${f.component} {...}> (props not checked)`\n case 'missing-prop':\n return `<${f.component}> requires \"${f.prop}\"`\n case 'raw-string':\n return `\"${f.text}\" → use labels prop / i18n`\n }\n}\n\nfunction levelLabel(level: Finding['level']): string {\n return level === 'warn' ? 'warn' : level\n}\n\nfunction renderFindings(findings: Finding[]): void {\n if (findings.length === 0) {\n console.log('cascade audit --ai: no findings.')\n return\n }\n const rows = findings.map((f) => ({\n loc: `${f.file}:${f.line}`,\n level: levelLabel(f.level),\n rule: f.rule,\n detail: detail(f),\n }))\n const locW = Math.max(...rows.map((r) => r.loc.length), 8)\n const lvlW = Math.max(...rows.map((r) => r.level.length), 5)\n const ruleW = Math.max(...rows.map((r) => r.rule.length), 4)\n for (const r of rows) {\n console.log(\n `${r.loc.padEnd(locW)} ${r.level.padEnd(lvlW)} ${r.rule.padEnd(ruleW)} ${r.detail}`,\n )\n }\n console.log('---')\n const errors = findings.filter((f) => f.level === 'error').length\n const warnings = findings.filter((f) => f.level === 'warn').length\n const infos = findings.filter((f) => f.level === 'info').length\n const parts = [\n `${errors} error${errors === 1 ? '' : 's'}`,\n `${warnings} warning${warnings === 1 ? '' : 's'}`,\n ]\n if (infos) parts.push(`${infos} info`)\n console.log(parts.join(', '))\n}\n\nfunction escapeRe(s: string): string {\n return s.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&')\n}\n\n/**\n * Pure literal→token rewrite. Only rewrites simple `property: #hex;` style\n * declarations where exactly one token matches. Returns the new source and how\n * many findings were resolved (verified by re-running the checker).\n */\nexport function fixCssLiterals(\n source: string,\n file: string,\n contract: Contract,\n): { source: string; fixed: number } {\n const fixable = findCssLiteralViolations(source, file, contract).filter(\n (f) => f.level === 'error' && f.suggestedToken && /^#[0-9a-fA-F]{3,8}$/.test(f.value),\n )\n let next = source\n for (const f of fixable) {\n // Only rewrite a full-value declaration: `prop: #hex;` (or end of block).\n const re = new RegExp(`(${escapeRe(f.property)}\\\\s*:\\\\s*)${escapeRe(f.value)}(\\\\s*[;}])`, 'gi')\n next = next.replace(re, `$1var(${f.suggestedToken})$2`)\n }\n if (next === source) return { source, fixed: 0 }\n const remaining = findCssLiteralViolations(next, file, contract).filter(\n (f) => f.level === 'error' && f.suggestedToken,\n ).length\n return { source: next, fixed: fixable.length - remaining }\n}\n\n/** Apply {@link fixCssLiterals} to each .css file on disk. */\nfunction applyFixes(files: string[], contract: Contract): number {\n let fixed = 0\n for (const file of files) {\n if (extname(file) !== '.css') continue\n const { source, fixed: n } = fixCssLiterals(readFileSync(file, 'utf8'), file, contract)\n if (n > 0) {\n writeFileSync(file, source)\n fixed += n\n }\n }\n return fixed\n}\n\nexport async function audit(args: string[], _config: CascadeConfig): Promise<void> {\n if (!args.includes('--ai')) {\n console.log('cascade audit: use --ai to audit AI-generated code against the cascade contract')\n return\n }\n\n const jsonOutput = args.includes('--json')\n const fixMode = args.includes('--fix')\n const levelIdx = args.indexOf('--level')\n const minLevel = levelIdx >= 0 ? (args[levelIdx + 1] ?? 'error') : 'error'\n\n const paths = args.filter((a, i) => {\n if (a.startsWith('--')) return false\n if (levelIdx >= 0 && i === levelIdx + 1) return false\n return true\n })\n\n let contract: Contract\n try {\n contract = await loadContract()\n } catch (e) {\n console.error(`Contract unavailable: ${e instanceof Error ? e.message : String(e)}`)\n process.exitCode = 2\n return\n }\n\n const files = collectFiles(paths.length ? paths : [process.cwd()])\n\n if (fixMode) {\n const n = applyFixes(files, contract)\n console.log(`cascade audit --ai --fix: rewrote ${n} literal${n === 1 ? '' : 's'} to tokens.`)\n }\n\n const allFindings: Finding[] = []\n for (const file of files) {\n allFindings.push(...findingsFor(file, readFileSync(file, 'utf8'), contract))\n }\n\n if (jsonOutput) {\n console.log(JSON.stringify(allFindings, null, 2))\n } else {\n renderFindings(allFindings)\n }\n\n const hasErrors = allFindings.some((f) => f.level === 'error')\n if (minLevel === 'error' && hasErrors) process.exitCode = 1\n if (minLevel === 'warn' && allFindings.some((f) => f.level !== 'info')) process.exitCode = 1\n}\n"],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ //#region src/commands/drift.ts
2
+ async function runDoctorDrift(_args) {
3
+ console.log("cascade doctor --drift: not yet implemented");
4
+ }
5
+ //#endregion
6
+ export { runDoctorDrift };
7
+
8
+ //# sourceMappingURL=drift-D7JFzpP_.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"drift-D7JFzpP_.mjs","names":[],"sources":["../src/commands/drift.ts"],"sourcesContent":["export async function runDoctorDrift(_args: string[]): Promise<void> {\n console.log('cascade doctor --drift: not yet implemented')\n}\n"],"mappings":";AAAA,eAAsB,eAAe,OAAgC;CACnE,QAAQ,IAAI,6CAA6C;AAC3D"}
@@ -0,0 +1,26 @@
1
+ //#region src/utils/config.d.ts
2
+ type ThemeName = 'light' | 'dark' | 'warm';
3
+ type RegistryNamespaceConfig = string | {
4
+ url: string;
5
+ headers?: Record<string, string>;
6
+ params?: Record<string, string>;
7
+ };
8
+ interface CascadeConfig {
9
+ /** URL of the registry.json index. */
10
+ registry: string;
11
+ /** Directory (relative to project root) where components are written. */
12
+ outputDir: string;
13
+ /** Default theme imported by `cascade init`. */
14
+ theme: ThemeName;
15
+ /** Namespace → registry URL template (with {name} placeholder) or auth config. */
16
+ registries?: Record<string, RegistryNamespaceConfig>;
17
+ /** Whether to copy test files (*.contract.test.tsx) when adding components. */
18
+ tests?: boolean;
19
+ }
20
+ //#endregion
21
+ //#region src/index.d.ts
22
+ declare const VERSION = "0.0.0";
23
+ declare function run(args: string[]): Promise<void>;
24
+ //#endregion
25
+ export { type CascadeConfig, type ThemeName, VERSION, run };
26
+ //# sourceMappingURL=index.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.mts","names":[],"sources":["../src/utils/config.ts","../src/index.ts"],"mappings":";KAIY,SAAA;AAAA,KAEA,uBAAA;EAEN,GAAA;EAAa,OAAA,GAAU,MAAA;EAAwB,MAAA,GAAS,MAAM;AAAA;AAAA,UAEnD,aAAA;EAJkB;EAMjC,QAAA;EAJkE;EAMlE,SAAA;EANiB;EAQjB,KAAA,EAAO,SAAA;EAR4C;EAUnD,UAAA,GAAa,MAAA,SAAe,uBAAA;EAVsC;EAYlE,KAAA;AAAA;;;cCNW,OAAA;AAAA,iBAuBS,GAAA,CAAI,IAAA,aAAiB,OAAO"}