Your music, beautifully tracked. All yours. (coming soon) teal.fm
teal-fm atproto
at main 142 lines 3.9 kB view raw
1import { existsSync } from "fs"; 2import { join } from "path"; 3import { execa } from "execa"; 4import pc from "picocolors"; 5 6import { findWorkspaceRoot } from "../utils/workspace.js"; 7 8interface GenerateOptions { 9 tsOnly?: boolean; 10 rustOnly?: boolean; 11 force?: boolean; 12} 13 14export 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 38async 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 71async 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}