export type Credential = { kind: 'password' | 'hash' | 'invite'; value: string } function credentialHeaders(cred: Credential): Record { if (cred.kind === 'password') return { 'X-Upload-Password': cred.value } if (cred.kind === 'hash') return { 'X-Upload-Password-Hash': cred.value } return { 'X-Upload-Invite': cred.value } } export async function checkCredential(cred: Credential): Promise { const res = await fetch('/api/auth/check', { method: 'POST', headers: credentialHeaders(cred), }) const body = (await res.json()) as { ok: boolean } return body.ok } export async function uploadDrop( ciphertext: Uint8Array, cred: Credential, ): Promise<{ id: string; ttl: number }> { const res = await fetch('/api/drops', { method: 'POST', headers: { 'Content-Type': 'application/octet-stream', ...credentialHeaders(cred), }, body: ciphertext.slice().buffer, }) if (!res.ok) { const body = (await res.json().catch(() => ({}))) as { error?: string } throw new Error(body.error ?? `upload failed: ${res.status}`) } return res.json() } export async function downloadDrop( id: string, ): Promise<{ ciphertext: Uint8Array; confirmToken: string }> { const res = await fetch(`/api/drops/${id}`) if (!res.ok) throw new Error(`download failed: ${res.status}`) const confirmToken = res.headers.get('X-Confirm-Token') ?? '' const ciphertext = new Uint8Array(await res.arrayBuffer()) return { ciphertext, confirmToken } } export async function confirmDrop(id: string, confirmToken: string): Promise { await fetch(`/api/drops/${id}/confirm`, { method: 'POST', headers: { Authorization: `Bearer ${confirmToken}` }, }) }