| 1 | import { z } from "zod"; |
| 2 | |
| 3 | import { formatBytes } |
| 4 | |
| 5 | export const releaseSchema = |
| 6 | tagName: z |
| 7 | .string() |
| 8 | .trim() |
| 9 | .min(1, " |
| 10 | .max(250, " |
| 11 | target: z.string |
| 12 | name: z.string |
| 13 | body: z.string |
| 14 | isPrerelease: z.boolean |
| 15 | }); |
| 16 | |
| 17 | export type ReleaseInput |
| 18 | |
| 19 | /** Where a release, its edit form or its downloads live. Tags may contain `/`, so each segment is encoded on its own. */ |
| 20 | export function releasePath( |
| 21 | username: string, |
| 22 | repo: string, |
| 23 | tagName: string, |
| 24 | view: "tag |
| 25 | ) { |
| 26 | return `/${username |
| 27 | } |
| 28 | |
| 29 | /** Why these files cannot be uploaded, checked before any byte is sent; the API checks again. Null when they fit. */ |
| 30 | export function assetProblem( |
| 31 | files: { |
| 32 | existing: { |
| 33 | storage: { |
| 34 | usedBytes: number |
| 35 | quotaBytes: number |
| 36 | maxAssetBytes: number |
| 37 | } | null |
| 38 | ) { |
| 39 | const names = |
| 40 | for (const file |
| 41 | if (names.has |
| 42 | names.add(file |
| 43 | if (storage && |
| 44 | return `${file. |
| 45 | } |
| 46 | } |
| 47 | |
| 48 | if (storage?.quotaBytes |
| 49 | const needed = |
| 50 | const free = |
| 51 | if (needed > |
| 52 | return `These files need ${formatBytes |
| 53 | } |
| 54 | } |
| 55 | return null; |
| 56 | } |