(version: string)
| 21 | const GHCR_BASE = 'ghcr.io/learnhouse/app' |
| 22 | |
| 23 | async function resolveTag(version: string): Promise<boolean> { |
| 24 | try { |
| 25 | const tokenResp = await fetch( |
| 26 | 'https://ghcr.io/token?scope=repository:learnhouse/app:pull', |
| 27 | { signal: AbortSignal.timeout(5000) }, |
| 28 | ) |
| 29 | if (!tokenResp.ok) return false |
| 30 | const { token } = (await tokenResp.json()) as { token: string } |
| 31 | |
| 32 | const manifestResp = await fetch( |
| 33 | `https://ghcr.io/v2/learnhouse/app/manifests/${version}`, |
| 34 | { |
| 35 | signal: AbortSignal.timeout(5000), |
| 36 | headers: { |
| 37 | Accept: |
| 38 | 'application/vnd.oci.image.index.v1+json, application/vnd.docker.distribution.manifest.list.v2+json', |
| 39 | Authorization: `Bearer ${token}`, |
| 40 | }, |
| 41 | }, |
| 42 | ) |
| 43 | return manifestResp.ok |
| 44 | } catch { |
| 45 | return false |
| 46 | } |
| 47 | } |
| 48 | |
| 49 | export async function updateCommand(options: { version?: string; migrate?: boolean; backup?: boolean }) { |
| 50 | const dir = findInstallDir() |
no test coverage detected