@hyper-fetch/core
Version:
Cache, Queue and Persist your requests no matter if you are online or offline!
956 lines (924 loc) • 79.9 kB
TypeScript
import EventEmitter from 'events';
type NegativeTypes = null | undefined;
type NullableType<T> = T | NegativeTypes;
type NullableKeys<T> = {
[P in keyof T]-?: NullableType<T[P]>;
};
type NonNullableKeys<T> = {
[P in keyof T]-?: NonNullable<T[P]>;
};
type RequiredKeys<T> = {
[P in keyof T]-?: Exclude<T[P], NegativeTypes>;
};
type HttpMethodsType = "GET" | "POST" | "PUT" | "PATCH" | "DELETE";
type HttpStatusType = number;
declare const adapter: AdapterType;
/**
* App manager handles main application states - focus and online. Those two values can answer questions:
* - Is the tab or current view instance focused and visible for user?
* - Is our application online or offline?
* With the app manager it is not a problem to get the valid answer for this question.
*
* @caution
* Make sure to apply valid focus/online handlers for different environments like for example for native mobile applications.
*/
declare class AppManager {
options?: AppManagerOptionsType;
emitter: EventEmitter;
events: {
emitFocus: () => void;
emitBlur: () => void;
emitOnline: () => void;
emitOffline: () => void;
onFocus: (callback: () => void) => VoidFunction;
onBlur: (callback: () => void) => VoidFunction;
onOnline: (callback: () => void) => VoidFunction;
onOffline: (callback: () => void) => VoidFunction;
};
isBrowser: boolean;
isOnline: boolean;
isFocused: boolean;
constructor(options?: AppManagerOptionsType);
private setInitialFocus;
private setInitialOnline;
setFocused: (isFocused: boolean) => void;
setOnline: (isOnline: boolean) => void;
}
type AppManagerOptionsType = {
initiallyFocused?: boolean | (() => boolean | Promise<boolean>);
initiallyOnline?: boolean | (() => boolean | Promise<boolean>);
focusEvent?: (setFocused: (isFocused: boolean) => void) => void;
onlineEvent?: (setOnline: (isOnline: boolean) => void) => void;
};
declare const hasWindow: () => boolean;
declare const hasDocument: () => boolean;
declare const onWindowEvent: <K extends keyof WindowEventMap>(key: K, listener: (this: Window, ev: WindowEventMap[K]) => any, options?: boolean | AddEventListenerOptions | undefined) => void;
declare const onDocumentEvent: <K extends keyof DocumentEventMap>(key: K, listener: (this: Document, ev: DocumentEventMap[K]) => any, options?: boolean | AddEventListenerOptions | undefined) => void;
declare const getAppManagerEvents: (emitter: EventEmitter) => {
emitFocus: () => void;
emitBlur: () => void;
emitOnline: () => void;
emitOffline: () => void;
onFocus: (callback: () => void) => VoidFunction;
onBlur: (callback: () => void) => VoidFunction;
onOnline: (callback: () => void) => VoidFunction;
onOffline: (callback: () => void) => VoidFunction;
};
declare enum AppEvents {
focus = "focus",
blur = "blur",
online = "online",
offline = "offline"
}
declare const appManagerInitialOptions: RequiredKeys<AppManagerOptionsType>;
/**
* **Request Manager** is used to emit `request lifecycle events` like - request start, request end, upload and download progress.
* It is also the place of `request aborting` system, here we store all the keys and controllers that are isolated for each client instance.
*/
declare class RequestManager {
emitter: EventEmitter;
events: {
emitLoading: (queueKey: string, requestId: string, values: RequestLoadingEventType) => void;
emitRequestStart: (queueKey: string, requestId: string, details: RequestEventType<RequestInstance>) => void;
emitResponseStart: (queueKey: string, requestId: string, details: RequestEventType<RequestInstance>) => void;
emitUploadProgress: (queueKey: string, requestId: string, values: ProgressType, details: RequestEventType<RequestInstance>) => void;
emitDownloadProgress: (queueKey: string, requestId: string, values: ProgressType, details: RequestEventType<RequestInstance>) => void;
emitResponse: <Adapter extends AdapterInstance>(cacheKey: string, requestId: string, response: ResponseReturnType<unknown, unknown, Adapter>, details: ResponseDetailsType) => void;
emitAbort: (abortKey: string, requestId: string, request: RequestInstance) => void;
emitRemove: <T extends RequestInstance>(queueKey: string, requestId: string, details: RequestEventType<T>) => void;
onLoading: (queueKey: string, callback: (values: RequestLoadingEventType) => void) => VoidFunction;
onLoadingById: (requestId: string, callback: (values: RequestLoadingEventType) => void) => VoidFunction;
onRequestStart: <T_1 extends RequestInstance>(queueKey: string, callback: (details: RequestEventType<T_1>) => void) => VoidFunction;
onRequestStartById: <T_2 extends RequestInstance>(requestId: string, callback: (details: RequestEventType<T_2>) => void) => VoidFunction;
onResponseStart: <T_3 extends RequestInstance>(queueKey: string, callback: (details: RequestEventType<T_3>) => void) => VoidFunction;
onResponseStartById: <T_4 extends RequestInstance>(requestId: string, callback: (details: RequestEventType<T_4>) => void) => VoidFunction;
onUploadProgress: <T_5 extends RequestInstance = RequestInstance>(queueKey: string, callback: (values: ProgressType, details: RequestEventType<T_5>) => void) => VoidFunction;
onUploadProgressById: <T_6 extends RequestInstance = RequestInstance>(requestId: string, callback: (values: ProgressType, details: RequestEventType<T_6>) => void) => VoidFunction;
onDownloadProgress: <T_7 extends RequestInstance = RequestInstance>(queueKey: string, callback: (values: ProgressType, details: RequestEventType<T_7>) => void) => VoidFunction;
onDownloadProgressById: <T_8 extends RequestInstance = RequestInstance>(requestId: string, callback: (values: ProgressType, details: RequestEventType<T_8>) => void) => VoidFunction;
onResponse: <Response_1, ErrorType, Adapter_1 extends AdapterInstance>(cacheKey: string, callback: (response: ResponseReturnType<Response_1, ErrorType, Adapter_1>, details: ResponseDetailsType) => void) => VoidFunction;
onResponseById: <Response_2, ErrorType_1, Adapter_2 extends AdapterInstance>(requestId: string, callback: (response: ResponseReturnType<Response_2, ErrorType_1, Adapter_2>, details: ResponseDetailsType) => void) => VoidFunction;
onAbort: (abortKey: string, callback: (request: RequestInstance) => void) => VoidFunction;
onAbortById: (requestId: string, callback: (request: RequestInstance) => void) => VoidFunction;
onRemove: <T_9 extends RequestInstance = RequestInstance>(queueKey: string, callback: (details: RequestEventType<T_9>) => void) => VoidFunction;
onRemoveById: <T_10 extends RequestInstance = RequestInstance>(requestId: string, callback: (details: RequestEventType<T_10>) => void) => VoidFunction;
};
abortControllers: Map<string, Map<string, AbortController>>;
addAbortController: (abortKey: string, requestId: string) => void;
getAbortController: (abortKey: string, requestId: string) => AbortController;
removeAbortController: (abortKey: string, requestId: string) => void;
useAbortController: (abortKey: string, requestId: string) => void;
abortByKey: (abortKey: string) => void;
abortByRequestId: (abortKey: string, requestId: string) => void;
abortAll: () => void;
}
declare const getLoadingEventKey: (key: string) => string;
declare const getLoadingIdEventKey: (key: string) => string;
declare const getRemoveEventKey: (key: string) => string;
declare const getRemoveIdEventKey: (key: string) => string;
declare const getAbortEventKey: (key: string) => string;
declare const getAbortByIdEventKey: (key: string) => string;
declare const getResponseEventKey: (key: string) => string;
declare const getResponseIdEventKey: (key: string) => string;
declare const getRequestStartEventKey: (key: string) => string;
declare const getRequestStartIdEventKey: (key: string) => string;
declare const getResponseStartEventKey: (key: string) => string;
declare const getResponseStartIdEventKey: (key: string) => string;
declare const getUploadProgressEventKey: (key: string) => string;
declare const getUploadProgressIdEventKey: (key: string) => string;
declare const getDownloadProgressEventKey: (key: string) => string;
declare const getDownloadProgressIdEventKey: (key: string) => string;
declare const getRequestManagerEvents: (emitter: EventEmitter) => {
/**
* Emiter
*/
emitLoading: (queueKey: string, requestId: string, values: RequestLoadingEventType) => void;
emitRequestStart: (queueKey: string, requestId: string, details: RequestEventType<RequestInstance>) => void;
emitResponseStart: (queueKey: string, requestId: string, details: RequestEventType<RequestInstance>) => void;
emitUploadProgress: (queueKey: string, requestId: string, values: ProgressType, details: RequestEventType<RequestInstance>) => void;
emitDownloadProgress: (queueKey: string, requestId: string, values: ProgressType, details: RequestEventType<RequestInstance>) => void;
emitResponse: <Adapter extends AdapterInstance>(cacheKey: string, requestId: string, response: ResponseReturnType<unknown, unknown, Adapter>, details: ResponseDetailsType) => void;
emitAbort: (abortKey: string, requestId: string, request: RequestInstance) => void;
emitRemove: <T extends RequestInstance>(queueKey: string, requestId: string, details: RequestEventType<T>) => void;
/**
* Listeners
*/
onLoading: (queueKey: string, callback: (values: RequestLoadingEventType) => void) => VoidFunction;
onLoadingById: (requestId: string, callback: (values: RequestLoadingEventType) => void) => VoidFunction;
onRequestStart: <T_1 extends RequestInstance>(queueKey: string, callback: (details: RequestEventType<T_1>) => void) => VoidFunction;
onRequestStartById: <T_2 extends RequestInstance>(requestId: string, callback: (details: RequestEventType<T_2>) => void) => VoidFunction;
onResponseStart: <T_3 extends RequestInstance>(queueKey: string, callback: (details: RequestEventType<T_3>) => void) => VoidFunction;
onResponseStartById: <T_4 extends RequestInstance>(requestId: string, callback: (details: RequestEventType<T_4>) => void) => VoidFunction;
onUploadProgress: <T_5 extends RequestInstance = RequestInstance>(queueKey: string, callback: (values: ProgressType, details: RequestEventType<T_5>) => void) => VoidFunction;
onUploadProgressById: <T_6 extends RequestInstance = RequestInstance>(requestId: string, callback: (values: ProgressType, details: RequestEventType<T_6>) => void) => VoidFunction;
onDownloadProgress: <T_7 extends RequestInstance = RequestInstance>(queueKey: string, callback: (values: ProgressType, details: RequestEventType<T_7>) => void) => VoidFunction;
onDownloadProgressById: <T_8 extends RequestInstance = RequestInstance>(requestId: string, callback: (values: ProgressType, details: RequestEventType<T_8>) => void) => VoidFunction;
onResponse: <Response_1, ErrorType, Adapter_1 extends AdapterInstance>(cacheKey: string, callback: (response: ResponseReturnType<Response_1, ErrorType, Adapter_1>, details: ResponseDetailsType) => void) => VoidFunction;
onResponseById: <Response_2, ErrorType_1, Adapter_2 extends AdapterInstance>(requestId: string, callback: (response: ResponseReturnType<Response_2, ErrorType_1, Adapter_2>, details: ResponseDetailsType) => void) => VoidFunction;
onAbort: (abortKey: string, callback: (request: RequestInstance) => void) => VoidFunction;
onAbortById: (requestId: string, callback: (request: RequestInstance) => void) => VoidFunction;
onRemove: <T_9 extends RequestInstance = RequestInstance>(queueKey: string, callback: (details: RequestEventType<T_9>) => void) => VoidFunction;
onRemoveById: <T_10 extends RequestInstance = RequestInstance>(requestId: string, callback: (details: RequestEventType<T_10>) => void) => VoidFunction;
};
type RequestLoadingEventType = {
queueKey: string;
requestId: string;
loading: boolean;
isRetry: boolean;
isOffline: boolean;
};
type RequestEventType<T extends RequestInstance> = {
requestId: string;
request: T;
};
type ResponseDetailsType = {
retries: number;
timestamp: number;
isCanceled: boolean;
isOffline: boolean;
};
type RequestRemoveDataType = {
queueKey: string;
requestId: string;
};
/**
* This class is used across the Hyper Fetch library to provide unified logging system with necessary setup per each client.
* We can set up the logging level based on available values. This manager enable to initialize the logging instance per individual module
* like Client, Request etc. Which can give you better feedback on the logging itself.
*/
declare class LoggerManager {
private client;
private options?;
logger: LoggerFunctionType;
severity: SeverityType;
emitter: EventEmitter;
constructor(client: Pick<ClientInstance, "debug">, options?: LoggerOptionsType);
setSeverity: (severity: SeverityType) => void;
init: (module: string) => LoggerType;
}
declare const getTime: () => string;
declare const logger: LoggerFunctionType;
type SeverityType = 0 | 1 | 2 | 3;
type LoggerType = Record<LoggerLevelType, (message: LoggerMessageType, ...extra: LoggerMessageType[]) => void>;
type LoggerFunctionType = (log: LogType) => void;
type LoggerOptionsType = {
logger?: LoggerFunctionType;
severity?: SeverityType;
};
type LogType = {
module: string;
level: LoggerLevelType;
message: LoggerMessageType;
extra?: LoggerMessageType[];
enabled: boolean;
severity: SeverityType;
};
type LoggerLevelType = "error" | "warning" | "info" | "debug";
type LoggerMessageType = string | Record<string, unknown> | Array<unknown>;
type LoggerRequestEventData = {
requestId: string;
request: RequestInstance;
};
type LoggerResponseEventData<Adapter extends AdapterInstance> = {
requestId: string;
request: RequestInstance;
response: ResponseReturnType<unknown, unknown, Adapter>;
details: ResponseDetailsType;
};
declare const loggerStyles: Record<LoggerLevelType, string>;
declare const loggerIconLevels: Record<LoggerLevelType, string>;
declare const severity: Record<LoggerLevelType, number>;
/**
* Cache class handles the data exchange with the dispatchers.
*
* @note
* Keys used to save the values are created dynamically on the Request class
*
*/
declare class Cache<C extends ClientInstance> {
client: C;
options?: CacheOptionsType;
emitter: EventEmitter;
events: ReturnType<typeof getCacheEvents>;
storage: CacheStorageType;
lazyStorage?: CacheAsyncStorageType;
clearKey: string;
garbageCollectors: Map<string, NodeJS.Timeout>;
private logger;
constructor(client: C, options?: CacheOptionsType);
/**
* Set the cache data to the storage
* @param request
* @param response
* @returns
*/
set: <Request_1 extends RequestInstance>(request: RequestInstance | RequestJSON<any>, response: CacheMethodType<ResponseReturnType<ExtractResponseType<Request_1>, ExtractErrorType<Request_1>, ExtractAdapterType<Request_1>> & ResponseDetailsType>) => void;
/**
* Update the cache data with partial response data
* @param request
* @param partialResponse
* @returns
*/
update: <Request_1 extends RequestInstance>(request: RequestInstance | RequestJSON<RequestInstance>, partialResponse: CacheMethodType<Partial<ResponseReturnType<ExtractResponseType<Request_1>, ExtractErrorType<Request_1>, ExtractAdapterType<Request_1>> & ResponseDetailsType>>) => void;
/**
* Get particular record from storage by cacheKey. It will trigger lazyStorage to emit lazy load event for reading it's data.
* @param cacheKey
* @returns
*/
get: <Response_1, Error_1, Adapter extends AdapterInstance>(cacheKey: string) => CacheValueType<Response_1, Error_1, Adapter>;
/**
* Get sync storage keys, lazyStorage keys will not be included
* @returns
*/
keys: () => string[];
/**
* Delete record from storages and trigger invalidation event
* @param cacheKey
*/
delete: (cacheKey: string) => void;
/**
* Invalidate cache by cacheKey or partial matching with RegExp
* @param cacheKey
*/
invalidate: (cacheKey: string | RegExp) => Promise<void>;
/**
* Used to receive data from lazy storage
* @param cacheKey
*/
getLazyResource: <Response_1, Error_1, Adapter extends AdapterInstance>(cacheKey: string) => Promise<CacheValueType<Response_1, Error_1, Adapter>>;
/**
* Used to receive keys from sync storage and lazy storage
* @param cacheKey
*/
getLazyKeys: () => Promise<string[]>;
/**
* Schedule garbage collection for given key
* @param cacheKey
* @returns
*/
scheduleGarbageCollector: (cacheKey: string) => Promise<void>;
/**
* Clear cache storages
*/
clear: () => Promise<void>;
}
type CacheOptionsType<C extends ClientInstance = ClientInstance> = {
/**
* Assign your custom sync storage
*/
storage?: CacheStorageType;
/**
* Lazy loading from remote resources - possibly persistent
*/
lazyStorage?: CacheAsyncStorageType;
/**
* Key to clear lazy storage data
*/
clearKey?: string;
/**
* Initialization callback
*/
onInitialization?: (cache: Cache<C>) => void;
/**
* Callback for every change in the storage
*/
onChange?: <Response = any, Error = any, Adapter extends AdapterInstance = AdapterInstance>(key: string, data: CacheValueType<Response, Error, Adapter>) => void;
/**
* Callback for every delete in the storage
*/
onDelete?: (key: string) => void;
};
type CacheValueType<Response = any, Error = any, Adapter extends AdapterInstance = AdapterInstance> = ResponseReturnType<Response, Error, Adapter> & ResponseDetailsType & {
cacheTime: number;
clearKey: string;
garbageCollection: number;
};
type CacheAsyncStorageType = {
set: <Response, Error, Adapter extends AdapterInstance>(key: string, data: CacheValueType<Response, Error, Adapter>) => Promise<void>;
get: <Response, Error, Adapter extends AdapterInstance>(key: string) => Promise<CacheValueType<Response, Error, Adapter> | undefined>;
keys: () => Promise<string[] | IterableIterator<string> | string[]>;
delete: (key: string) => Promise<void>;
};
type CacheStorageType = {
set: <Response, Error, Adapter extends AdapterInstance>(key: string, data: CacheValueType<Response, Error, Adapter>) => void;
get: <Response, Error, Adapter extends AdapterInstance>(key: string) => CacheValueType<Response, Error, Adapter> | undefined;
keys: () => string[] | IterableIterator<string> | string[];
delete: (key: string) => void;
clear: () => void;
};
type CacheInitialData = Record<string, CacheValueType>;
type CacheMethodType<CacheData> = CacheData | ((previousData: CacheData | null) => CacheData);
declare const getCacheData: <T extends RequestInstance>(previousResponse: ExtractAdapterReturnType<T>, response: ExtractAdapterReturnType<T> & ResponseDetailsType) => ExtractAdapterReturnType<T> & ResponseDetailsType;
declare const getInvalidateEventKey: (key: string) => string;
declare const getCacheKey: (key: string) => string;
declare const getCacheIdKey: (key: string) => string;
declare const getCacheEvents: (emitter: EventEmitter) => {
/**
* Set cache data
* @param cacheKey
* @param data
*/
emitCacheData: <Response_1, Error_1, Adapter extends AdapterInstance>(cacheKey: string, data: CacheValueType<Response_1, Error_1, Adapter>) => void;
/**
* Invalidate cache values event
*/
emitInvalidation: (cacheKey: string) => void;
/** StatusType
* Cache data listener
* @param cacheKey
* @param callback
* @returns
*/
onData: <Response_2, Error_2, Adapter_1 extends AdapterInstance>(cacheKey: string, callback: (data: CacheValueType<Response_2, Error_2, Adapter_1>) => void) => VoidFunction;
/**
* Cache invalidation listener
* @param cacheKey
* @param callback
* @returns
*/
onInvalidate: (cacheKey: string, callback: () => void) => VoidFunction;
};
declare enum DispatcherRequestType {
oneByOne = "one-by-one",
allAtOnce = "all-at-once",
previousCanceled = "previous-canceled",
deduplicated = "deduplicated"
}
declare const getDispatcherEvents: (emitter: EventEmitter) => {
setDrained: <Request_1 extends RequestInstance>(queueKey: string, values: QueueDataType<Request_1>) => void;
setQueueStatus: <Request_2 extends RequestInstance>(queueKey: string, values: QueueDataType<Request_2>) => void;
setQueueChanged: <Request_3 extends RequestInstance>(queueKey: string, values: QueueDataType<Request_3>) => void;
onDrained: <Request_4 extends RequestInstance>(queueKey: string, callback: (values: QueueDataType<Request_4>) => void) => VoidFunction;
onQueueStatus: <Request_5 extends RequestInstance>(queueKey: string, callback: (values: QueueDataType<Request_5>) => void) => VoidFunction;
onQueueChange: <Request_6 extends RequestInstance>(queueKey: string, callback: (values: QueueDataType<Request_6>) => void) => VoidFunction;
};
/**
* Dispatcher class was made to store controlled request Fetches, and firing them all-at-once or one-by-one in request queue.
* Generally requests should be flushed at the same time, the queue provide mechanism to fire them in the order.
*/
declare class Dispatcher {
client: ClientInstance;
options?: DispatcherOptionsType;
emitter: EventEmitter;
events: {
setDrained: <Request_1 extends RequestInstance>(queueKey: string, values: QueueDataType<Request_1>) => void;
setQueueStatus: <Request_2 extends RequestInstance>(queueKey: string, values: QueueDataType<Request_2>) => void;
setQueueChanged: <Request_3 extends RequestInstance>(queueKey: string, values: QueueDataType<Request_3>) => void;
onDrained: <Request_4 extends RequestInstance>(queueKey: string, callback: (values: QueueDataType<Request_4>) => void) => VoidFunction;
onQueueStatus: <Request_5 extends RequestInstance>(queueKey: string, callback: (values: QueueDataType<Request_5>) => void) => VoidFunction;
onQueueChange: <Request_6 extends RequestInstance>(queueKey: string, callback: (values: QueueDataType<Request_6>) => void) => VoidFunction;
};
storage: DispatcherStorageType;
private requestCount;
private runningRequests;
private logger;
constructor(client: ClientInstance, options?: DispatcherOptionsType);
/**
* Start request handling by queueKey
*/
start: (queueKey: string) => void;
/**
* Pause request queue, but not cancel already started requests
*/
pause: (queueKey: string) => void;
/**
* Stop request queue and cancel all started requests - those will be treated like not started
*/
stop: (queueKey: string) => void;
/**
* Return all
*/
getQueuesKeys: () => string[];
/**
* Return queue state object
*/
getQueue: <Request_1 extends RequestInstance = RequestInstance>(queueKey: string) => QueueDataType<Request_1>;
/**
* Return request from queue state
*/
getRequest: <Request_1 extends RequestInstance = RequestInstance>(queueKey: string, requestId: string) => QueueElementType<Request_1>;
/**
* Get value of the active queue status based on the stopped status
*/
getIsActiveQueue: (queueKey: string) => boolean;
/**
* Add new element to storage
*/
addQueueElement: <Request_1 extends RequestInstance = RequestInstance>(queueKey: string, dispatcherDump: QueueElementType<Request_1>) => void;
/**
* Set new queue storage value
*/
setQueue: <Request_1 extends RequestInstance = RequestInstance>(queueKey: string, queue: QueueDataType<Request_1>) => QueueDataType<Request_1>;
/**
* Clear requests from queue cache
*/
clearQueue: (queueKey: string) => {
requests: any[];
stopped: boolean;
};
/**
* Method used to flush the queue requests
*/
flushQueue: (queueKey: string) => Promise<void>;
/**
* Flush all available requests from all queues
*/
flush: () => Promise<void>;
/**
* Clear all running requests and storage
*/
clear: () => void;
/**
* Start particular request
*/
startRequest: (queueKey: string, requestId: string) => void;
/**
* Stop particular request
*/
stopRequest: (queueKey: string, requestId: string) => void;
/**
* Get currently running requests from all queueKeys
*/
getAllRunningRequest: () => RunningRequestValueType[];
/**
* Get currently running requests
*/
getRunningRequests: (queueKey: string) => RunningRequestValueType[];
/**
* Get running request by id
*/
getRunningRequest: (queueKey: string, requestId: string) => RunningRequestValueType;
/**
* Add request to the running requests list
*/
addRunningRequest: (queueKey: string, requestId: string, request: RequestInstance) => void;
/**
* Get the value based on the currently running requests
*/
hasRunningRequests: (queueKey: string) => boolean;
/**
* Check if request is currently processing
*/
hasRunningRequest: (queueKey: string, requestId: string) => boolean;
/**
* Cancel all started requests, but do NOT remove it from main storage
*/
cancelRunningRequests: (queueKey: string) => void;
/**
* Cancel started request, but do NOT remove it from main storage
*/
cancelRunningRequest: (queueKey: string, requestId: string) => void;
/**
* Delete all started requests, but do NOT clear it from queue and do NOT cancel them
*/
deleteRunningRequests: (queueKey: string) => void;
/**
* Delete request by id, but do NOT clear it from queue and do NOT cancel them
*/
deleteRunningRequest: (queueKey: string, requestId: string) => void;
/**
* Get count of requests from the same queueKey
*/
getQueueRequestCount: (queueKey: string) => number;
/**
* Add request count to the queueKey
*/
incrementQueueRequestCount: (queueKey: string) => void;
/**
* Create storage element from request
*/
createStorageElement: <Request_1 extends RequestInstance>(request: Request_1) => QueueElementType<Request_1>;
/**
* Add request to the dispatcher handler
*/
add: (request: RequestInstance) => string;
/**
* Delete from the storage and cancel request
*/
delete: (queueKey: string, requestId: string, abortKey: string) => QueueDataType<RequestInstance>;
/**
* Request can run for some time, once it's done, we have to check if it's successful or if it was aborted
* It can be different once the previous call was set as cancelled and removed from queue before this request got resolved
*/
performRequest: (storageElement: QueueElementType) => Promise<void | QueueDataType<RequestInstance>>;
}
type DispatcherOptionsType = {
storage?: DispatcherStorageType;
onInitialization?: (dispatcherInstance: Dispatcher) => void;
onUpdateStorage?: <Request extends RequestInstance>(queueKey: string, data: QueueDataType<Request>) => void;
onDeleteFromStorage?: <Request extends RequestInstance>(queueKey: string, data: QueueDataType<Request>) => void;
onClearStorage?: (dispatcherInstance: Dispatcher) => void;
};
type QueueElementType<Request extends RequestInstance = RequestInstance> = {
requestId: string;
request: Request;
retries: number;
timestamp: number;
stopped: boolean;
};
type QueueDataType<Request extends RequestInstance = RequestInstance> = {
requests: QueueElementType<Request>[];
stopped: boolean;
};
type DispatcherStorageType = {
set: <Request extends RequestInstance = RequestInstance>(key: string, data: QueueDataType<Request>) => void;
get: <Request extends RequestInstance = RequestInstance>(key: string) => QueueDataType<Request> | undefined;
keys: () => string[] | IterableIterator<string>;
delete: (key: string) => void;
clear: () => void;
};
type RunningRequestValueType = {
requestId: string;
request: RequestInstance;
timestamp: number;
};
declare const getDispatcherDrainedEventKey: (key: string) => string;
declare const getDispatcherStatusEventKey: (key: string) => string;
declare const getDispatcherChangeEventKey: (key: string) => string;
declare const getIsEqualTimestamp: (currentTimestamp: number, threshold: number, queueTimestamp?: number) => boolean;
declare const canRetryRequest: (currentRetries: number, retry: number | undefined) => boolean;
declare const getRequestType: (request: RequestInstance, latestRequest: QueueElementType | undefined) => DispatcherRequestType;
/**
* **Client** is a class that allows you to configure the connection with the server and then use it to create
* requests which, when called using the appropriate method, will cause the server to be queried for the endpoint and
* method specified in the request.
*/
declare class Client<GlobalErrorType extends ClientErrorType = Error, Adapter extends AdapterInstance = AdapterType, EndpointMapper extends DefaultEndpointMapper = DefaultEndpointMapper> {
options: ClientOptionsType<Client<GlobalErrorType, Adapter, EndpointMapper>>;
readonly url: string;
debug: boolean;
__onErrorCallbacks: ResponseInterceptorType[];
__onSuccessCallbacks: ResponseInterceptorType[];
__onResponseCallbacks: ResponseInterceptorType[];
__onAuthCallbacks: RequestInterceptorType[];
__onRequestCallbacks: RequestInterceptorType[];
requestManager: RequestManager;
appManager: AppManager;
loggerManager: LoggerManager;
adapter: Adapter;
cache: Cache<this>;
fetchDispatcher: Dispatcher;
submitDispatcher: Dispatcher;
defaultMethod: ExtractAdapterMethodType<Adapter>;
defaultExtra: ExtractAdapterExtraType<Adapter>;
isMockEnabled: boolean;
effects: RequestEffectInstance[];
queryParamsConfig?: QueryStringifyOptionsType;
adapterDefaultOptions?: (request: RequestInstance) => ExtractAdapterOptionsType<Adapter>;
requestDefaultOptions?: (options: RequestOptionsType<string, ExtractAdapterOptionsType<Adapter>, ExtractAdapterMethodType<Adapter>>) => Partial<RequestOptionsType<string, ExtractAdapterOptionsType<Adapter>, ExtractAdapterMethodType<Adapter>>>;
abortKeyMapper?: (request: RequestInstance) => string;
cacheKeyMapper?: (request: RequestInstance) => string;
queueKeyMapper?: (request: RequestInstance) => string;
effectKeyMapper?: (request: RequestInstance) => string;
/**
* Method to stringify query params from objects.
*/
stringifyQueryParams: StringifyCallbackType;
/**
* Method to get default headers and to map them based on the data format exchange, by default it handles FormData / JSON formats.
*/
headerMapper: HeaderMappingType;
/**
* Method to get request data and transform them to the required format. It handles FormData and JSON by default.
*/
payloadMapper: AdapterPayloadMappingType;
/**
* Method to get request data and transform them to the required format. It handles FormData and JSON by default.
*/
endpointMapper: EndpointMapper;
logger: LoggerType;
constructor(options: ClientOptionsType<Client<GlobalErrorType, Adapter, EndpointMapper>>);
/**
* This method allows to configure global defaults for the request configuration like method, auth, deduplication etc.
*/
setRequestDefaultOptions: (callback: (request: RequestInstance) => Partial<RequestOptionsType<string, ExtractAdapterOptionsType<Adapter>, ExtractAdapterMethodType<Adapter>>>) => Client<GlobalErrorType, Adapter, EndpointMapper>;
setAdapterDefaultOptions: (callback: (request: RequestInstance) => ExtractAdapterOptionsType<Adapter>) => Client<GlobalErrorType, Adapter, EndpointMapper>;
/**
* This method enables the logger usage and display the logs in console
*/
setDebug: (debug: boolean) => Client<GlobalErrorType, Adapter, EndpointMapper>;
/**
* Set the logger severity of the messages displayed to the console
*/
setLoggerSeverity: (severity: SeverityType) => Client<GlobalErrorType, Adapter, EndpointMapper>;
/**
* Set the new logger instance to the Client
*/
setLogger: (callback: (Client: ClientInstance) => LoggerManager) => Client<GlobalErrorType, Adapter, EndpointMapper>;
/**
* Set config for the query params stringify method, we can set here, among others, arrayFormat, skipNull, encode, skipEmptyString and more
*/
setQueryParamsConfig: (queryParamsConfig: QueryStringifyOptionsType) => Client<GlobalErrorType, Adapter, EndpointMapper>;
/**
* Set the custom query params stringify method to the Client
* @param stringifyFn Custom callback handling query params stringify
*/
setStringifyQueryParams: (stringifyFn: StringifyCallbackType) => Client<GlobalErrorType, Adapter, EndpointMapper>;
/**
* Set the custom header mapping function
*/
setHeaderMapper: (headerMapper: HeaderMappingType) => Client<GlobalErrorType, Adapter, EndpointMapper>;
/**
* Set the request payload mapping function which get triggered before request get send
*/
setPayloadMapper: (payloadMapper: AdapterPayloadMappingType) => Client<GlobalErrorType, Adapter, EndpointMapper>;
/**
* Set globally if mocking should be enabled or disabled for all client requests.
* @param isMockEnabled
*/
setEnableGlobalMocking: (isMockEnabled: boolean) => this;
/**
* Set the request payload mapping function which get triggered before request get send
*/
setEndpointMapper: <NewEndpointMapper extends DefaultEndpointMapper>(endpointMapper: NewEndpointMapper) => Client<GlobalErrorType, Adapter, NewEndpointMapper>;
/**
* Set custom http adapter to handle graphql, rest, firebase or others
*/
setAdapter: <NewAdapter extends AdapterInstance, Returns extends AdapterInstance | ClientInstance>(callback: (client: this) => Returns extends AdapterInstance ? NewAdapter : Client<GlobalErrorType, NewAdapter, EndpointMapper>) => Client<GlobalErrorType, Returns extends AdapterInstance ? NewAdapter : ExtractAdapterType<NewAdapter>, EndpointMapper>;
/**
* Set default method for requests.
*/
setDefaultMethod: (defaultMethod: ExtractAdapterMethodType<Adapter>) => ClientInstance;
/**
* Set default additional data for initial state.
*/
setDefaultExtra: (defaultExtra: ExtractAdapterExtraType<Adapter>) => ClientInstance;
/**
* Method of manipulating requests before sending the request. We can for example add custom header with token to the request which request had the auth set to true.
*/
onAuth: (callback: RequestInterceptorType) => Client<GlobalErrorType, Adapter, EndpointMapper>;
/**
* Method for removing listeners on auth.
* */
removeOnAuthInterceptors: (callbacks: RequestInterceptorType[]) => Client<GlobalErrorType, Adapter, EndpointMapper>;
/**
* Method for intercepting error responses. It can be used for example to refresh tokens.
*/
onError: <ErrorType = null>(callback: ResponseInterceptorType<any, GlobalErrorType | ErrorType, Adapter>) => Client<GlobalErrorType, Adapter, EndpointMapper>;
/**
* Method for removing listeners on error.
* */
removeOnErrorInterceptors: (callbacks: ResponseInterceptorType<any, null | GlobalErrorType, Adapter>[]) => Client<GlobalErrorType, Adapter, EndpointMapper>;
/**
* Method for intercepting success responses.
*/
onSuccess: <ErrorType = null>(callback: ResponseInterceptorType<any, GlobalErrorType | ErrorType, Adapter>) => Client<GlobalErrorType, Adapter, EndpointMapper>;
/**
* Method for removing listeners on success.
* */
removeOnSuccessInterceptors: (callbacks: ResponseInterceptorType<any, null | GlobalErrorType, Adapter>[]) => Client<GlobalErrorType, Adapter, EndpointMapper>;
/**
* Method of manipulating requests before sending the request.
*/
onRequest: (callback: RequestInterceptorType) => Client<GlobalErrorType, Adapter, EndpointMapper>;
/**
* Method for removing listeners on request.
* */
removeOnRequestInterceptors: (callbacks: RequestInterceptorType[]) => Client<GlobalErrorType, Adapter, EndpointMapper>;
/**
* Method for intercepting any responses.
*/
onResponse: <ErrorType = null>(callback: ResponseInterceptorType<any, GlobalErrorType | ErrorType, Adapter>) => Client<GlobalErrorType, Adapter, EndpointMapper>;
/**
* Method for removing listeners on request.
* */
removeOnResponseInterceptors: (callbacks: ResponseInterceptorType<any, null | GlobalErrorType, Adapter>[]) => Client<GlobalErrorType, Adapter, EndpointMapper>;
/**
* Add persistent effects which trigger on the request lifecycle
*/
addEffect: (effect: RequestEffectInstance | RequestEffectInstance[]) => this;
/**
* Remove effects from Client
*/
removeEffect: (effect: RequestEffectInstance | string) => this;
/**
* Key setters
*/
setAbortKeyMapper: (callback: (request: RequestInstance) => string) => void;
setCacheKeyMapper: (callback: (request: RequestInstance) => string) => void;
setQueueKeyMapper: (callback: (request: RequestInstance) => string) => void;
setEffectKeyMapper: (callback: (request: RequestInstance) => string) => void;
/**
* Helper used by http adapter to apply the modifications on response error
*/
__modifyAuth: (request: RequestInstance) => Promise<RequestInstance>;
/**
* Private helper to run async pre-request processing
*/
__modifyRequest: (request: RequestInstance) => Promise<RequestInstance>;
/**
* Private helper to run async on-error response processing
*/
__modifyErrorResponse: (response: ResponseReturnType<any, GlobalErrorType, Adapter>, request: RequestInstance) => Promise<ResponseReturnType<any, GlobalErrorType, Adapter>>;
/**
* Private helper to run async on-success response processing
*/
__modifySuccessResponse: (response: ResponseReturnType<any, GlobalErrorType, Adapter>, request: RequestInstance) => Promise<ResponseReturnType<any, GlobalErrorType, Adapter>>;
/**
* Private helper to run async response processing
*/
__modifyResponse: (response: ResponseReturnType<any, GlobalErrorType, Adapter>, request: RequestInstance) => Promise<ResponseReturnType<any, GlobalErrorType, Adapter>>;
/**
* Clears the Client instance and remove all listeners on it's dependencies
*/
clear: () => void;
/**
* Create requests based on the Client setup
*/
createRequest: <Response_1, Payload = undefined, LocalError = undefined, QueryParams = ExtractAdapterQueryParamsType<Adapter>>() => <EndpointType extends ExtractAdapterEndpointType<Adapter>, AdapterOptions extends ExtractAdapterOptionsType<Adapter>, MethodType extends ExtractAdapterMethodType<Adapter>>(params: RequestOptionsType<EndpointType, AdapterOptions, MethodType>) => Request<Response_1, Payload, QueryParams, GlobalErrorType, LocalError, EndpointType extends string ? EndpointType : string, ExtractUnionAdapter<Adapter, {
method: MethodType;
options: AdapterOptions;
queryParams: QueryParams;
}> extends null ? Adapter : ExtractUnionAdapter<Adapter, {
method: MethodType;
options: AdapterOptions;
queryParams: QueryParams;
}>, false, false, false>;
}
type ClientErrorType = Record<string, any> | string;
type ClientInstance = Client<any, AdapterType<any, any, any, any>>;
type ExtractAdapterTypeFromClient<T> = T extends Client<any, infer A> ? A : never;
/**
* Configuration setup for the client
*/
type ClientOptionsType<C extends ClientInstance> = {
/**
* Url to your server
*/
url: string;
/**
* Custom adapter initialization prop
*/
adapter?: AdapterType;
/**
* Custom cache initialization prop
*/
cache?: (client: C) => C["cache"];
/**
* Custom app manager initialization prop
*/
appManager?: (client: C) => C["appManager"];
/**
* Custom fetch dispatcher initialization prop
*/
fetchDispatcher?: (client: C) => C["submitDispatcher"];
/**
* Custom submit dispatcher initialization prop
*/
submitDispatcher?: (client: C) => C["fetchDispatcher"];
};
type RequestInterceptorType = (request: RequestInstance) => Promise<RequestInstance> | RequestInstance;
type ResponseInterceptorType<Response = any, Error = any, Adapter extends AdapterInstance = AdapterType> = (response: ResponseReturnType<Response, Error, Adapter>, request: RequestInstance) => Promise<ResponseReturnType<any, any, Adapter>> | ResponseReturnType<any, any, Adapter>;
type StringifyCallbackType = (queryParams: QueryParamsType | string | NegativeTypes) => string;
type DefaultEndpointMapper = (endpoint: any) => string;
declare const stringifyValue: (response: string | unknown) => string;
declare const interceptRequest: (interceptors: RequestInterceptorType[], request: RequestInstance) => Promise<RequestInstance>;
declare const interceptResponse: <GlobalErrorType, Adapter extends AdapterInstance>(interceptors: ResponseInterceptorType[], response: ResponseReturnType<any, GlobalErrorType, Adapter>, request: RequestInstance) => Promise<ResponseReturnType<any, GlobalErrorType, Adapter>>;
declare const getAdapterHeaders: (request: RequestInstance) => HeadersInit;
declare const getAdapterPayload: (data: unknown) => string | FormData;
declare const stringifyQueryParams: (queryParams: QueryParamsType | string | NegativeTypes, options?: QueryStringifyOptionsType) => string;
declare const stringifyDefaultOptions: {
readonly strict: true;
readonly encode: true;
readonly arrayFormat: "bracket";
readonly arraySeparator: "bracket";
readonly sort: false;
readonly skipNull: true;
readonly skipEmptyString: true;
};
declare const mocker: <T extends AdapterInstance = AdapterType<Partial<XMLHttpRequest>, HttpMethodsType, number, AdapterExtraType, string | QueryParamsType, string>>(request: RequestInstance, { onError, onResponseEnd, onTimeoutError, onRequestEnd, createAbortListener, onResponseProgress, onRequestProgress, onResponseStart, onBeforeRequest, onRequestStart, onSuccess, }: Pick<{
fullUrl: string;
data: any;
headers: HeadersInit;
payload: any;
config: ExtractAdapterOptionsType<T>;
getAbortController: () => AbortController;
getRequestStartTimestamp: () => number;
getResponseStartTimestamp: () => number;
createAbortListener: (status: ExtractAdapterStatusType<T>, abortExtra: ExtractAdapterExtraType<T>, callback: () => void, resolve: (value: ResponseReturnErrorType<ExtractErrorType<T>, T>) => void) => () => void;
onBeforeRequest: () => void;
onRequestStart: (progress?: ProgressDataType) => number;
onRequestProgress: (progress: ProgressDataType) => number;
onRequestEnd: () => number;
onResponseStart: (progress?: ProgressDataType) => number;
onResponseProgress: (progress: ProgressDataType) => number;
onResponseEnd: () => number;
onSuccess: (responseData: any, status: ExtractAdapterStatusType<T>, extra: ExtractAdapterExtraType<T>, resolve: (value: ResponseReturnErrorType<any, T>) => void) => Promise<ResponseReturnSuccessType<ExtractResponseType<T>, T>>;
onAbortError: (status: ExtractAdapterStatusType<T>, extra: ExtractAdapterExtraType<T>, resolve: (value: ResponseReturnErrorType<ExtractErrorType<T>, T>) => void) => Promise<ResponseReturnErrorType<any, T>>;
onTimeoutError: (status: ExtractAdapterStatusType<T>, extra: ExtractAdapterExtraType<T>, resolve: (value: ResponseReturnErrorType<ExtractErrorType<T>, T>) => void) => Promise<ResponseReturnErrorType<any, T>>;
onUnexpectedError: (status: ExtractAdapterStatusType<T>, extra: ExtractAdapterExtraType<T>, resolve: (value: ResponseReturnErrorType<ExtractErrorType<T>, T>) => void) => Promise<ResponseReturnErrorType<any, T>>;
onError: (error: any, status: ExtractAdapterStatusType<T>, extra: ExtractAdapterExtraType<T>, resolve: (value: ResponseReturnErrorType<any, T>) => void) => Promise<ResponseReturnErrorType<any, T>>;
makeRequest: (apiCall: (resolve: (value: ResponseReturnType<any, any, T> | PromiseLike<ResponseReturnType<any, any, T>>) => void) => void) => Promise<ResponseReturnType<any, any, T>>;
}, "onRequestStart" | "onResponseStart" | "onError" | "onSuccess" | "onResponseEnd" | "onTimeoutError" | "onRequestEnd" | "createAbortListener" | "onResponseProgress" | "onRequestProgress" | "onBeforeRequest">) => Promise<ResponseReturnType<any, any, any>>;
type RequestMockType<Response> = {
data: Response | Response[] | (() => Response);
status?: number | string;
success?: boolean;
config?: {
timeout?: boolean;
requestTime?: number;
responseTime?: number;
totalUploaded?: number;
totalDownloaded?: number;
};
extra?: any;
};
type RequestDataMockTypes<Response, Request extends RequestInstance> = RequestMockType<Response> | RequestMockType<Response>[] | ((r: Request) => RequestMockType<Response>) | ((r: Request) => RequestMockType<Response>)[] | ((r: Request) => Promise<RequestMockType<Response>>) | ((r: Request) => Promise<RequestMockType<Response>>)[];
type GeneratorReturnMockTypes<Response, Request extends RequestInstance> = RequestMockType<Response> | ((r: Request) => RequestMockType<Response>) | ((r: Request) => Promise<RequestMockType<Response>>);
/**
* Fetch request it is designed to prepare the necessary setup to execute the request to the server.
* We can set up basic options for example endpoint, method, headers and advanced settings like cache, invalidation patterns, concurrency, retries and much, much more.
* :::info Usage
* We should not use this class directly in the standard development flow. We can initialize it using the `createRequest` method on the **Client** class.
* :::
*
* @attention
* The most important thing about the request is that it keeps data in the format that can be dumped. This is necessary for the persistence and different dispatcher storage types.
* This class doesn't have any callback methods by design and communicate with dispatcher and cache by events.
*/
declare class Request<Response, Payload, QueryParams, GlobalError, // Global Error Type
LocalError, // Additional Error for specific endpoint
Endpoint extends string, Adapter extends AdapterInstance = AdapterType, HasData extends true | false = false, HasParams extends true | false = false, HasQuery extends true | false = false> {
readonly client: Client<GlobalError, Adapter>;
readonly requestOptions: RequestOptionsType<Endpoint, ExtractAdapterOptionsType<Adapter>, ExtractAdapterMethodType<Adapter>>;
readonly requestJSON?: RequestCurrentType<Payload, QueryParams, Endpoint, ExtractAdapterOptionsType<Adapter>, ExtractAdapterMethodType<Adapter>> | undefined;
endpoint: Endpoint;
headers?: HeadersInit;
auth: boolean;
method: ExtractAdapterMethodType<Adapter>;
params: ExtractRouteParams<Endpoint> | NegativeTypes;
data: PayloadType<Payload>;
queryParams: QueryParams | NegativeTypes;
options?: ExtractAdapterOptionsType<Adapter> | undefined;
cancelable: boolean;
retry: number;
retryTime: number;
garbageCollection: number;
cache: boolean;
cacheTime: number;
queued: boolean;
offline: boolean;
abortKey: string;
cacheKey: string;
queueKey: string;
effectKey: string;
used: boolean;
deduplicate: boolean;
deduplicateTime: number;
dataMapper?: PayloadMapperType<Payload>;
mock?: Generator<GeneratorReturnMockTypes<Response, this>, GeneratorReturnMockTypes<Response, this>, GeneratorReturnMockTypes<Response, this>>;
mockData?: RequestDataMockTypes<Response, this>;
isMockEnabled: boolean;
requestMapper?: RequestMapper<this, any>;
responseMapper?: ResponseMapper<this, any, any>;
private updatedAbortKey;
private updatedCacheKey;
private updatedQueueKey;
private updatedEffectKey;
constructor(client: Client<GlobalError, Adapter>, requestOptions: RequestOptionsType<Endpoint, ExtractAdapterOptionsType<Adapter>, ExtractAdapterMethodType<Adapter>>, requestJSON?: RequestCurrentType<Payload, QueryParams, Endpoint, ExtractAdapterOptionsType<Adapter>, ExtractAdapterMethodType<Adapter>> | undefined);
setHeaders: (headers: HeadersInit) => Request<Response, Payload, QueryParams, GlobalError, LocalError, Endpoint, Adapter, HasData, HasParams, HasQuery>;
setAuth: (auth: boolean) => Request<Response, Payload, QueryParams, GlobalError, LocalError, Endpoint, Adapter, HasData, HasParams, HasQuery>;
setParams: <P extends ExtractRouteParams<Endpoint>>(params: P) => Request<Response, Payload, QueryParams, GlobalError, LocalError, Endpoint, Adapter, HasData, P extends null ? false : true, HasQuery>;
setData: <D extends Payload>(data: D) => Request<Response, Payload, QueryParams, GlobalError, LocalError, Endpoint, Adapter, D extends null ? false : true, HasParams, HasQuery>;
setQueryParams: (queryParams: QueryParams) => Request<Response, Payload, QueryParams, GlobalError, LocalError, Endpoint, Adapter, HasData, HasParams, true>;
setOptions: (options: ExtractAdapterOptionsType<Adapter>) => Request<Response, Payload, QueryParams, GlobalErr