(name: string, dir: string)
| 36 | return []; // unreadable registry → no projects, not a crashed request |
| 37 | } |
| 38 | // Accept the canonical `{projects: [...]}`, and tolerate a bare array, which is what a |
| 39 | // hand-edited file usually becomes. |
| 40 | const list = Array.isArray(parsed) |
| 41 | ? parsed |
| 42 | : Array.isArray((parsed as { projects?: unknown })?.projects) |
| 43 | ? (parsed as { projects: unknown[] }).projects |
| 44 | : []; |
| 45 | return list.filter( |
| 46 | (entry): entry is Project => |
| 47 | typeof entry === 'object' && |
| 48 | entry !== null && |
| 49 | typeof (entry as Project).name === 'string' && |
| 50 | typeof (entry as Project).path === 'string', |
| 51 | ); |
| 52 | } |
| 53 | |
| 54 | export async function findProject(name: string): Promise<Project | null> { |
| 55 | return (await loadProjects()).find((p) => p.name === name) ?? null; |
| 56 | } |
no test coverage detected