(filePath: string, content: string)
| 72 | // ── Core: Upload to HuggingFace ────────────────────────────────────── |
| 73 | |
| 74 | async function commitFile(filePath: string, content: string): Promise<boolean> { |
| 75 | const { token, repo, branch } = getConfig() |
| 76 | if (!token || !repo) return false |
| 77 | |
| 78 | const url = `${HF_API}/datasets/${repo}/commit/${branch}` |
| 79 | |
| 80 | // HF Hub commit API uses NDJSON (application/x-ndjson) |
| 81 | // Line 1: commit header with summary |
| 82 | // Line 2: file operation with base64-encoded content |
| 83 | const contentBase64 = Buffer.from(content).toString('base64') |
| 84 | const ndjson = [ |
| 85 | JSON.stringify({ key: 'header', value: { summary: `[auto-publish] ${filePath}` } }), |
| 86 | JSON.stringify({ key: 'file', value: { content: contentBase64, path: filePath, encoding: 'base64' } }), |
| 87 | ].join('\n') |
| 88 | |
| 89 | try { |
| 90 | const res = await fetch(url, { |
| 91 | method: 'POST', |
| 92 | headers: { |
| 93 | 'Authorization': `Bearer ${token}`, |
| 94 | 'Content-Type': 'application/x-ndjson', |
| 95 | }, |
| 96 | body: ndjson, |
| 97 | }) |
| 98 | |
| 99 | if (res.ok) { |
| 100 | console.log(`[HF Publisher] Committed ${filePath} (${content.length} bytes)`) |
| 101 | return true |
| 102 | } |
| 103 | |
| 104 | const errText = await res.text().catch(() => '') |
| 105 | console.error(`[HF Publisher] Commit failed (${res.status}): ${errText.slice(0, 200)}`) |
| 106 | return false |
| 107 | } catch (err) { |
| 108 | console.error(`[HF Publisher] Network error:`, (err as Error).message) |
| 109 | return false |
| 110 | } |
| 111 | } |
| 112 | |
| 113 | // ── Flush Functions ────────────────────────────────────────────────── |
| 114 | // Safe pattern: snapshot → upload → clear only on success |
no test coverage detected