Files
NewTube/src/app/search/api.v1.ts
T
bruno 665a0f0ebd
CI / build-and-test (push) Successful in 14m43s
feat(providers): phases 7.3/7.4/7.6/8.1 — provenance, health, NDJSON, contrat unique
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.
2026-09-30 07:57:11 -04:00

83 lines
2.5 KiB
TypeScript

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[]>;
page?: number;
pageSize?: number;
sort?: 'relevance' | 'date' | 'views';
/** Filtres appliqués côté serveur (les valeurs par défaut sont omises). */
filters?: Record<string, string>;
/** Per-provider backend failures, keyed by provider id. */
errors?: Partial<Record<ProviderId, string>>;
}