(params: { path: string })
| 39 | * Read openade.toml process config from a search root. |
| 40 | */ |
| 41 | export async function readRuntimeProcs(params: { path: string }): Promise<ReadProcsResult> { |
| 42 | const searchRoot = params.path |
| 43 | if (TRACE_PROCS_READS) logger.debug(`[Procs] Reading config from ${searchRoot}`) |
| 44 | |
| 45 | // Detect git info |
| 46 | const gitInfo = await detectGitInfo(searchRoot) |
| 47 | if (TRACE_PROCS_READS) logger.debug(`[Procs] Git info:`, JSON.stringify(gitInfo)) |
| 48 | |
| 49 | // Find all config files (openade.toml) |
| 50 | const configFiles = await findProcsFiles(searchRoot, gitInfo) |
| 51 | if (TRACE_PROCS_READS) logger.debug(`[Procs] Found ${configFiles.length} config files`) |
| 52 | |
| 53 | // Parse each file |
| 54 | const configs: ProcsConfig[] = [] |
| 55 | const errors: ProcsConfigError[] = [] |
| 56 | |
| 57 | for (const filePath of configFiles) { |
| 58 | try { |
| 59 | const content = await fs.readFile(filePath, "utf-8") |
| 60 | const relativePath = path.relative(gitInfo?.repoRoot ?? searchRoot, filePath) |
| 61 | const result = parseProcsFile(content, relativePath) |
| 62 | |
| 63 | if ("config" in result) { |
| 64 | configs.push(result.config) |
| 65 | if (TRACE_PROCS_READS) logger.debug(`[Procs] Parsed ${relativePath}: ${result.config.processes.length} processes, ${result.config.crons.length} crons`) |
| 66 | } else { |
| 67 | errors.push(result.error) |
| 68 | logger.warn(`[Procs] Parse error in ${relativePath}: ${result.error.error}`) |
| 69 | } |
| 70 | } catch (e) { |
| 71 | // File read error |
| 72 | const relativePath = path.relative(gitInfo?.repoRoot ?? searchRoot, filePath) |
| 73 | const error = e instanceof Error ? e.message : "Failed to read file" |
| 74 | errors.push({ relativePath, error }) |
| 75 | logger.error(`[Procs] Read error for ${relativePath}: ${error}`) |
| 76 | } |
| 77 | } |
| 78 | |
| 79 | return { |
| 80 | repoRoot: gitInfo?.repoRoot ?? searchRoot, |
| 81 | searchRoot, |
| 82 | isWorktree: gitInfo?.isWorktree ?? false, |
| 83 | worktreeRoot: gitInfo?.worktreeRoot, |
| 84 | configs, |
| 85 | errors, |
| 86 | } |
| 87 | } |
| 88 | |
| 89 | async function getRepoRootForPath(filePath: string, searchPath?: string): Promise<string> { |
| 90 | if (searchPath) { |
no test coverage detected