UNPKG

@foundatiofx/fetchclient

Version:

A typed JSON fetch client with middleware support for Deno, Node and the browser.

201 lines (200 loc) 6.08 kB
import { FetchClient } from "./FetchClient.js"; import { Counter } from "./Counter.js"; import { FetchClientCache } from "./FetchClientCache.js"; import { ObjectEvent } from "./ObjectEvent.js"; import { RateLimitMiddleware, } from "./RateLimitMiddleware.js"; import { groupByDomain } from "./RateLimiter.js"; /** * Represents a provider for creating instances of the FetchClient class with shared default options and cache. */ export class FetchClientProvider { #options = {}; #fetch; #cache; #rateLimitMiddleware; #counter = new Counter(); #onLoading = new ObjectEvent(); /** * Creates a new instance of FetchClientProvider. * @param fetch - The fetch function to use. If not provided, the global fetch function will be used. */ constructor(fetch) { this.#cache = new FetchClientCache(); if (fetch) { this.#fetch = fetch; } this.#options = { cache: this.#cache, providerCounter: this.#counter, fetch: this.#fetch, }; this.#counter.changed.on((e) => { if (!e) { throw new Error("Event data is required."); } if (e.value > 0 && e.previous == 0) { this.#onLoading.trigger(true); } else if (e.value == 0 && e.previous > 0) { this.#onLoading.trigger(false); } }); } /** * Gets the fetch function used for making requests. */ get fetch() { return this.#fetch; } /** * Sets the fetch function used for making requests. */ set fetch(value) { this.#fetch = value; } /** * Gets a value indicating whether there are ongoing requests. */ get isLoading() { return this.#counter.count > 0; } /** * Gets an event that is triggered when the loading state changes. */ get loading() { return this.#onLoading.expose(); } /** * Gets the number of ongoing requests. */ get requestCount() { return this.#counter.count; } /** * Gets the counter used for tracking ongoing requests. */ get counter() { return this.#counter; } /** * Gets the options used for FetchClient instances. */ get options() { return this.#options; } /** * Sets the options used for FetchClient instances. */ set options(value) { this.#options = value; } /** * Gets the cache used for storing HTTP responses. */ get cache() { return this.#cache; } /** * Creates a new instance of FetchClient using the current provider. * @param options - The options to use for the FetchClient instance. * @returns A new instance of FetchClient. */ getFetchClient(options) { if (options) { options = { ...this.#options, ...options, }; options.provider = this; return new FetchClient(options); } return new FetchClient(this); } /** * Applies the specified options by merging with the current options. */ applyOptions(options) { this.#options = { ...this.#options, ...options, }; } /** * Sets the function used for retrieving the access token. * @param accessTokenFunc - The function that retrieves the access token. */ setAccessTokenFunc(accessTokenFunc) { this.#options = { ...this.#options, accessTokenFunc: accessTokenFunc, }; } /** * Sets the default model validator function for all FetchClient instances created by this provider. * @param validate - The function that validates the model. */ setModelValidator(validate) { this.#options = { ...this.#options, modelValidator: validate, }; } /** * Sets the default base URL for all FetchClient instances created by this provider. * @param url - The URL to set as the default base URL. */ setBaseUrl(url) { this.#options = { ...this.#options, baseUrl: url, }; } /** * Adds a middleware to all FetchClient instances created by this provider. * @param middleware - The middleware function to be added. */ useMiddleware(middleware) { this.#options = { ...this.#options, middleware: [ ...(this.#options.middleware ?? []), middleware, ], }; } /** * Enables rate limiting for all FetchClient instances created by this provider. * @param options - The rate limiting configuration options. */ useRateLimit(options) { this.#rateLimitMiddleware = new RateLimitMiddleware(options); this.useMiddleware(this.#rateLimitMiddleware.middleware()); } /** * Enables rate limiting for all FetchClient instances created by this provider. * @param options - The rate limiting configuration options. */ usePerDomainRateLimit(options) { this.#rateLimitMiddleware = new RateLimitMiddleware({ ...options, getGroupFunc: groupByDomain, }); this.useMiddleware(this.#rateLimitMiddleware.middleware()); } /** * Gets the rate limiter instance used for rate limiting. * @returns The rate limiter instance, or undefined if rate limiting is not enabled. */ get rateLimiter() { return this.#rateLimitMiddleware?.rateLimiter; } /** * Removes the rate limiting middleware from all FetchClient instances created by this provider. */ removeRateLimit() { this.#rateLimitMiddleware = undefined; this.#options.middleware = this.#options.middleware?.filter((m) => !(m instanceof RateLimitMiddleware)); } } const provider = new FetchClientProvider(); export const defaultInstance = provider;