UNPKG

@follow-app/client-sdk

Version:

TypeScript client SDK for Follow RSS Server API

172 lines (148 loc) 4.54 kB
import type { ModuleAPIs } from "../modules/registry" import { moduleRegistry } from "../modules/registry" import type { ClientConfig, RequestOptions } from "../types" import { HttpClient } from "./base" import type { ErrorInterceptor, RequestInterceptor, ResponseInterceptor, } from "./interceptors" import { commonInterceptors } from "./interceptors" import { createAPIProxy } from "./proxy" /** * Configuration options for the Follow Client */ export interface FollowClientConfig extends Partial<ClientConfig> { // Additional SDK-specific configuration enableDefaultInterceptors?: boolean authToken?: string } export class FollowClient { private httpClient: HttpClient public api: ModuleAPIs = {} as ModuleAPIs constructor(config: FollowClientConfig = {}) { // Initialize HTTP client with proper defaults this.httpClient = new HttpClient({ baseURL: config.baseURL || "https://api.folo.is", timeout: config.timeout || 30000, headers: config.headers || {}, credentials: config.credentials || "include", fetch: config.fetch || globalThis.fetch.bind(globalThis), }) // Initialize API route groups this.initializeRoutes() // Setup default interceptors if enabled if (config.enableDefaultInterceptors) { this.setupDefaultInterceptors() } // Set auth token if provided if (config.authToken) { this.setAuthToken(config.authToken) } } /** * Initialize API route groups with proper typing */ private initializeRoutes(): void { // Automatically initialize all modules from registry for (const [moduleName, moduleDefinition] of Object.entries( moduleRegistry, )) { (this.api as any)[moduleName] = createAPIProxy(this.httpClient, moduleDefinition) } } /** * Setup default interceptors */ private setupDefaultInterceptors(): void { const interceptors = this.httpClient.getInterceptors() // Add default logging interceptor interceptors.addRequestInterceptor( commonInterceptors.logRequests({ log: console.info }), ) interceptors.addResponseInterceptor( commonInterceptors.logResponses({ log: console.info }), ) } /** * Set authentication token for API requests */ setAuthToken(token: string): void { this.httpClient.setHeaders({ Authorization: `Bearer ${token}` }) } /** * Remove authentication token */ removeAuthToken(): void { const currentHeaders = this.httpClient.getConfig().headers const { Authorization, ...newHeaders } = currentHeaders this.httpClient.setHeaders(newHeaders) } /** * Set custom headers for API requests */ setHeaders(headers: Record<string, string>): void { this.httpClient.setHeaders(headers) } /** * Set custom fetch instance */ setFetch(fetchInstance: typeof fetch): void { this.httpClient.setFetch(fetchInstance) } /** * Update client configuration */ updateConfig(config: Partial<FollowClientConfig>): void { this.httpClient.setConfig(config) } /** * Get current configuration (readonly) */ getConfig(): Readonly<Required<ClientConfig>> { return this.httpClient.getConfig() } /** * Make a custom HTTP request using the underlying HTTP client * This allows direct access to the HTTP client for custom requests */ async request<T>(path: string, options?: RequestOptions): Promise<T> { return this.httpClient.request<T>(path, options) } /** * Batch multiple requests */ async batch<T extends readonly any[]>( requests: readonly [...T], ): Promise<{ [K in keyof T]: Awaited<T[K]> }> { return Promise.all(requests) as any } /** * Create a new instance with different configuration */ clone(config?: Partial<FollowClientConfig>): FollowClient { const currentConfig = this.getConfig() return new FollowClient({ ...currentConfig, ...config, }) } /** * Add request interceptor */ addRequestInterceptor(interceptor: RequestInterceptor): () => void { return this.httpClient.getInterceptors().addRequestInterceptor(interceptor) } /** * Add response interceptor */ addResponseInterceptor(interceptor: ResponseInterceptor): () => void { return this.httpClient.getInterceptors().addResponseInterceptor(interceptor) } /** * Add error interceptor */ addErrorInterceptor(interceptor: ErrorInterceptor): () => void { return this.httpClient.getInterceptors().addErrorInterceptor(interceptor) } }