Your music, beautifully tracked. All yours. (coming soon) teal.fm
teal-fm atproto

Refactor lexicon generation with improved error handling

Changed files
+92 -62
tools
lexicon-cli
src
commands
+92 -62
tools/lexicon-cli/src/commands/generate.ts
··· 1 - import { execa } from 'execa'; 2 - import { existsSync } from 'fs'; 3 - import { join } from 'path'; 4 - import pc from 'picocolors'; 5 - import { findWorkspaceRoot } from '../utils/workspace.js'; 6 7 interface GenerateOptions { 8 tsOnly?: boolean; ··· 12 13 export async function generate(options: GenerateOptions = {}) { 14 const workspaceRoot = findWorkspaceRoot(); 15 - 16 - console.log(pc.blue('🔧 Generating lexicon types...')); 17 - 18 try { 19 if (!options.rustOnly) { 20 await generateTypeScript(workspaceRoot, options.force); 21 } 22 - 23 if (!options.tsOnly) { 24 await generateRust(workspaceRoot, options.force); 25 } 26 - 27 - console.log(pc.green('✅ Lexicon generation complete!')); 28 } catch (error) { 29 - console.error(pc.red('❌ Generation failed:'), error instanceof Error ? error.message : String(error)); 30 process.exit(1); 31 } 32 } 33 34 async function generateTypeScript(workspaceRoot: string, force?: boolean) { 35 - const lexiconsPath = join(workspaceRoot, 'lexicons'); 36 - 37 if (!existsSync(lexiconsPath)) { 38 - throw new Error('Lexicons directory not found at workspace root'); 39 } 40 - 41 // Check if packages/lexicons exists for TypeScript generation 42 - const packagesLexiconsPath = join(workspaceRoot, 'packages/lexicons'); 43 if (!existsSync(packagesLexiconsPath)) { 44 - console.log(pc.yellow(' ⚠️ TypeScript lexicons package not found, skipping TypeScript generation')); 45 return; 46 } 47 - 48 - console.log(pc.cyan(' 📦 Generating TypeScript types...')); 49 - 50 try { 51 - await execa('pnpm', ['lex:gen-server'], { 52 cwd: packagesLexiconsPath, 53 - stdio: 'inherit' 54 }); 55 - console.log(pc.green(' ✓ TypeScript types generated')); 56 } catch (error) { 57 - throw new Error(`TypeScript generation failed: ${error instanceof Error ? error.message : String(error)}`); 58 } 59 } 60 61 async function generateRust(workspaceRoot: string, force?: boolean) { 62 - const typesPath = join(workspaceRoot, 'services/types'); 63 - const lexiconsPath = join(workspaceRoot, 'lexicons'); 64 - 65 if (!existsSync(typesPath)) { 66 - throw new Error('Rust types service not found'); 67 } 68 - 69 if (!existsSync(lexiconsPath)) { 70 - throw new Error('Lexicons directory not found at workspace root'); 71 } 72 - 73 - console.log(pc.cyan(' 🦀 Generating Rust types...')); 74 - 75 try { 76 // Check if esquema-cli is available 77 try { 78 - await execa('esquema-cli', ['--version'], { stdio: 'pipe' }); 79 } catch { 80 - console.log(pc.yellow(' ⚠️ esquema-cli not found. Installing...')); 81 try { 82 - await execa('cargo', [ 83 - 'install', 84 - 'esquema-cli', 85 - '--git', 86 - 'https://github.com/fatfingers23/esquema.git' 87 - ], { 88 - stdio: 'inherit' 89 - }); 90 - console.log(pc.green(' ✓ esquema-cli installed successfully')); 91 } catch (installError) { 92 - throw new Error('Failed to install esquema-cli. Please install manually: cargo install esquema-cli --git https://github.com/fatfingers23/esquema.git'); 93 } 94 } 95 - 96 - await execa('esquema-cli', [ 97 - 'generate', 98 - 'local', 99 - '--lexdir', 100 - lexiconsPath, 101 - '--outdir', 102 - join(typesPath, 'src') 103 - ], { 104 - cwd: typesPath, 105 - stdio: 'inherit' 106 - }); 107 - 108 - console.log(pc.green(' ✓ Rust types generated')); 109 } catch (error) { 110 - throw new Error(`Rust generation failed: ${error instanceof Error ? error.message : String(error)}`); 111 } 112 - }
··· 1 + import { existsSync } from "fs"; 2 + import { join } from "path"; 3 + import { execa } from "execa"; 4 + import pc from "picocolors"; 5 + 6 + import { findWorkspaceRoot } from "../utils/workspace.js"; 7 8 interface GenerateOptions { 9 tsOnly?: boolean; ··· 13 14 export async function generate(options: GenerateOptions = {}) { 15 const workspaceRoot = findWorkspaceRoot(); 16 + 17 + console.log(pc.blue("🔧 Generating lexicon types...")); 18 + 19 try { 20 if (!options.rustOnly) { 21 await generateTypeScript(workspaceRoot, options.force); 22 } 23 + 24 if (!options.tsOnly) { 25 await generateRust(workspaceRoot, options.force); 26 } 27 + 28 + console.log(pc.green("✅ Lexicon generation complete!")); 29 } catch (error) { 30 + console.error( 31 + pc.red("❌ Generation failed:"), 32 + error instanceof Error ? error.message : String(error), 33 + ); 34 process.exit(1); 35 } 36 } 37 38 async function generateTypeScript(workspaceRoot: string, force?: boolean) { 39 + const lexiconsPath = join(workspaceRoot, "lexicons"); 40 + 41 if (!existsSync(lexiconsPath)) { 42 + throw new Error("Lexicons directory not found at workspace root"); 43 } 44 + 45 // Check if packages/lexicons exists for TypeScript generation 46 + const packagesLexiconsPath = join(workspaceRoot, "packages/lexicons"); 47 if (!existsSync(packagesLexiconsPath)) { 48 + console.log( 49 + pc.yellow( 50 + " ⚠️ TypeScript lexicons package not found, skipping TypeScript generation", 51 + ), 52 + ); 53 return; 54 } 55 + 56 + console.log(pc.cyan(" 📦 Generating TypeScript types...")); 57 + 58 try { 59 + await execa("pnpm", ["lex:gen-server"], { 60 cwd: packagesLexiconsPath, 61 + stdio: "inherit", 62 }); 63 + console.log(pc.green(" ✓ TypeScript types generated")); 64 } catch (error) { 65 + throw new Error( 66 + `TypeScript generation failed: ${error instanceof Error ? error.message : String(error)}`, 67 + ); 68 } 69 } 70 71 async function generateRust(workspaceRoot: string, force?: boolean) { 72 + const typesPath = join(workspaceRoot, "services/types"); 73 + const lexiconsPath = join(workspaceRoot, "lexicons"); 74 + 75 if (!existsSync(typesPath)) { 76 + throw new Error("Rust types service not found"); 77 } 78 + 79 if (!existsSync(lexiconsPath)) { 80 + throw new Error("Lexicons directory not found at workspace root"); 81 } 82 + 83 + console.log(pc.cyan(" 🦀 Generating Rust types...")); 84 + 85 try { 86 // Check if esquema-cli is available 87 try { 88 + await execa("esquema-cli", ["--version"], { stdio: "pipe" }); 89 } catch { 90 + console.log(pc.yellow(" ⚠️ esquema-cli not found. Installing...")); 91 try { 92 + await execa( 93 + "cargo", 94 + [ 95 + "install", 96 + "esquema-cli", 97 + "--git", 98 + "https://github.com/fatfingers23/esquema.git", 99 + ], 100 + { 101 + stdio: "inherit", 102 + }, 103 + ); 104 + console.log(pc.green(" ✓ esquema-cli installed successfully")); 105 } catch (installError) { 106 + throw new Error( 107 + "Failed to install esquema-cli. Please install manually: cargo install esquema-cli --git https://github.com/fatfingers23/esquema.git", 108 + ); 109 } 110 } 111 + 112 + // create typespath/src if it doesn't exist 113 + if (!existsSync(join(typesPath, "src"))) { 114 + console.log(pc.yellow(" Creating src directory for Rust types...")); 115 + await execa("mkdir", ["-p", join(typesPath, "src")], { 116 + stdio: "inherit", 117 + }); 118 + } 119 + 120 + await execa( 121 + "esquema-cli", 122 + [ 123 + "generate", 124 + "local", 125 + "--lexdir", 126 + lexiconsPath, 127 + "--outdir", 128 + join(typesPath, "src"), 129 + ], 130 + { 131 + cwd: typesPath, 132 + stdio: "inherit", 133 + }, 134 + ); 135 + 136 + console.log(pc.green(" ✓ Rust types generated")); 137 } catch (error) { 138 + throw new Error( 139 + `Rust generation failed: ${error instanceof Error ? error.message : String(error)}`, 140 + ); 141 } 142 + }