/** * Input/output TypeScript interfaces for all JSON-LD builders. * * These describe the data shape each builder expects, NOT the raw API response * shape (those exist in `api/types.ts`). The mapping from API types to these * builder input types happens at the call site. */ /** What buildEventJsonLd expects for an event. */ export interface EventJsonLdInput { name: string; startDateTime: string; endDateTime?: string; status?: string; description?: string; eventSummary?: string; image?: string; coverImage?: string; ShowImage?: string; availableTickets?: EventTicketInput[]; performers?: EventPerformerInput[]; } export interface EventTicketInput { visibility?: number; salesChannel?: number; price?: number | string; /** * Per-ticket service fee (dollars). The JSON-LD offer must advertise the same * all-in total the ticket row renders (ticketAllInPrice, MIC-1772), so the * offer builder adds this to `price` rather than publishing the bare wire * price. Absent means a legitimate 0 fee, not a missing value. */ fee?: number | string; remainingCapacity?: number; quantityRemaining?: number; quantity?: number; soldOut?: boolean; salesBegin?: string; salesStart?: string; saleBegin?: string; onSaleStart?: string; salesEnd?: string; saleEnd?: string; onSaleEnd?: string; } export interface EventPerformerInput { acceptedState?: number; shouldBeHidden?: boolean; RosterPerformer?: { User?: { performerProfile?: { firstName?: string; lastName?: string; displayName?: string; }; }; }; } export interface VenueInput { name: string; address?: string; city?: string; state?: string; postalCode?: string; country?: string; googleLocationNameCache?: string; } export interface OrganizerInput { name: string; url?: string; } /** What buildSeriesJsonLd expects. */ export interface SeriesJsonLdInput { title: string; description?: string; eventSummary?: string; image?: string; timeZone: string; venue: { name: string; address?: string; city?: string; state?: string; postalCode?: string; country?: string; googleLocationNameCache?: string; }; performers?: Array<{ displayName: string; }>; occurrences: Array<{ id: number; title: string; slug: string; startDateTime: string; endDateTime?: string; status?: string; tickets?: Array<{ name: string; price: number; status: string; }>; }>; } /** Options for HostSeoController constructor */ export interface HostSeoControllerOptions { /** Venue name for JSON-LD location and page title */ venueName: string; /** Venue address string (from googleLocationNameCache or address field) */ venueAddress?: string; /** Venue timezone (IANA), defaults to getDefaultTimezone() */ venueTimeZone?: string; /** Base URL for canonical links, e.g., "https://comedy-club.com/shows" (defaults to current page URL without query params) */ baseUrl?: string; /** * Origin of the Micdrop site that server-renders `/e/{id}-{slug}`, e.g. * "https://get-micdrop.com". Trailing slashes are stripped. * * This is what makes the injected structured data crawlable. A host page has * ONE URL however many shows the widget draws on it, so without a per-show * address the whole listing is a single URL to a search engine. `/e/{id}-{slug}` * is the only per-show page that exists and server-renders. * * Unset falls back to the host page's in-place deep link — today's behaviour, * and the right degradation: a guessed origin would publish 404s. */ publicSiteOrigin?: string; } /** What buildCollectionJsonLd expects. */ export interface CollectionJsonLdInput { collectionTitle: string; description?: string; summary?: string; coverImage?: string; dateRange?: { startDate: string; endDate: string; } | null; events: Array<{ id: number; title: string; slug?: string; startDateTime?: string; endDateTime?: string; image?: string; status?: string; venueName?: string; venueAddress?: string; venueId?: number; }>; }