fast-iterable
Version:
Provides LINQ-like fluent api operations for iterables and async iterables (ES2018+).
77 lines (76 loc) • 2.6 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.flatJoinRecipe = void 0;
const base_1 = require("./../types/base");
const is_iterable_1 = require("../is-iterable");
function flattable(value) {
return typeof value !== 'string' && (0, is_iterable_1.isIterable)(value);
}
function getNextIterable(current, path, nextIndex) {
let item = current;
if (flattable(item)) {
return [item, nextIndex];
}
while (nextIndex < path.length) {
item = item[path[nextIndex]];
nextIndex++;
if (flattable(item)) {
break;
}
}
return [item, nextIndex];
}
function fillMiddleFieldsFactory(oldItem, start, nextIndex, path) {
return (x) => {
let current = oldItem;
for (let i = start; i < nextIndex; i++) {
current = current[path[i]];
if (!flattable(current)) {
x[path[i]] = current;
}
}
return x;
};
}
function fillMiddleToHeadFieldsFactory(oldItem, start, nextIndex, path) {
const fillMiddleFields = fillMiddleFieldsFactory(oldItem, start, nextIndex, path);
return (sub) => {
const newItem = fillMiddleFields({});
newItem[base_1.head] = sub;
return newItem;
};
}
function mapRoot(iterable, map, key, value) {
return map.call(iterable, (x) => {
x[key] = value;
return x;
});
}
function flatMap(item, ingredients, path, nextIndex) {
const oldItem = item;
const { flatten, map } = ingredients;
const start = nextIndex;
const result = getNextIterable(item, path, nextIndex);
item = result[0];
nextIndex = result[1];
if (nextIndex < path.length) {
return flatten.call(item, (sub) => {
const mapped = map.call(flatMap(sub, ingredients, path, nextIndex), fillMiddleFieldsFactory(oldItem, start, nextIndex, path));
return mapRoot(mapped, map, nextIndex > 0 ? path[nextIndex - 1] : base_1.tail, sub);
});
}
const fillMiddleToHeadItems = fillMiddleToHeadFieldsFactory(oldItem, start, nextIndex, path);
return flattable(item)
? map.call(item, fillMiddleToHeadItems)
: [fillMiddleToHeadItems(item)];
}
function flatJoinRecipe(ingredients) {
const { map, iterateAll } = ingredients;
return function (...path) {
return iterateAll(map.call(this, (x) => {
const flatted = flatMap(x, ingredients, path, 0);
return flattable(x) ? flatted : mapRoot(flatted, map, base_1.tail, x);
}));
};
}
exports.flatJoinRecipe = flatJoinRecipe;