import { identity } from '../util/identity.js'; import { UnaryFunction, OperatorFunction } from '../interfaces.js'; import { bindCallback } from '../util/bindcallback.js'; import { isArrayLike, isIterable, isIterator, isReadableNodeStream, isWritableNodeStream, } from '../util/isiterable.js'; import { toLength } from '../util/tolength.js'; /** * This class serves as the base for all operations which support [Symbol.iterator]. */ export abstract class IterableX implements Iterable { abstract [Symbol.iterator](): Iterator; /** @nocollapse */ forEach(projection: (value: T, index: number) => void, thisArg?: any): void { const fn = bindCallback(projection, thisArg, 2); let i = 0; for (const item of this) { fn(item, i++); } } /** @nocollapse */ pipe(...operations: UnaryFunction, R>[]): R; pipe(...operations: OperatorFunction[]): IterableX; pipe(writable: R, options?: { end?: boolean }): R; pipe(...args: any[]) { let i = -1; const n = args.length; let acc: any = this; while (++i < n) { acc = args[i](IterableX.as(acc)); } return acc; } /** * Converts an existing string into an iterable of characters. * * @param {string} source The string to convert to an iterable. * @returns {IterableX} An terable stream of characters from the source. */ static as(source: string): IterableX; /** * Converts the iterable like input into an iterable. * * @template T The tyep of elements in the source iterable. * @param {Iterable} source The iterable to convert to an iterable. * @returns {IterableX} An iterable stream of the source sequence. */ static as(source: Iterable): IterableX; /** * Converts an array-like object to an iterable. * * @template T The type of elements in the source array-like sequence. * @param {ArrayLike} source The array-like sequence to convert to an iterable. * @returns {IterableX} The iterable containing the elements from the array-like sequence. */ static as(source: ArrayLike): IterableX; /** * Converts the object into a singleton in an iterable sequence. * * @template T The type of element to turn into an iterable sequence. * @param {T} source The item to turn into an iterable sequence. * @returns {IterableX} An iterable sequence from the source object. */ static as(source: T): IterableX; /** @nocollapse */ static as(source: any) { if (source instanceof IterableX) { return source; } if (typeof source === 'string') { return new FromIterable([source], identity); } if (isIterable(source) || isArrayLike(source)) { return new FromIterable(source, identity); } return new FromIterable([source], identity); } /** @nocollapse */ static from( source: Iterable | Iterator | ArrayLike, selector: (value: TSource, index: number) => TResult = identity, thisArg?: any ): IterableX { const fn = bindCallback(selector, thisArg, 2); if (isIterable(source)) { return new FromIterable(source, fn); } if (isArrayLike(source)) { return new FromIterable(source, fn); } if (isIterator(source)) { return new FromIterable({ [Symbol.iterator]: () => source }, fn); } throw new TypeError('Input type not supported'); } } (IterableX.prototype)[Symbol.toStringTag] = 'IterableX'; Object.defineProperty(IterableX, Symbol.hasInstance, { writable: true, configurable: true, value(inst: any) { return !!(inst && inst[Symbol.toStringTag] === 'IterableX'); }, }); /** @ignore */ export class FromIterable extends IterableX { private _source: Iterable | ArrayLike; private _fn: (value: TSource, index: number) => TResult; constructor( source: Iterable | ArrayLike, fn: (value: TSource, index: number) => TResult ) { super(); this._source = source; this._fn = fn; } *[Symbol.iterator]() { const iterable = isIterable(this._source); let i = 0; if (iterable) { for (const item of >this._source) { yield this._fn(item, i++); } } else { const length = toLength((>this._source).length); while (i < length) { const val = (>this._source)[i]; yield this._fn(val, i++); } } } } type WritableOrOperatorFunction = | NodeJS.WritableStream | NodeJS.ReadWriteStream | OperatorFunction; declare module '../iterable/iterablex' { interface IterableX extends Iterable { pipe(): IterableX; pipe(op1: OperatorFunction): IterableX; pipe(op1: OperatorFunction, op2: OperatorFunction): IterableX; pipe( op1: OperatorFunction, op2: OperatorFunction, op3: OperatorFunction ): IterableX; pipe( op1: OperatorFunction, op2: OperatorFunction, op3: OperatorFunction, op4: OperatorFunction ): IterableX; pipe( op1: OperatorFunction, op2: OperatorFunction, op3: OperatorFunction, op4: OperatorFunction, op5: OperatorFunction ): IterableX; pipe( op1: OperatorFunction, op2: OperatorFunction, op3: OperatorFunction, op4: OperatorFunction, op5: OperatorFunction, op6: OperatorFunction ): IterableX; pipe( op1: OperatorFunction, op2: OperatorFunction, op3: OperatorFunction, op4: OperatorFunction, op5: OperatorFunction, op6: OperatorFunction, op7: OperatorFunction ): IterableX; pipe( op1: OperatorFunction, op2: OperatorFunction, op3: OperatorFunction, op4: OperatorFunction, op5: OperatorFunction, op6: OperatorFunction, op7: OperatorFunction, op8: OperatorFunction ): IterableX; pipe( op1: OperatorFunction, op2: OperatorFunction, op3: OperatorFunction, op4: OperatorFunction, op5: OperatorFunction, op6: OperatorFunction, op7: OperatorFunction, op8: OperatorFunction, op9: OperatorFunction ): IterableX; pipe(...operations: OperatorFunction[]): IterableX; pipe(op1: A, options?: { end?: boolean }): A; } } try { ((isBrowser) => { if (isBrowser) { return; } IterableX.prototype['pipe'] = nodePipe; const readableOpts = (x: any, opts = x._writableState || { objectMode: true }) => opts; function nodePipe(this: IterableX, ...args: any[]) { let i = -1; let end: boolean; const n = args.length; let prev: any = this; let next: WritableOrOperatorFunction; while (++i < n) { next = args[i]; if (typeof next === 'function') { prev = next(IterableX.as(prev)); } else if (isWritableNodeStream(next)) { ({ end = true } = args[i + 1] || {}); // prettier-ignore return isReadableNodeStream(prev) ? prev.pipe(next, { end }) : IterableX.as(prev).toNodeStream(readableOpts(next)).pipe(next, { end }); } } return prev; } })(typeof window === 'object' && typeof document === 'object' && document.nodeType === 9); } catch (e) { /* */ } export const as = IterableX.as; export const from = IterableX.from;