(cwd: string, id: string)
| 137 | // ── I/O operations (writes go through WriteFn) ──────────────────────────────── |
| 138 | |
| 139 | async function readManifest(cwd: string, id: string): Promise<ArtifactManifest | null> { |
| 140 | let raw: string; |
| 141 | try { |
| 142 | raw = await fs.readFile(manifestPath(cwd, id), 'utf-8'); |
| 143 | } catch (err: any) { |
| 144 | // Truly absent → quietly null. Any other read error (permissions, etc.) is |
| 145 | // NOT "deleted" — surface it rather than masking it. |
| 146 | if (err?.code === 'ENOENT') return null; |
| 147 | throw err; |
| 148 | } |
| 149 | try { |
| 150 | return JSON.parse(raw) as ArtifactManifest; |
| 151 | } catch (err: any) { |
| 152 | // The manifest exists but is corrupt (e.g. a truncated write). Do NOT report |
| 153 | // the artifact as absent — that would make it look deleted. Surface it. |
| 154 | throw new Error(`Artifact "${id}" has a corrupt manifest.json: ${err?.message ?? err}`); |
| 155 | } |
| 156 | } |
| 157 | |
| 158 | /** Resolve a unique id when the slug already exists (append -2, -3, …). */ |
| 159 | async function uniqueId(cwd: string, base: string): Promise<string> { |
no test coverage detected