UNPKG

@haandev/core

Version:

Core library for @haandev packages

89 lines (88 loc) 2.09 kB
// src/enforcer/enforcer.ts var sleep = (ms) => new Promise((res) => setTimeout(res, ms)); var enforcer = async (retrier, options) => { const { maxRetries = 3, retryDelay = 1e3, fix, onFix, onInvalid, timeout = 1e4, onStart, isCancelled, onCancelled, onFixError, abortSignal, onTimeout } = options; let result; let error; let isAborted = false; const abortHandler = async () => { isAborted = true; await onCancelled?.(); await finallyFn(); }; const finallyFn = async () => { if (timeoutId) { clearTimeout(timeoutId); } abortSignal?.removeEventListener("abort", abortHandler); }; const success = () => Promise.resolve(result).finally(finallyFn); const failure = () => Promise.reject(error).finally(finallyFn); abortSignal?.addEventListener("abort", abortHandler); await onStart?.(); if (isCancelled?.() || abortSignal?.aborted) { error = new Error("Aborted"); await onCancelled?.(); return failure(); } let timeoutId; let isTimeouted = false; if (timeout) { timeoutId = setTimeout(() => { isTimeouted = true; }, timeout); } const check = async (attempt) => { try { result = await retrier(result, error, attempt); return true; } catch (err) { error = err; if (error?.message === "Aborted") isAborted = true; return false; } }; if (await check(0)) return success(); onInvalid?.(); for (let attempt = 0; attempt < maxRetries; attempt++) { if (isCancelled?.() || isAborted || abortSignal?.aborted) { error = new Error("Aborted"); onCancelled?.(); return failure(); } if (isTimeouted) { onTimeout?.(); return failure(); } let fixResult; try { fixResult = await fix?.(result); } catch (err) { onFixError?.(err); } if (await check(attempt + 1)) { onFix?.(fixResult); return success(); } if (attempt < maxRetries - 1) { await sleep(retryDelay); } } return failure(); }; export { enforcer };