a reactive (signals based) hypermedia web framework (wip) stormlightlabs.github.io/volt/
hypermedia frontend signals
at main 2.8 kB view raw
1import { existsSync } from "node:fs"; 2import { readFile } from "node:fs/promises"; 3import path from "node:path"; 4 5/** 6 * Find the monorepo root by walking up the directory tree. 7 * 8 * Looks for pnpm-workspace.yaml with valid workspace packages or a package.json with workspaces defined. 9 */ 10export async function findMonorepoRoot(startDir: string = process.cwd()): Promise<string> { 11 let currentDir = startDir; 12 const maxDepth = 10; 13 let depth = 0; 14 15 while (depth < maxDepth) { 16 const workspaceYaml = path.join(currentDir, "pnpm-workspace.yaml"); 17 const packageJson = path.join(currentDir, "package.json"); 18 19 if (existsSync(workspaceYaml)) { 20 const hasLibPackage = existsSync(path.join(currentDir, "lib", "package.json")); 21 const hasCliPackage = existsSync(path.join(currentDir, "cli", "package.json")); 22 23 if (hasLibPackage || hasCliPackage) { 24 return currentDir; 25 } 26 } 27 28 if (existsSync(packageJson)) { 29 try { 30 const pkgContent = JSON.parse(await readFile(packageJson, "utf8")); 31 if (pkgContent.workspaces || pkgContent.private) { 32 const hasLibPackage = existsSync(path.join(currentDir, "lib", "package.json")); 33 const hasCliPackage = existsSync(path.join(currentDir, "cli", "package.json")); 34 35 if (hasLibPackage || hasCliPackage) { 36 return currentDir; 37 } 38 } 39 } catch { 40 // No-Op: Continue searching 41 } 42 } 43 44 const parentDir = path.dirname(currentDir); 45 if (parentDir === currentDir) { 46 throw new Error("Could not find monorepo root. Make sure you're in the Volt project directory."); 47 } 48 49 currentDir = parentDir; 50 depth++; 51 } 52 53 throw new Error("Could not find monorepo root. Make sure you're in the Volt project directory."); 54} 55 56/** 57 * Get the path to the lib package directory 58 */ 59export async function getLibPath(startDir?: string): Promise<string> { 60 const root = await findMonorepoRoot(startDir); 61 return path.join(root, "lib"); 62} 63 64/** 65 * Get the path to the docs package directory 66 */ 67export async function getDocsPath(startDir?: string): Promise<string> { 68 const root = await findMonorepoRoot(startDir); 69 return path.join(root, "docs"); 70} 71 72/** 73 * Get the path to the examples directory 74 */ 75export async function getExamplesPath(startDir?: string): Promise<string> { 76 const root = await findMonorepoRoot(startDir); 77 return path.join(root, "examples"); 78} 79 80/** 81 * Get the path to the lib source directory 82 */ 83export async function getLibSrcPath(startDir?: string): Promise<string> { 84 const libPath = await getLibPath(startDir); 85 return path.join(libPath, "src"); 86} 87 88/** 89 * Get the path to the lib test directory 90 */ 91export async function getLibTestPath(startDir?: string): Promise<string> { 92 const libPath = await getLibPath(startDir); 93 return path.join(libPath, "test"); 94}