( id: string, raw: string, )
| 198 | * both paths agree on the exact schema + error shape. Never throws. |
| 199 | */ |
| 200 | export function parseIssueContent( |
| 201 | id: string, |
| 202 | raw: string, |
| 203 | ): { ok: true; issue: IssueRecord } | { ok: false; error: string } { |
| 204 | const split = splitFrontmatter(raw) |
| 205 | if (!split) return { ok: false, error: 'missing YAML frontmatter (expected a leading `---` block)' } |
| 206 | |
| 207 | let data: unknown |
| 208 | try { |
| 209 | data = parseYaml(split.frontmatter) |
| 210 | } catch (err) { |
| 211 | return { ok: false, error: `invalid YAML frontmatter: ${err instanceof Error ? err.message : String(err)}` } |
| 212 | } |
| 213 | if (data === null || typeof data !== 'object' || Array.isArray(data)) { |
| 214 | return { ok: false, error: 'frontmatter is not a mapping' } |
| 215 | } |
| 216 | const rawFrontmatter = data as Record<string, unknown> |
| 217 | |
| 218 | const parsed = issueFrontmatterSchema.safeParse(data) |
| 219 | if (!parsed.success) { |
| 220 | return { ok: false, error: parsed.error.issues.map((i) => `${i.path.join('.')}: ${i.message}`).join('; ') } |
| 221 | } |
| 222 | |
| 223 | return { |
| 224 | ok: true, |
| 225 | issue: { |
| 226 | id, |
| 227 | ...parsed.data, |
| 228 | body: split.body, |
| 229 | assigneeDefaulted: !Object.prototype.hasOwnProperty.call(rawFrontmatter, 'assignee'), |
| 230 | }, |
| 231 | } |
| 232 | } |
| 233 | |
| 234 | /** Split a `---\n<yaml>\n---\n<body>` document. Line-based so a `---` inside the |
| 235 | * body (e.g. a markdown horizontal rule) never confuses the close fence. Returns |
no test coverage detected