@konkon5991/pipeline-ts
Version:
A lightweight TypeScript library for Railway Oriented Programming (ROP) with comprehensive functional programming utilities.
176 lines • 7.06 kB
JavaScript
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