import type { ProviderId } from '../shared/providers/provider-ids'; import type { ChannelRef } from '../shared/providers/channel-ref'; export type { ProviderId, ChannelRef }; /** * Contrat `Suggestion` v2 — doit rester aligné avec le JSDoc de * `server/providers/registry.mjs` (vérifié par `npm run test:contract`). * * v1 (inchangé, rétrocompatible) : title, id, duration, isShort, thumbnail, * uploaderName, url, type. * v2 (additif) : compteurs, dates ISO, identité de chaîne, avatars, et flags. * * Règle : un champ absent est `undefined`, jamais `0` ni `''`. Une durée nulle * n'existe pas — elle casse les règles de classification (voir §2.2 du plan). */ export interface SuggestionItemV1 { title: string; id: string; /** Secondes, strictement > 0. `undefined` = durée inconnue. */ duration?: number; isShort?: boolean; thumbnail?: string; uploaderName?: string; url?: string; type?: string; // --- v2 --- /** Vues (> 0). */ views?: number; /** * Phase 3.8 / 7.3 — spectateurs EN DIRECT (Twitch `viewer_count`). * Distinct de `views` : ne jamais afficher comme un compteur de vues. */ viewers?: number; likes?: number; dislikes?: number; /** ISO 8601. Jamais « il y a 2 mois ». */ publishedAt?: string; channelId?: string; channelExternalId?: string; channelHandle?: string; channelUrl?: string; uploaderAvatar?: string; channelAvatarUrl?: string; slug?: string; channel?: string; /** 'vod' | 'live' | 'clip' (Twitch). */ kind?: string; game?: string; /** BCP-47. */ language?: string; hasSubtitles?: boolean; isLive?: boolean; embeddable?: boolean; description?: string; tags?: string[]; /** Libellés bruts, pour afficher « valeur approchée » plutôt que « — ». */ durationRaw?: string; viewCountRaw?: string; /** * Phase 6 — identité de chaîne normalisée. `channelExternalId` reste lu en * repli (transition non cassante) mais `channelRef` est la forme canonique : * `scheme` dit comment lire `value`. */ channelRef?: ChannelRef; } export interface SearchResponseV1 { /** Version du contrat `Suggestion` (2 depuis la phase 0). */ v?: number; q: string; providers: ProviderId[]; groups: Record; page?: number; pageSize?: number; sort?: 'relevance' | 'date' | 'views'; /** Filtres appliqués côté serveur (les valeurs par défaut sont omises). */ filters?: Record; /** Per-provider backend failures, keyed by provider id. */ errors?: Partial>; }