UNPKG

@konkon5991/pipeline-ts

Version:

A lightweight TypeScript library for Railway Oriented Programming (ROP) with comprehensive functional programming utilities.

176 lines 7.06 kB
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; import { success, failure, isSuccess, isFailure } from './result'; /** * Executes functions in parallel and collects all results. * @template T - Array type of all function return values. * @template E - The type of the error. * @param {...Array<() => Promise<Result<any, E>>>} fns - Functions to execute in parallel. * @returns {Promise<Result<T, E[]>>} - Result containing array of values or array of errors. */ export const parallel = (...fns) => __awaiter(void 0, void 0, void 0, function* () { const results = yield Promise.all(fns.map(fn => fn())); const errors = []; const values = []; for (const result of results) { if (isFailure(result)) { errors.push(result.error); } else { values.push(result.value); } } return errors.length > 0 ? failure(errors) : success(values); }); /** * Executes functions in parallel and returns the first successful result. * @template T - The type of the value. * @template E - The type of the error. * @param {...Array<() => Promise<Result<T, E>>>} fns - Functions to execute. * @returns {Promise<Result<T, E[]>>} - First successful result or all errors. */ export const race = (...fns) => __awaiter(void 0, void 0, void 0, function* () { const results = yield Promise.allSettled(fns.map(fn => fn())); const errors = []; for (const result of results) { if (result.status === 'fulfilled' && isSuccess(result.value)) { return result.value; } else if (result.status === 'fulfilled' && isFailure(result.value)) { errors.push(result.value.error); } } return failure(errors); }); /** * Executes functions sequentially, stopping on first failure. * @template T - Array type of all function return values. * @template E - The type of the error. * @param {...Array<() => Promise<Result<any, E>>>} fns - Functions to execute sequentially. * @returns {Promise<Result<T, E>>} - Result containing array of values or first error. */ export const sequential = (...fns) => __awaiter(void 0, void 0, void 0, function* () { const values = []; for (const fn of fns) { const result = yield fn(); if (isFailure(result)) { return result; } values.push(result.value); } return success(values); }); /** * Retries a function with configurable options. * @template T - The type of the value. * @template E - The type of the error. * @param {() => Promise<Result<T, E>>} fn - Function to retry. * @param {RetryOptions} options - Retry configuration. * @returns {Promise<Result<T, E>>} - Result after retries. */ export const retry = (fn_1, ...args_1) => __awaiter(void 0, [fn_1, ...args_1], void 0, function* (fn, options = {}) { const { maxAttempts = 3, delay = 1000, backoff = 'linear', backoffFactor = 2, onRetry } = options; let lastError; for (let attempt = 1; attempt <= maxAttempts; attempt++) { const result = yield fn(); if (isSuccess(result)) { return result; } lastError = result.error; if (attempt < maxAttempts) { if (onRetry) { onRetry(attempt, lastError); } const waitTime = backoff === 'exponential' ? delay * Math.pow(backoffFactor, attempt - 1) : delay * attempt; yield new Promise(resolve => setTimeout(resolve, waitTime)); } } return failure(lastError); }); /** * Applies a timeout to an async operation. * @template T - The type of the value. * @template E - The type of the error. * @param {() => Promise<Result<T, E>>} fn - Function to execute with timeout. * @param {number} ms - Timeout in milliseconds. * @param {E} timeoutError - Error to return on timeout. * @returns {Promise<Result<T, E>>} - Result or timeout error. */ export const withTimeout = (fn, ms, timeoutError) => __awaiter(void 0, void 0, void 0, function* () { const timeout = new Promise(resolve => setTimeout(() => resolve(failure(timeoutError)), ms)); return Promise.race([fn(), timeout]); }); /** * Batches multiple operations and executes them with concurrency control. * @template T - The type of the value. * @template E - The type of the error. * @param {Array<() => Promise<Result<T, E>>>} fns - Functions to execute. * @param {number} concurrency - Maximum concurrent executions. * @returns {Promise<Result<T[], E[]>>} - Results of all operations. */ export const batch = (fns, concurrency) => __awaiter(void 0, void 0, void 0, function* () { const results = []; const executing = new Set(); for (let i = 0; i < fns.length; i++) { const promise = fns[i]().then(result => { results[i] = result; }).then(() => { executing.delete(promise); }); executing.add(promise); if (executing.size >= concurrency) { yield Promise.race(executing); } } yield Promise.all(executing); const errors = []; const values = []; for (const result of results) { if (isFailure(result)) { errors.push(result.error); } else { values.push(result.value); } } return errors.length > 0 ? failure(errors) : success(values); }); /** * Debounces an async function. * @template T - The type of the value. * @template E - The type of the error. * @param {(...args: any[]) => Promise<Result<T, E>>} fn - Function to debounce. * @param {number} ms - Debounce delay in milliseconds. * @returns {(...args: any[]) => Promise<Result<T, E>>} - Debounced function. */ export const debounce = (fn, ms) => { let timeoutId = null; let lastResolve = null; return (...args) => { return new Promise(resolve => { if (timeoutId) { clearTimeout(timeoutId); if (lastResolve) { lastResolve(failure(new Error('Debounced'))); } } lastResolve = resolve; timeoutId = setTimeout(() => __awaiter(void 0, void 0, void 0, function* () { const result = yield fn(...args); resolve(result); timeoutId = null; lastResolve = null; }), ms); }); }; }; //# sourceMappingURL=async.js.map