UNPKG

@segment/analytics-node

Version:

https://www.npmjs.com/package/@segment/analytics-node

107 lines (97 loc) 3.01 kB
import { abortSignalAfterTimeout } from './abort' import { fetch as defaultFetch } from './fetch' /** * This interface is meant to be compatible with different fetch implementations (node and browser). * Using the ambient fetch type is not possible because the AbortSignal type is not compatible with node-fetch. * @link https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API */ export interface HTTPFetchFn { (url: string, requestInit: HTTPFetchRequest): Promise<HTTPResponse> } /** * This interface is meant to be compatible with the Request interface. * @link https://developer.mozilla.org/en-US/docs/Web/API/Request */ export interface HTTPFetchRequest { headers: Record<string, string> body: string method: HTTPClientRequest['method'] signal: any // AbortSignal type does not play nicely with node-fetch } /** * This interface is meant to be compatible with the Headers interface. * @link https://developer.mozilla.org/en-US/docs/Web/API/Headers */ export interface HTTPHeaders { get: (key: string) => string | null has: (key: string) => boolean entries: () => IterableIterator<[string, any]> } /** * This interface is meant to very minimally conform to the Response interface. * @link https://developer.mozilla.org/en-US/docs/Web/API/Response */ export interface HTTPResponse { headers?: Record<string, any> | HTTPHeaders text?: () => Promise<string> status: number statusText: string } /** * This interface is meant to be a generic interface for making HTTP requests. * While it may overlap with fetch's Request interface, it is not coupled to it. */ export interface HTTPClientRequest { /** * URL to be used for the request * @example 'https://api.segment.io/v1/batch' */ url: string /** * HTTP method to be used for the request. This will always be a 'POST' request. **/ method: 'POST' /** * Headers to be sent with the request */ headers: Record<string, string> /** * Data to be sent with the request */ body: string /** * Specifies the timeout (in milliseconds) for an HTTP client to get an HTTP response from the server * @example 10000 */ httpRequestTimeout: number } /** * HTTP client interface for making requests */ export interface HTTPClient { makeRequest(_options: HTTPClientRequest): Promise<HTTPResponse> } /** * Default HTTP client implementation using fetch */ export class FetchHTTPClient implements HTTPClient { private _fetch: HTTPFetchFn constructor(fetchFn?: HTTPFetchFn) { this._fetch = fetchFn ?? defaultFetch } async makeRequest(options: HTTPClientRequest): Promise<HTTPResponse> { const [signal, timeoutId] = abortSignalAfterTimeout( options.httpRequestTimeout ) const requestInit = { url: options.url, method: options.method, headers: options.headers, body: options.body, signal: signal, } return this._fetch(options.url, requestInit).finally(() => clearTimeout(timeoutId) ) } }