import * as fs from 'node:fs'; import * as path from 'node:path'; import { MediaReferenceSchema } from '../../../src/types/media-reference.js'; import { generateComponentReferences, generateFeatureReferences, generateMediaElementReferences, generatePresetReferences, } from './pipeline.js'; import { ComponentReferenceSchema, FeatureReferenceSchema, PresetReferenceSchema } from './types.js'; import { generateUtilReferences } from './util-handler.js'; // Magenta prefix - visible on both light and dark terminals const PREFIX = '\x1b[35m[api-docs-builder]\x1b[0m'; const log = { info: (...args: unknown[]) => console.log(PREFIX, ...args), warn: (...args: unknown[]) => console.warn(PREFIX, '\x1b[33mwarn:\x1b[0m', ...args), error: (...args: unknown[]) => console.error(PREFIX, '\x1b[31merror:\x1b[0m', ...args), success: (...args: unknown[]) => console.log(PREFIX, ...args), }; // Paths relative to the monorepo root const MONOREPO_ROOT = path.resolve(import.meta.dirname, '../../../../'); const COMPONENT_OUTPUT_PATH = path.join(MONOREPO_ROOT, 'site/src/content/generated-component-reference'); const UTIL_OUTPUT_PATH = path.join(MONOREPO_ROOT, 'site/src/content/generated-util-reference'); const FEATURE_OUTPUT_PATH = path.join(MONOREPO_ROOT, 'site/src/content/generated-feature-reference'); const MEDIA_OUTPUT_PATH = path.join(MONOREPO_ROOT, 'site/src/content/generated-media-reference'); const PRESET_OUTPUT_PATH = path.join(MONOREPO_ROOT, 'site/src/content/generated-preset-reference'); /** * Main entry point. */ function main() { // typescript-api-extractor doesn't handle the `never` TypeScript type flag // (or a few others like ESSymbol, TemplateLiteral). It falls back to `any` // and logs a warning for each occurrence. This is a known gap in the alpha // library — not a bug in our types. Suppress the noise here. const originalWarn = console.warn; console.warn = (...args: unknown[]) => { if (typeof args[0] === 'string' && args[0].startsWith('Unable to handle a type with flag')) return; originalWarn.apply(console, args); }; // Ensure output directories exist for (const dir of [ COMPONENT_OUTPUT_PATH, UTIL_OUTPUT_PATH, FEATURE_OUTPUT_PATH, MEDIA_OUTPUT_PATH, PRESET_OUTPUT_PATH, ]) { if (!fs.existsSync(dir)) { fs.mkdirSync(dir, { recursive: true }); } } // Generate component references via pipeline const componentResults = generateComponentReferences(MONOREPO_ROOT); if (componentResults.length === 0) { log.info('No components found.'); } else { log.info(`Found ${componentResults.length} components. Processing...`); } let successCount = 0; let errorCount = 0; for (const result of componentResults) { // Validate against schema before writing const validated = ComponentReferenceSchema.safeParse(result.reference); if (!validated.success) { log.error(`Schema validation failed for ${result.name}:`); for (const issue of validated.error.issues) { log.error(` - ${issue.path.join('.')}: ${issue.message}`); } errorCount++; continue; } // Write JSON file const outputFile = path.join(COMPONENT_OUTPUT_PATH, `${result.kebab}.json`); const json = `${JSON.stringify(validated.data, null, 2)}\n`; fs.writeFileSync(outputFile, json); log.success(`✅ Generated ${path.basename(outputFile)}`); successCount++; } log.info(`Done! Generated ${successCount} component files.`); // Generate util references const utilResult = generateUtilReferences(UTIL_OUTPUT_PATH, MONOREPO_ROOT); successCount += utilResult.success; errorCount += utilResult.errors; log.info(`Done! Generated ${utilResult.success} util files.`); // Generate feature references const featureResults = generateFeatureReferences(MONOREPO_ROOT); if (featureResults.length === 0) { log.info('No features found.'); } else { log.info(`Found ${featureResults.length} features. Processing...`); } let featureSuccessCount = 0; for (const result of featureResults) { const validated = FeatureReferenceSchema.safeParse(result.reference); if (!validated.success) { log.error(`Schema validation failed for feature ${result.name}:`); for (const issue of validated.error.issues) { log.error(` - ${issue.path.join('.')}: ${issue.message}`); } errorCount++; continue; } const outputFile = path.join(FEATURE_OUTPUT_PATH, `${result.slug}.json`); const json = `${JSON.stringify(validated.data, null, 2)}\n`; fs.writeFileSync(outputFile, json); log.success(`✅ Generated ${path.basename(outputFile)}`); featureSuccessCount++; successCount++; } log.info(`Done! Generated ${featureSuccessCount} feature files.`); // Generate media element references const mediaResults = generateMediaElementReferences(MONOREPO_ROOT); if (mediaResults.length === 0) { log.info('No media elements found.'); } else { log.info(`Found ${mediaResults.length} media elements. Processing...`); } let mediaSuccessCount = 0; for (const result of mediaResults) { const validated = MediaReferenceSchema.safeParse(result.reference); if (!validated.success) { log.error(`Schema validation failed for media element ${result.name}:`); for (const issue of validated.error.issues) { log.error(` - ${issue.path.join('.')}: ${issue.message}`); } errorCount++; continue; } const outputFile = path.join(MEDIA_OUTPUT_PATH, `${validated.data.tagName}.json`); const json = `${JSON.stringify(validated.data, null, 2)}\n`; fs.writeFileSync(outputFile, json); log.success(`✅ Generated ${path.basename(outputFile)}`); mediaSuccessCount++; successCount++; } log.info(`Done! Generated ${mediaSuccessCount} media element files.`); // Generate preset references const presetResults = generatePresetReferences(MONOREPO_ROOT); if (presetResults.length === 0) { log.info('No presets found.'); } else { log.info(`Found ${presetResults.length} presets. Processing...`); } let presetSuccessCount = 0; for (const result of presetResults) { const validated = PresetReferenceSchema.safeParse(result.reference); if (!validated.success) { log.error(`Schema validation failed for preset ${result.name}:`); for (const issue of validated.error.issues) { log.error(` - ${issue.path.join('.')}: ${issue.message}`); } errorCount++; continue; } const outputFile = path.join(PRESET_OUTPUT_PATH, `${result.name}.json`); const json = `${JSON.stringify(validated.data, null, 2)}\n`; fs.writeFileSync(outputFile, json); log.success(`✅ Generated ${path.basename(outputFile)}`); presetSuccessCount++; successCount++; } log.info(`Done! Generated ${presetSuccessCount} preset files.`); console.warn = originalWarn; if (errorCount > 0) { log.error(`${errorCount} errors occurred.`); process.exit(1); } } main();