@foundatiofx/fetchclient
Version:
A typed JSON fetch client with middleware support for Deno, Node and the browser.
201 lines (200 loc) • 6.08 kB
JavaScript
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;