UNPKG

@hoover-institution/hubspot-lib

Version:

A toolkit for deep integration with HubSpot's Marketing Events API with a plugin-based architecture.

98 lines (91 loc) 2.95 kB
/** * Polls any async function until a condition is met or retries run out. * @param {Function} fn - The async function to call (should return a result). * @param {Function} condition - Function(result): boolean, determines if polling should stop. * @param {Array} args - Arguments to pass to the async function. * @param {number} maxRetries - Maximum number of attempts. * @param {number} delayMs - Delay between attempts (ms). * @returns {Promise<any>} The result from fn if condition passes, otherwise throws. */ async function pollUntil( fn, condition, args = [], maxRetries = 6, delayMs = 1000 ) { for (let attempt = 1; attempt <= maxRetries; attempt++) { const result = await fn(...args); if (condition(result)) return result; if (attempt < maxRetries) { console.log( `⏳ Attempt ${attempt}/${maxRetries} did not meet condition, retrying in ${delayMs}ms` ); await new Promise((res) => setTimeout(res, delayMs)); } } throw new Error("Condition not met after polling."); } export { pollUntil }; /** * Displays a simple console spinner while an async operation runs. * @param {Promise<any>} promise - The promise to wait for. * @param {string} [message] - Optional message to display. * @returns {Promise<any>} Resolves with the promise's result. */ async function withSpinner(promise, message = "Processing") { const spinnerFrames = ["|", "/", "-", "\\"]; let i = 0; let active = true; const spinner = setInterval(() => { process.stdout.write( `\r${spinnerFrames[i++ % spinnerFrames.length]} ${message}` ); }, 100); try { const result = await promise; active = false; clearInterval(spinner); process.stdout.write(`\r✅${message}\n`); return result; } catch (err) { active = false; clearInterval(spinner); process.stdout.write(`\r❌${message}\n`); throw err; } } export { withSpinner }; /** * Waits for a specified amount of time, displaying a spinner. * @param {number} ms - The number of milliseconds to wait. * @returns {Promise<void>} Resolves after the specified delay. */ async function wait(ms) { function msToReadable(ms) { if (ms < 1000) return `${ms}ms`; const sec = Math.floor(ms / 1000) % 60; const min = Math.floor(ms / 60000); let str = ""; if (min > 0) str += `${min}m `; if (sec > 0) str += `${sec}s`; return str.trim(); } const readable = msToReadable(ms); await withSpinner( new Promise((resolve) => setTimeout(resolve, ms)), `Processing the request for ${readable}` ); } export { wait }; /** * Waits for a specified time, then runs the provided function. * @param {Function} fn - The function to execute after waiting. * @param {number} ms - The number of milliseconds to wait. * @returns {Promise<any>} Resolves with the result of fn. */ async function execDelay(fn, ms) { await wait(ms); return fn(); } export { execDelay };