import { Context } from "react"; import { v4 as uuidv4 } from "uuid"; export const valuesOfSetEquals = (a: Set, b: Set) => a.size === b.size && [...a].every((item) => b.has(item)); export const createRelatedAbortController = (...signals: AbortSignal[]) => { const abortController = new AbortController(); signals.forEach((signal) => signal.addEventListener( "abort", () => abortController.abort("parent signal is aborted"), { once: true, signal: abortController.signal, } ) ); return abortController; }; export const uniqueForFirstSet = (first: Set, second: Set) => { const uniqueForFirst = new Set(); first.forEach((item) => { if (!second.has(item)) { uniqueForFirst.add(item); } }); return uniqueForFirst; }; export const doFunc = (callback: () => T) => callback(); export const isNotUndefined = (item: T): item is Exclude => typeof item !== "undefined"; export const createGuid = () => uuidv4(); export const retryAsync = async ( times: number, action: () => Promise ) => { for (let i = 0; i < times; i += 1) { try { return await action(); } catch (err) { console.error(`Attempt ${i + 1} was failed`, err); } } return Promise.reject("all attempts failed"); }; type CallbackMustBeAsyncFunction = never; type AsyncFunction = T extends (...args: any) => Promise ? T : CallbackMustBeAsyncFunction; export const withRetryAsync = (times: number) => (callback: AsyncFunction): T => ((...args: any) => { const action = () => callback(...args); return retryAsync(times, action); }) as unknown as T; export const identity = (item: T) => item; export const pipe = , Return1, Return2>( callback1: (...args: Input) => Return1, callback2: (item: Return1) => Return2 ) => (...items: Input) => callback2(callback1(...items)) as Return2; export const prop = (key: Key) => >(target: T) => target[key]; export const omit = (omitKeys: ReadonlyArray) => >(target: T) => omitKeys.reduce( (accumulator, keyForDelete) => { delete accumulator[keyForDelete]; return accumulator; }, { ...target } ) as Omit; export const pick = (pickKeys: ReadonlyArray) => >(target: T) => pickKeys.reduce((accumulator, keyForAdd) => { accumulator[keyForAdd] = target[keyForAdd]; return accumulator; }, {} as Pick); export const zip = (first: T[], second: U[]) => first.map((current, index) => [current, second[index]] as const); export const renameContext = (context: Context, name: string) => { (context as any).displayName = `${name}`; (context as any).Provider.displayName = `${name}.Provider`; (context as any).Consumer.displayName = `${name}.Consumer`; return context; };