UNPKG

@codibre/fluent-iterable

Version:

Provides LINQ-like fluent api operations for iterables and async iterables (ES2018+).

305 lines (304 loc) 8.47 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.iterate = void 0; exports.isPromise = isPromise; exports.asc = asc; exports.desc = desc; exports.assureOrder = assureOrder; exports.assureOrderDescending = assureOrderDescending; exports.constant = constant; exports.empty = empty; exports.emptyAsync = emptyAsync; exports.identity = identity; exports.truth = truth; exports.falsity = falsity; exports.negation = negation; exports.asyncNegation = asyncNegation; exports.fluentGroup = fluentGroup; exports.getAverageStepper = getAverageStepper; exports.eq = eq; exports.ge = ge; exports.gt = gt; exports.le = le; exports.lt = lt; exports.iterateAsync = iterateAsync; exports.iterateAllAsync = iterateAllAsync; exports.iterateAll = iterateAll; exports.iterateObjProps = iterateObjProps; exports.iterateObjEntries = iterateObjEntries; /* eslint-disable guard-for-in */ /* eslint-disable @typescript-eslint/no-empty-function */ const fluent_1 = __importDefault(require("../fluent")); const types_internal_1 = require("../types-internal"); const string_wrapper_1 = require("../types-internal/string-wrapper"); const map_1 = require("../sync/map"); const fluent_class_1 = require("../fluent-class"); const valueTypes = ['string', 'number', 'boolean']; /** * Returns exactly the informed parameter * @param param The informed parameter to be returned */ function identity(param) { return param; } /** * @internal */ async function* promiseIterateAsync(a) { const resolved = await a; yield* resolved; } function iteratorIterateAsync(a) { return { [Symbol.asyncIterator]() { const iterator = a[Symbol.iterator](); return { next() { const { done, value } = iterator.next(); return Promise.resolve({ done, value: done ? undefined : value }); }, return: iterator.return ? () => Promise.resolve(iterator.return(iterator)) : undefined, throw: iterator.throw ? () => Promise.resolve(iterator.throw(iterator)) : undefined, }; }, }; } function isPromise(t) { return !!(t && typeof t.then === 'function'); } /** * Iterates all element of an async iterable * @typeparam T the item type of the [[Iterable]] * @param a The async iterable */ function iterateAsync(a) { if (isPromise(a)) return promiseIterateAsync(a); return a[Symbol.iterator] ? iteratorIterateAsync(a) : a; } /** * Iterates in all elements of an async iterable of iterables or async iterables * @typeparam T the item type of the internal [[Iterable/AsyncIterable]] * @param a The async iterable */ async function* iterateAllAsync(a) { for await (const it of a) { yield* it; } } /** * Iterates all element of an iterable * @typeparam T the item type of the [[Iterable]] * @param a The iterable */ const iterate = identity; exports.iterate = iterate; /** * Returns a function that always returns the informed value * @param value the constant value */ function constant(value) { return function constantValue() { return value; }; } /** * Iterates in all elements of an iterable of iterables * @typeparam T the item type of the internal [[Iterable]] * @param a The iterable */ function* iterateAll(a) { for (const it of a) { yield* it; } } /** * Iterates over all owned properties of the given object * @param obj The object to iterate with */ function* iterateObjProps(obj) { for (const property in obj) { yield property; } } /** * Iterates over all owned entries of given object * @param obj The object to iterate with */ function iterateObjEntries(obj) { return map_1.map.call(iterateObjProps(obj), (property) => [ property, obj[property], ]); } /** * Provides a "equals" comparer * @typeparam T the type of b * @param b the value for comparison */ function eq(b) { return (a) => a === b; } /** * Provides a "greater than" comparer * @typeparam T the type of b * @param b the value for comparison */ function gt(b) { return (a) => a > b; } /** * Provides a "greater or equal" comparer * @typeparam T the type of b * @param b the value for comparison */ function ge(b) { return (a) => a >= b; } /** * Provides a "lesser than" comparer * @typeparam T the type of b * @param b the value for comparison */ function lt(b) { return (a) => a < b; } /** * Provides a "lesser or equal" comparer * @typeparam T the type of b * @param b the value for comparison */ function le(b) { return (a) => a <= b; } /** * Provides an empty iterable */ function* empty() { } /** * Provides an empty async iterable */ async function* emptyAsync() { } /** * Always returns true */ function truth() { return true; } /** * Always returns false */ function falsity() { return false; } /** * Provides a function that negates the informed predicate * @typeparam T the item type of the [[Predicate]] * @param predicate The predicate to be negated */ function negation(predicate) { return (...item) => !predicate.apply(this, item); } /** * Provides a function that negates the informed async predicate * @typeparam T the item type of the [[AsyncPredicate]] * @param predicate The async predicate to be negated */ function asyncNegation(predicate) { return async (item) => !(await predicate(item)); } /** * Convert a simple [[Group]] to a [[FluentGroup]] * @typeparam Key The type of the key * @typeparam Value the type of the items of the value property * @param {Group} grp the [[Group]] to be converted */ function fluentGroup(grp) { return { ...grp, values: (0, fluent_1.default)(grp.values), }; } /** * Returns an object to calculates incremental average/iterative means */ function getAverageStepper() { let avg = 0; let count = 0; const wrapper = { get avg() { return count ? avg : NaN; }, get count() { return count; }, step: (y) => (avg = avg + (y - avg) / ++count), }; return wrapper; } function getItemToAssure(f) { return typeof f === 'function' && !(f instanceof fluent_class_1.FluentClass) ? (...args) => f(...args) : f; } /** * Returns a new instance of a function with a order assuring mark. * Fluent Iterable will treat order Assuring marked function as if * they're guaranteed to return ordered result in regard some iterable * where they're applied. The actual order, though, is of responsibility * of the code using this package. * * This is useful to have access to faster versions of some algorithms, but * the output may not match expectation if the resulting order is not actually right. * * @param f the function to assure order */ function assureOrder(f) { const result = getItemToAssure(f); result[types_internal_1.orderAssured] = 1; return result; } /** * Returns a new instance of a function with a descending order assuring mark. * Fluent Iterable will treat descending order assuring marked functions as if * they're guaranteed to return descending ordered results in regard some iterable * where they're applied. The actual order, though, is of responsibility * of the code using this package. * * This is useful to have access to faster versions of some algorithms, but * the output may not match expectation if the resulting order is not actually right. * * @param f the function to assure order */ function assureOrderDescending(f) { const result = getItemToAssure(f); result[types_internal_1.orderAssured] = -1; return result; } function isValueType(f) { const tp = typeof f; return valueTypes.includes(tp); } /** * Mark a field name or a mapper as ascending, for use with sortBy * @param f the mapper or the field name */ function asc(f) { return assureOrder((isValueType(f) ? { [string_wrapper_1.valueTypeWrapper]: f } : f)); } /** * Mark a field name or a mapper as descending, for use with sortBy * @param f the mapper or the field name */ function desc(f) { return assureOrderDescending((isValueType(f) ? { [string_wrapper_1.valueTypeWrapper]: f } : f)); }