import { ApiContext, CacheConfig, RequestDefinition, RetryConfig } from './api.interface'; import { QueryOptions, QueryResult, Unsubscribe } from './query.interface'; /** * Конфигурация эндпоинта */ export interface EndpointConfig = any, RequestResult = any> { /** Функция для создания определения запроса из параметров */ request: (params: RequestParams, context?: Record) => RequestDefinition; /** Настройки кэша для эндпоинта */ cache?: CacheConfig; /** Теги эндпоинта для группировки в кэше */ tags?: string[]; /** Теги, которые инвалидируются при успешном запросе */ invalidatesTags?: string[]; /** Функция для подготовки заголовков (дополняет глобальную) */ prepareHeaders?: (headers: Headers, context: ApiContext) => Promise; /** Добавить ключи заголовков, влияющие на кэш (Дополняет глобавльные ключи) */ includeCacheableHeaderKeys?: string[]; /** Исключить ключи заголовков, влияющие на кэш (Дополняет глобавльные ключи) */ excludeCacheableHeaderKeys?: string[]; /** Конфигурация retry для этого эндпоинта (переопределяет глобальную) */ retry?: RetryConfig; } /** * Состояние эндпоинта * Содержит информацию о текущем состоянии запроса и данные */ export interface EndpointState { /** Статус запроса */ status: 'idle' | 'loading' | 'success' | 'error'; /** Ошибка (при неуспешном запросе) */ error?: Error; /** Количество вызовов */ fetchCounts: number; /** Метаданные эндпоинта */ meta: Endpoint['meta']; /** Какие заголовки участвовали в формировании ключа кэша (итоговые) */ cacheableHeaders: string[]; } /** * Статус выполнения запроса */ export type RequestStatus = 'idle' | 'loading' | 'success' | 'error'; /** * Состояние самого запроса */ export interface RequestState = any, E = Error> { status: RequestStatus; data?: ResponseData; error?: E; headers: Record | Headers; requestParams: RequestParams; fromCache: boolean; } export interface SubscribeOptions { /** Автоматически отписаться после завершения запроса */ autoUnsubscribe?: boolean; } /** * Дополнительные методы для request */ export interface RequestResponseModify = any> { id: string; /** * Подписка на изменения состояния запроса */ subscribe: (listener: (state: RequestState) => void, options?: SubscribeOptions) => VoidFunction; /** * Ожидание завершения запроса * @returns Promise с результатом запроса */ wait: () => Promise>; waitWithCallbacks: (handlers: { idle?: (request: RequestState) => void; loading?: (request: RequestState) => void; success?: (data: T | undefined, request: RequestState) => void; error?: (error: Error | undefined, request: RequestState) => void; }) => Promise>; /** * Отменить запрос */ abort: VoidFunction; then, TResult2 = never>(onfulfilled?: ((value: QueryResult) => TResult1 | PromiseLike) | undefined | null, onrejected?: ((reason: Error) => TResult2 | PromiseLike) | undefined | null): Promise; catch(onrejected?: ((reason: Error) => TResult | PromiseLike) | undefined | null): Promise | TResult>; finally(onfinally?: VoidFunction | undefined | null): Promise>; } /** * Структура эндпоинта * * Эндпоинт - это всего лишь определение того6 как будет вызван метод * Эндпоинт может быть вызван в разных частях приложения с разными параметрами * По этому нет смысла хранить ответы так как они будут перезаписываться * метод subscribe больше нужен для мониторинга * meta - метаинформация по эндпоинту (то как он сконфигурирован) */ export interface Endpoint = any, ResponseData = any> { /** Счетчик вызова конкретного эндпоинта в проекте */ fetchCounts: number; /** Выполнить запрос с параметрами */ request: (params: RequestParams, options?: QueryOptions) => RequestResponseModify; /** Подписаться на изменения состояния эндпоинта (в основном для сбора статистики) */ subscribe: (callback: (state: EndpointState) => void) => Unsubscribe; /** * Синхронно прочитать результат из кэша без сетевого запроса (fast-path для SSR). * Возвращает `undefined`, если кэш недоступен синхронно (async-хранилище, * заголовки в ключе кэша, отключённый кэш или протухшая запись). */ getCachedSync: (params: RequestParams) => QueryResult | undefined; /** Подписка на инвалидацию кэша по тегам эндпоинта (для авто-рефетча хуков) */ onCacheInvalidate: (listener: VoidFunction) => Unsubscribe; /** Сбросить состояние */ reset: () => Promise; /** Метаданные эндпоинта */ meta: { /** Имя эндпоинта */ name: string; /** Теги эндпоинта */ tags: string[]; /** Теги, которые инвалидируются */ invalidatesTags: string[]; /** Настройки кэша */ cache: CacheConfig; }; destroy: VoidFunction; } /** * Функция для создания типизированных эндпоинтов */ export type CreateEndpoint = , RequestResult>(config: EndpointConfig) => EndpointConfig;