this repo has no description
1import { createWriteStream } from 'node:fs'
2import { unlink } from 'node:fs/promises'
3import { Readable } from 'node:stream'
4import { pipeline } from 'node:stream/promises'
5import type { ReadableStream } from 'node:stream/web'
6import type { ReleaseInfo } from './index.js'
7
8export async function fetchReleaseInfo(repo: string, version: string): Promise<ReleaseInfo> {
9 const url = `https://api.github.com/repos/${repo}/releases/tags/${version}`
10
11 const response = await fetch(url, {
12 headers: { Accept: 'application/vnd.github.v3+json' },
13 })
14
15 if (!response.ok) {
16 if (response.status === 404) throw new Error(`Release ${version} not found for repository ${repo}`)
17 throw new Error(`Failed to fetch release info: ${response.status} ${response.statusText}`)
18 }
19
20 const data = await response.json()
21
22 return {
23 tag_name: data.tag_name,
24 assets: data.assets.map((asset: { name: string; browser_download_url: string; size: number }) => ({
25 name: asset.name,
26 download_url: asset.browser_download_url,
27 size: asset.size,
28 })),
29 }
30}
31
32export async function downloadAsset(url: string, outputPath: string): Promise<void> {
33 const response = await fetch(url)
34
35 if (!response.ok) throw new Error(`Failed to download asset: ${response.status} ${response.statusText}`)
36 if (!response.body) throw new Error('GitHub API response body is empty')
37
38 // Use streaming for better memory efficiency
39 const fileStream = createWriteStream(outputPath)
40 const readableStream = Readable.fromWeb(response.body as ReadableStream)
41
42 try {
43 await pipeline(readableStream, fileStream)
44 } catch (error) {
45 // Clean up partial file on error
46 try {
47 await unlink(outputPath)
48 } catch {
49 // Ignore cleanup errors
50 }
51 throw new Error(`Failed to download asset: ${error instanceof Error ? error.message : 'Unknown error'}`)
52 }
53}