import type { OperatorInterface, AsyncOperatorInterface } from "./interfaces"; /** * Identity operator — returns data unchanged. * * @category Operators */ export class TransparentOperator implements OperatorInterface { apply(data: T): T { return data; } } /** * Transform operator — applies a mapper function to input data. * * @category Operators */ export class MapOperator implements OperatorInterface { private readonly _transformer: (data: TInput) => TOutput; constructor(mapper: (data: TInput) => TOutput) { this._transformer = mapper; } apply(data: TInput): TOutput { return this._transformer(data); } } /** * Array filter operator — filters elements by predicate, returning a new array. * * @category Operators */ export class FilterOperator implements OperatorInterface { private readonly _predicate: (item: T) => boolean; constructor(predicate: (item: T) => boolean) { this._predicate = predicate; } apply(data: T[]): T[] { return data.filter(this._predicate); } } /** * Array reduce operator — reduces an array to a single value. Returns defaultValue for empty arrays. * * @category Operators */ export class ReducerOperator implements OperatorInterface { private readonly _reducer: (acc: T, curr: T) => T; private readonly _defaultValue?: T; constructor(reducer: (acc: T, curr: T) => T, defaultValue?: T) { this._reducer = reducer; this._defaultValue = defaultValue; } apply(data: T[]): T | undefined { if (data.length === 0) { return this._defaultValue; } return data.reduce(this._reducer); } } /** * Validation operator — passes data through if validator returns true, otherwise returns undefined. * * @category Operators */ export class GuardOperator implements OperatorInterface { private readonly _validator: (data: T) => boolean; constructor(validator: (data: T) => boolean) { this._validator = validator; } apply(data: T): T | undefined { return this._validator(data) ? data : undefined; } } /** * Composite operator — chains multiple operators sequentially, piping output of each into the next. * * @category Operators */ export class PipelineOperator implements OperatorInterface { private readonly _operators: readonly OperatorInterface[] constructor(operators: OperatorInterface[]) { this._operators = operators; } apply(data: TInput): TOutput { let current: unknown = data; for (const operator of this._operators) { current = operator.apply(current); } return current as TOutput; } } // ═══════════════════════════════════════════════════════════════ // Async operators // ═══════════════════════════════════════════════════════════════ /** * Async map operator. * The mapper can be synchronous or asynchronous (return a Promise). * * @category Async Operators */ export class AsyncMapOperator implements AsyncOperatorInterface { private readonly _transformer: (data: TInput) => Promise | TOutput; constructor(mapper: (data: TInput) => Promise | TOutput) { this._transformer = mapper; } async apply(data: TInput): Promise { return this._transformer(data); } } /** * Async guard operator. * The validator can be synchronous or asynchronous (return a Promise). * Passes data through if the predicate is true, otherwise returns undefined. * * @category Async Operators */ export class AsyncGuardOperator implements AsyncOperatorInterface { private readonly _validator: (data: T) => Promise | boolean; constructor(validator: (data: T) => Promise | boolean) { this._validator = validator; } async apply(data: T): Promise { const valid = await this._validator(data); return valid ? data : undefined; } } /** * Async operator pipeline. * Accepts both synchronous (OperatorInterface) and asynchronous (AsyncOperatorInterface) operators. * Each step is executed via await — a sync operator is unwrapped as a no-op. * * @category Async Operators */ export class AsyncPipelineOperator implements AsyncOperatorInterface { private readonly _operators: readonly (OperatorInterface | AsyncOperatorInterface)[]; constructor(operators: (OperatorInterface | AsyncOperatorInterface)[]) { this._operators = operators; } async apply(data: TInput): Promise { let current: unknown = data; for (const operator of this._operators) { current = await (operator as { apply: (data: unknown) => Promise | unknown }).apply(current); } return current as TOutput; } }