import type { ResolvedConfig } from "../shared/config.js"; import type { ManifestEntry } from "./manifest.js"; export interface PublishProject { id: string; slug: string; name: string; liveUrl: string; publishState: "never" | "live" | "unpublished" | "not_serving"; firstPublishedAt: string | null; liveVersion: number | null; highestVersion: number | null; /** The LIVE version's publishedAt. Ledger-derived; it is why the checklist needs one call. */ livePublishedAt: string | null; rolledBackFrom: number | null; } export interface UploadTarget { path: string; /** The presigned S3 PUT. THE CLI NEVER PARSES IT. */ url: string; /** * The map the CLI MUST send verbatim. Content-Type and x-amz-checksum-sha256 * are both covered by the signature: dropping either yields * SignatureDoesNotMatch, which reads as an auth bug and gets "fixed" by * deleting the header — §2.7's contract traps 3 and 4. */ headers: Record; } export interface OpenedUpload { uploadId: string; uploads: UploadTarget[]; expiresAt: string; } export interface CommitResult { version: number; liveVersion: number; highestVersion: number; liveUrl: string; publishedAt: string; /** Response-side name of the request's `note`. The asymmetry is deliberate. */ releaseNote?: string; } export interface ApiErrorDetail { limit?: number; observed?: number; missing?: number; mismatched?: number; reason?: string; path?: string; } export declare class PublishApiError extends Error { readonly status: number; readonly code: string; readonly detail: ApiErrorDetail; readonly retryAfterSec?: number | undefined; constructor(status: number, code: string, message: string, detail?: ApiErrorDetail, retryAfterSec?: number | undefined); } /** The ONE call before the checklist. liveVersion + livePublishedAt ride it, by design. */ export declare function readProject(cfg: ResolvedConfig, projectId: string, fetchImpl?: typeof fetch): Promise; /** * Open an upload. The request body carries `files` (path/size/sha256) and an * optional `note`, AND NOTHING ELSE — there is no field for a MIME type and no * field a parsed title, description or image URL could land in. */ export declare function openUpload(cfg: ResolvedConfig, projectId: string, files: ManifestEntry[], note: string | undefined, fetchImpl?: typeof fetch): Promise; export declare function commitUpload(cfg: ResolvedConfig, projectId: string, uploadId: string, fetchImpl?: typeof fetch): Promise; /** Abandon an open upload. Idempotent server-side; a failure here must never mask the real error. */ export declare function abandonUpload(cfg: ResolvedConfig, projectId: string, uploadId: string, fetchImpl?: typeof fetch): Promise;