UNPKG

@fluentity/core

Version:

Fluentity is a fluent, model-oriented, typed HTTP client for TypeScript and framework agnostic.

419 lines (418 loc) 12.5 kB
import { AdapterOptions, AdapterRequest, AdapterResponse } from '../Fluentity'; import { QueryBuilder } from '../QueryBuilder'; /** * HTTP method constants for use in requests. * Provides type-safe HTTP method names. * * @example * ```typescript * const method: MethodType = Methods.POST; * ``` */ export declare const Methods: { /** HTTP GET method */ readonly GET: "GET"; /** HTTP POST method */ readonly POST: "POST"; /** HTTP PUT method */ readonly PUT: "PUT"; /** HTTP PATCH method */ readonly PATCH: "PATCH"; /** HTTP DELETE method */ readonly DELETE: "DELETE"; /** HTTP HEAD method */ readonly HEAD: "HEAD"; /** HTTP OPTIONS method */ readonly OPTIONS: "OPTIONS"; }; /** * Type representing valid HTTP method names. * Derived from the Methods constant object. */ export type MethodType = keyof typeof Methods; /** * Abstract HTTP adapter class that provides base functionality for HTTP requests. * Implements caching, interceptors, and request/response handling capabilities. * Serves as the foundation for specific HTTP adapters like RestAdapter and GraphqlAdapter. * * Features: * - Built-in response caching with TTL support * - Request and response interceptors * - Error handling and custom error interceptors * - Configurable request handlers * - Automatic JSON body serialization * * @abstract * @class * @implements {AdapterInterface} * @example * ```typescript * class CustomHttpAdapter extends HttpAdapter { * protected async fetchRequestHandler(request: HttpRequest): Promise<HttpResponse> { * // Custom HTTP request implementation * } * } * * const adapter = new CustomHttpAdapter({ * baseUrl: 'https://api.example.com', * cacheOptions: { enabled: true, ttl: 300000 } * }); * ``` */ export declare abstract class HttpAdapter<T extends HttpAdapterOptions> { /** * Internal cache for storing HTTP responses. * Uses WeakMap to avoid memory leaks and automatically clean up cached responses. * @private */ protected _cache: WeakMap<HttpRequest, CacheData>; /** * Configuration options for the HTTP adapter. * Contains all settings for request handling, caching, and interceptors. */ options: HttpAdapterOptions; /** * The current request object being processed. * @private */ private _request; /** * Constructor for the HttpAdapter class. * Initializes the adapter with the provided configuration options. * * @param options - Partial configuration options to merge with existing options * @throws {Error} If baseUrl is not provided * @example * ```typescript * const adapter = new CustomHttpAdapter({ * baseUrl: 'https://api.example.com', * cacheOptions: { enabled: true, ttl: 300000 }, * requestInterceptor: (request) => { * request.options.headers['Authorization'] = 'Bearer token'; * return request; * } * }); * ``` */ constructor(options: Partial<T>); /** * Configures the adapter with new options. * Merges the provided options with existing configuration. * * @param options - Configuration options to apply * @returns The adapter instance for method chaining * @example * ```typescript * adapter.configure({ * baseUrl: 'https://new-api.example.com', * cacheOptions: { enabled: true } * }); * ``` */ configure(options: Partial<T>): this; /** * Gets the current request object. * Provides access to the request being processed. * * @returns The current HttpRequest instance */ get request(): HttpRequest; /** * Clears all cached responses. * Resets the internal cache, forcing all subsequent requests to be made fresh. * * @returns The adapter instance for method chaining * @example * ```typescript * // Clear cache after configuration changes * adapter.configure({ baseUrl: 'https://new-api.example.com' }); * adapter.clearCache(); * ``` */ clearCache(): this; /** * Makes an HTTP request using the adapter's configuration. * Handles caching, interceptors, and error handling automatically. * * @param queryBuilder - The query builder containing request details * @returns A promise that resolves to the response data * @throws {Error} If baseUrl is not configured or if the request fails * @example * ```typescript * const queryBuilder = new QueryBuilder() * .where({ status: 'active' }) * .limit(10); * * const response = await adapter.call(queryBuilder); * console.log(response.data); * ``` */ call(queryBuilder: QueryBuilder<T>): Promise<HttpResponse>; /** * Builds an HTTP request from a query builder. * Abstract method that must be implemented by subclasses to provide * adapter-specific request building logic. * * @param queryBuilder - The query builder containing request details * @returns An HttpRequest instance * @protected * @abstract */ protected buildRequest(queryBuilder: QueryBuilder): HttpRequest; /** * Default request handler that must be implemented by subclasses. * Provides the actual HTTP request implementation for the adapter. * * @param _request - The HTTP request to execute * @returns Promise resolving to an HttpResponse * @protected * @abstract */ protected fetchRequestHandler(_request: HttpRequest): Promise<HttpResponse>; } /** * Configuration options for HTTP adapters. * Extends AdapterOptions with HTTP-specific configuration including caching, * interceptors, and request handling options. * * @interface * @extends {AdapterOptions} * @template T - The type of response data * @example * ```typescript * const options: HttpAdapterOptions = { * baseUrl: 'https://api.example.com', * options: { * headers: { * 'Authorization': 'Bearer token', * 'Content-Type': 'application/json' * } * }, * cacheOptions: { * enabled: true, * ttl: 300000 // 5 minutes * }, * requestInterceptor: (request) => { * // Modify request before sending * return request; * }, * responseInterceptor: (response) => { * // Modify response after receiving * return response; * } * }; * ``` */ export interface HttpAdapterOptions<T = unknown | any> extends AdapterOptions { /** Base URL to prepend to all requests */ baseUrl?: string; /** Default request options to apply to all requests */ options?: HttpRequestOptions; /** Interceptor to modify requests before they are sent */ requestInterceptor?: (request: HttpRequest) => HttpRequest; /** Interceptor to modify responses after they are received */ responseInterceptor?: (response: HttpResponse<T>) => HttpResponse<T>; /** Handler for request errors */ errorInterceptor?: (error: Error) => void; /** Custom request handler function */ requestHandler?: (request: HttpRequest) => Promise<HttpResponse>; /** Cache configuration options */ cacheOptions?: CacheOptions; } /** * Configuration options for response caching. * Controls whether and how responses are cached by the adapter. * * @interface * @example * ```typescript * const cacheOptions: CacheOptions = { * enabled: true, * ttl: 300000 // 5 minutes in milliseconds * }; * ``` */ export interface CacheOptions { /** Whether caching is enabled */ enabled: boolean; /** Time-to-live for cached responses in milliseconds */ ttl?: number; } /** * Interface for HTTP request data. * Defines the structure of HTTP requests used by the adapter. * * @interface * @example * ```typescript * const request: HttpRequestInterface = { * url: '/users/123', * method: 'GET', * body: { name: 'John' }, * options: { * headers: { 'Authorization': 'Bearer token' } * } * }; * ``` */ export interface HttpRequestInterface { /** The full URL to send the request to */ url: string; /** Request options including method, headers, body, etc. */ options?: HttpRequestOptions; /** HTTP method to use */ method?: MethodType; /** Request body data */ body?: string | object | object[] | undefined; } /** * HTTP request class that implements HttpRequestInterface. * Provides a structured way to represent HTTP requests with proper typing. * * @class * @implements {HttpRequestInterface} * @implements {AdapterRequest} * @example * ```typescript * const request = new HttpRequest({ * url: '/users', * method: 'POST', * body: { name: 'John', email: 'john@example.com' }, * options: { * headers: { 'Content-Type': 'application/json' } * } * }); * ``` */ export declare class HttpRequest implements HttpRequestInterface, AdapterRequest { /** The full URL to send the request to */ url: string; /** Request options including headers, credentials, etc. */ options?: HttpRequestOptions; /** HTTP method to use for the request */ method?: MethodType; /** Request body data */ body?: string | any | any[]; /** * Creates a new HttpRequest instance. * * @param options - Partial request configuration * @example * ```typescript * const request = new HttpRequest({ * url: '/users/123', * method: 'GET' * }); * ``` */ constructor(options?: Partial<HttpRequestInterface>); } /** * Interface for HTTP response data. * Defines the structure of HTTP responses returned by the adapter. * * @interface * @example * ```typescript * const response: HttpResponseInterface = { * data: { id: 123, name: 'John' } * }; * ``` */ export interface HttpResponseInterface { /** The response data from the API */ data: any; } /** * HTTP response class that implements HttpResponseInterface. * Provides a structured way to represent HTTP responses with proper typing. * * @class * @implements {HttpResponseInterface} * @implements {AdapterResponse<T>} * @template T - The type of response data * @example * ```typescript * const response = new HttpResponse({ * data: { id: 123, name: 'John' } * }); * * console.log(response.data.name); // 'John' * ``` */ export declare class HttpResponse<T = any> implements HttpResponseInterface, AdapterResponse<T> { /** The response data from the API */ data: T; /** * Creates a new HttpResponse instance. * * @param options - Partial response configuration * @example * ```typescript * const response = new HttpResponse({ * data: { id: 123, name: 'John' } * }); * ``` */ constructor(options?: Partial<HttpResponseInterface>); } /** * Interface for HTTP request options. * Extends AdapterOptions with HTTP-specific request configuration. * * @interface * @extends {AdapterOptions} * @example * ```typescript * const requestOptions: HttpRequestOptions = { * headers: { * 'Authorization': 'Bearer token', * 'Content-Type': 'application/json' * }, * credentials: 'include', * mode: 'cors', * cache: 'default' * }; * ``` */ export interface HttpRequestOptions extends AdapterOptions { /** Request headers */ headers?: Record<string, string>; /** Request credentials mode */ credentials?: RequestCredentials; /** Request mode */ mode?: RequestMode; /** How to handle redirects */ redirect?: RequestRedirect; /** Referrer URL */ referrer?: string; /** Referrer policy */ referrerPolicy?: ReferrerPolicy; /** Subresource integrity value */ integrity?: string; /** Cache mode */ cache?: RequestCache; /** Whether to keep the connection alive */ keepalive?: boolean; /** Abort signal for cancelling the request */ signal?: AbortSignal; } /** * Interface for cached response data. * Represents a cached HTTP response with timestamp information. * * @interface * @example * ```typescript * const cachedData: CacheData = { * data: new HttpResponse({ data: { id: 123 } }), * timestamp: Date.now() * }; * ``` */ export interface CacheData { /** The cached response data */ data: HttpResponse; /** Timestamp when the data was cached (milliseconds since epoch) */ timestamp: number; }