export interface RichContent { type: string; url: string; siteName?: string; title?: string; description?: string; /** * A real preview image (og:image, a large content image, a video still). * Never a favicon — an absent value means "this page offers no artwork", * which is what makes the generated placeholder possible. */ thumbnailUrl?: string; /** The page's own icon, used as the placeholder's glyph. */ faviconUrl?: string; /** The page's declared brand color, normalized to `#rrggbb`. */ accentColor?: string; videoId?: string; embedUrl?: string; } export interface Dump { id: string; kind: "url" | "file"; title: string; slug?: string; comment?: string; userId: string; createdAt: Date; updatedAt?: Date; url?: string; richContent?: RichContent; fileName?: string; fileMime?: string; fileSize?: number; voteCount: number; commentCount: number; isPrivate: boolean; thumbnailMime?: string; categoryIds?: string[]; } /** * An existing dump pointing at the same URL, as shown by the create form's * duplicate hint (`GET /api/dumps/by-url`). Display-only projection — see * `findDumpsByUrl`. */ export interface DumpUrlMatch { id: string; slug?: string; title: string; username: string; createdAt: Date; voteCount: number; commentCount: number; } /** * `GET /api/preview`. `reached` is separate because a failed fetch still yields * a usable stub (hostname only): without it the create form can't tell "this * page has no preview" from "this link is dead". */ export interface LinkPreview { reached: boolean; richContent: RichContent | null; } export interface CreateUrlDumpRequest { url: string; /** Overrides the title scraped from the page — the poster edited the preview. */ title?: string; comment?: string; isPrivate?: boolean; categoryIds?: string[]; } export interface UpdateDumpRequest { url?: string; title?: string; /** `null` removes the note; leaving it out keeps it. */ comment?: string | null; isPrivate?: boolean; categoryIds?: string[]; } /** `POST /api/attachments`: the id the uploaded image is served under. */ export interface AttachmentResponse { id: string; }