feat(providers): phases 7.3/7.4/7.6/8.1 — provenance, health, NDJSON, contrat unique
CI / build-and-test (push) Successful in 14m43s
CI / build-and-test (push) Successful in 14m43s
7.3: capturedAt/source au registre + 6 adaptateurs + module provenance.ts + ?debug=1 (search-transport.mjs). 7.4: ProviderHealthService + badge source degradee. 7.6: squelettes par provider + snapshots progressifs + transport NDJSON /api/search. 8.1: ProviderAdapter unifie (search enveloppe + channelContent/channelMeta/capabilities) via getProviderAdapter + test de contrat offline.
This commit is contained in:
@@ -1,17 +1,74 @@
|
||||
export type ProviderId = 'yt' | 'dm' | 'tw' | 'pt' | 'od' | 'ru';
|
||||
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<ProviderId, SuggestionItemV1[]>;
|
||||
|
||||
Reference in New Issue
Block a user