UNPKG

novel-reader-sdk

Version:

SDK for Novel Reader API

386 lines (347 loc) 8.26 kB
/** * Shared Types for Novel Reader Scraping Service * * Single source of truth for all API types used by both service and client */ // ===== Core Data Models ===== export interface Review { username: string; rating: number; progress?: string; date: string; content: string; likes: number; spoilers?: Array<{ position: number; content: string }>; } export interface NovelDetails extends NovelSearchResult { alternativeTitles?: string[]; author?: string; artist?: string; year?: number; status?: string; licensed?: boolean; englishPublisher?: string; tags?: string[]; reviews?: Review[]; chapterList?: Array<{ title: string; url: string; releaseDate?: string; group?: string; }>; } export interface Chapter { title: string; url: string; chapterNumber?: number; publishedAt?: string; } export interface ChapterData { title: string; content: string; navigation: { previousChapter?: string; nextChapter?: string; }; } export interface NovelSearchResult { title: string; url: string; coverUrl?: string; rating?: number; chapters?: number; status?: string; genres?: string[]; description?: string; } export interface SiteConfiguration { name: string; hostname: string; configuration: { titleSelector: string; contentSelector: string; contentParagraphSelector: string; navigationSelectors: { previousChapter: string; nextChapter: string; }; }; status: 'active' | 'inactive'; useProxy: boolean; } // ===== API Response Types ===== export interface ScrapingServiceResponse<T> { results: T; } export interface PaginatedResponse<T> { results: T[]; pagination: { page: number; total: number; hasNext: boolean; }; } export interface ApiError { error: { code: string; message: string; }; } // ===== Health Management Types ===== /** * Service health status levels */ export type ServiceStatus = 'healthy' | 'degraded' | 'unhealthy'; /** * Browser manager health status */ export interface BrowserHealthStatus { status: ServiceStatus; activeInstances: number; availableInstances: number; totalInstances: number; maxInstances: number; error?: string; } /** * Proxy provider breakdown statistics */ export interface ProxyProviderBreakdown { total: number; healthy: number; unhealthy: number; } /** * Comprehensive proxy health status */ export interface ProxyHealthStatus { status: ServiceStatus; pool: { enabled: boolean; totalProxies: number; healthyProxies: number; unhealthyProxies: number; healthyPercentage: number; hasEnoughHealthyProxies: boolean; }; providers: Record<'getproxylist' | 'proxyscrape' | 'geonode', ProxyProviderBreakdown>; schedule: { lastRefresh: string; nextRefresh: string; lastHealthCheck: string; nextHealthCheck: string; }; recommendations: string[]; error?: string; } /** * Complete health overview for dashboards */ export interface HealthOverview { timestamp: string; serviceStatus: { isOnline: boolean; }; overall: { status: ServiceStatus; }; browser: BrowserHealthStatus | null; proxy: ProxyHealthStatus | null; errors: { overall?: string; proxy?: string; browser?: string; }; } // ===== Health Status Types ===== export interface ProxyPoolInfo { enabled: boolean; totalProxies: number; healthyProxies: number; unhealthyProxies: number; healthyPercentage: number; hasEnoughHealthyProxies: boolean; } export interface HealthStatus { status: 'healthy' | 'degraded' | 'unhealthy'; timestamp: string; version: string; browser: { activeInstances: number; availableInstances: number; totalInstances: number; maxInstances: number; }; proxy: ProxyPoolInfo; } // ===== Request/Response Schemas ===== export interface SearchNovelsRequest { query: string; page?: number; limit?: number; } export interface ScrapeChapterRequest { url: string; customConfig?: Partial<SiteConfiguration['configuration']>; } export interface BatchScrapeRequest { urls: string[]; maxConcurrent?: number; } export interface ValidateUrlRequest { url: string; } export interface TestSiteConfigRequest { hostname: string; testUrl: string; } // ===== Database Scraper Types ===== export interface DatabaseInfo { id: string; name: string; description: string; supportedOperations: ('search' | 'latest' | 'popular' | 'novel')[]; status: 'active' | 'inactive'; } export interface LatestNovelsRequest { page?: number; limit?: number; } export interface PopularNovelsRequest { period?: 'day' | 'week' | 'month' | 'all'; page?: number; limit?: number; } export interface NovelDetailsRequest { url: string; includeChapters?: boolean; } // ===== Error Types ===== export type ErrorCode = | 'INTERNAL_SERVER_ERROR' | 'NOT_FOUND' | 'BAD_REQUEST' | 'UNSUPPORTED_SITE' | 'CONTENT_NOT_FOUND' | 'BROWSER_ERROR' | 'TIMEOUT_ERROR' | 'RATE_LIMIT_EXCEEDED'; export type ErrorType = | 'SCRAPING_ERROR' | 'CHAPTER_NOT_FOUND' | 'CONTENT_NOT_FOUND' | 'UNSUPPORTED_SITE' | 'BROWSER_ERROR' | 'TIMEOUT_ERROR' | 'VALIDATION_ERROR' | 'RATE_LIMIT_ERROR'; // ===== Utility Types ===== export type DatabaseId = 'novelupdates'; export type SupportedOperation = 'search' | 'latest' | 'popular' | 'novel'; // ===== API Route Definitions ===== export interface ApiRoutes { databases: { list: { method: 'GET'; path: '/api/v1/databases'; response: ScrapingServiceResponse<DatabaseInfo[]>; }; search: { method: 'GET'; path: '/api/v1/databases/:id/search'; params: { id: DatabaseId }; query: SearchNovelsRequest; response: PaginatedResponse<NovelSearchResult>; }; latest: { method: 'GET'; path: '/api/v1/databases/:id/latest'; params: { id: DatabaseId }; query: LatestNovelsRequest; response: PaginatedResponse<NovelSearchResult>; }; popular: { method: 'GET'; path: '/api/v1/databases/:id/popular'; params: { id: DatabaseId }; query: PopularNovelsRequest; response: PaginatedResponse<NovelSearchResult>; }; novel: { method: 'GET'; path: '/api/v1/databases/:id/novel'; params: { id: DatabaseId }; query: NovelDetailsRequest; response: ScrapingServiceResponse<NovelDetails>; }; }; chapters: { scrape: { method: 'POST'; path: '/api/v1/chapters/scrape'; body: ScrapeChapterRequest; response: ScrapingServiceResponse<ChapterData>; }; batch: { method: 'POST'; path: '/api/v1/chapters/batch'; body: BatchScrapeRequest; response: ScrapingServiceResponse<ChapterData[]>; }; validateUrl: { method: 'GET'; path: '/api/v1/chapters/validate-url'; query: ValidateUrlRequest; response: ScrapingServiceResponse<{ supported: boolean; hostname: string }>; }; }; sites: { list: { method: 'GET'; path: '/api/v1/sites'; response: ScrapingServiceResponse<SiteConfiguration[]>; }; get: { method: 'GET'; path: '/api/v1/sites/:hostname'; params: { hostname: string }; response: ScrapingServiceResponse<SiteConfiguration>; }; update: { method: 'PUT'; path: '/api/v1/sites/:hostname'; params: { hostname: string }; body: Partial<SiteConfiguration>; response: ScrapingServiceResponse<SiteConfiguration>; }; test: { method: 'POST'; path: '/api/v1/sites/:hostname/test'; params: { hostname: string }; body: TestSiteConfigRequest; response: ScrapingServiceResponse<{ success: boolean; data?: ChapterData }>; }; }; health: { overall: { method: 'GET'; path: '/api/v1/health'; response: HealthStatus; }; overview: { method: 'GET'; path: '/api/v1/health/overview'; response: HealthOverview; }; proxy: { method: 'GET'; path: '/api/v1/health/proxy'; response: ProxyHealthStatus; }; browser: { method: 'GET'; path: '/api/v1/health/browser'; response: BrowserHealthStatus; }; }; }