import { exec } from 'child_process' import * as fs from 'fs/promises' import linguistLanguages from 'linguist-languages' import * as path from 'path' import { promisify } from 'util' const execAsync = promisify(exec) type LanguageData = { type: string aliases?: string[] extensions?: string[] } const LANGUAGES_FILE_PATH = path.join(__dirname, '../packages/shared/config/languages.ts') /** * Extracts and filters necessary language data from the linguist-languages package. * @returns A record of language data. */ function extractAllLanguageData(): Record { console.log('🔍 Extracting language data from linguist-languages...') const languages = Object.entries(linguistLanguages).reduce( (acc, [name, langData]) => { const { type, extensions, aliases } = langData as any // Only include languages with extensions or aliases if ((extensions && extensions.length > 0) || (aliases && aliases.length > 0)) { acc[name] = { type: type || 'programming', ...(extensions && { extensions }), ...(aliases && { aliases }) } } return acc }, {} as Record ) console.log(`✅ Extracted ${Object.keys(languages).length} languages.`) return languages } /** * Generates the content for the languages.ts file. * @param languages The language data to include in the file. * @returns The generated file content as a string. */ function generateLanguagesFileContent(languages: Record): string { console.log('📝 Generating languages.ts file content...') const sortedLanguages = Object.fromEntries(Object.entries(languages).sort(([a], [b]) => a.localeCompare(b))) const languagesObjectString = JSON.stringify(sortedLanguages, null, 2) const content = `/** * Code language list. * Data source: linguist-languages * * ⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️ * THIS FILE IS AUTOMATICALLY GENERATED BY A SCRIPT. DO NOT EDIT IT MANUALLY! * Run \`yarn update:languages\` to update this file. * ⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️ * */ type LanguageData = { type: string; aliases?: string[]; extensions?: string[]; }; export const languages: Record = ${languagesObjectString}; ` console.log('✅ File content generated.') return content } /** * Formats a file using Prettier. * @param filePath The path to the file to format. */ async function formatWithPrettier(filePath: string): Promise { console.log('🎨 Formatting file with Prettier...') try { await execAsync(`yarn prettier --write ${filePath}`) console.log('✅ Prettier formatting complete.') } catch (e: any) { console.error('❌ Prettier formatting failed:', e.stdout || e.stderr) throw new Error('Prettier formatting failed.') } } /** * Checks a file with TypeScript compiler. * @param filePath The path to the file to check. */ async function checkTypeScript(filePath: string): Promise { console.log('🧐 Checking file with TypeScript compiler...') try { await execAsync(`yarn tsc --noEmit --skipLibCheck ${filePath}`) console.log('✅ TypeScript check passed.') } catch (e: any) { console.error('❌ TypeScript check failed:', e.stdout || e.stderr) throw new Error('TypeScript check failed.') } } /** * Main function to update the languages.ts file. */ async function updateLanguagesFile(): Promise { console.log('🚀 Starting to update languages.ts...') try { const extractedLanguages = extractAllLanguageData() const fileContent = generateLanguagesFileContent(extractedLanguages) await fs.writeFile(LANGUAGES_FILE_PATH, fileContent, 'utf-8') console.log(`✅ Successfully wrote to ${LANGUAGES_FILE_PATH}`) await formatWithPrettier(LANGUAGES_FILE_PATH) await checkTypeScript(LANGUAGES_FILE_PATH) console.log('🎉 Successfully updated languages.ts file!') console.log(`📊 Contains ${Object.keys(extractedLanguages).length} languages.`) } catch (error) { console.error('❌ An error occurred during the update process:', (error as Error).message) // No need to restore backup as we write only at the end of successful generation. process.exit(1) } } if (require.main === module) { updateLanguagesFile() } export { updateLanguagesFile }