doddle
Version:
Tiny yet feature-packed (async) iteration toolkit.
128 lines • 4.47 kB
JavaScript
import { pull } from "../doddle/index.js";
import { checkASeqInputValue, chk, loadCheckers } from "../errors/error.js";
import { _xiter, isArrayLike, isAsyncIterable, isInt, isIterable, isNextable, isReadableStream } from "../utils.js";
import { ASeq, ASeqOperator } from "./aseq.class.js";
import { seq } from "./seq.ctor.js";
export function aseq(input) {
function fromFunctionResult(input) {
return ASeqOperator(input, async function* aseq(input) {
const pulled = await pull(input);
if (isAsyncIterable(pulled) || isIterable(pulled)) {
var iterator = _xiter(pulled);
}
else if (isArrayLike(pulled)) {
for (const key of Object.keys(pulled)) {
if (isInt(+key)) {
yield pull(pulled[+key]);
}
}
return;
}
else {
iterator = pulled;
}
for (let item = await iterator.next(); !item.done; item = await iterator.next()) {
yield pull(item.value);
}
await iterator.return?.();
});
}
input = checkASeqInputValue(input);
if (isNextable(input) || isReadableStream(input)) {
// readable streams are basically iterators
return fromFunctionResult(input).cache();
}
if (isAsyncIterable(input) || isIterable(input)) {
return aseq(() => input);
}
return ASeqOperator(input, async function* aseq(input) {
const result = typeof input === "function" ? await input() : input;
const pulled = await pull(result);
if (isNextable(pulled) || isReadableStream(pulled)) {
yield* fromFunctionResult(pulled).cache();
}
yield* fromFunctionResult(pulled);
});
}
/**
* Tools for creating {@link ASeq} instances.
*
* @category Create
* @class
*/
(function (aseq) {
/**
* Creates a {@link Seq} from the own, enumerable, string key-value pairs of an object. Values
* are produced lazily.
*
* @template Object Type of the source object.
* @param source Source object to create the {@link Seq} from.
* @returns A {@link Seq} of key-value pairs from the source object.
*/
function fromObject(source) {
const c = chk(fromObject);
c.source(source);
return aseq(() => Object.keys(source)).map(key => [key, source[key]]);
}
aseq.fromObject = fromObject;
/**
* Creates an {@link ASeq} of items by iterating a projection function.
*
* @param count Number of items to iterate.
* @param projection Function that receives the index and returns the item for that index,
* possibly asynchronously.
* @returns An {@link ASeq} of the generated items.
*/
function iterate(count, projection) {
const c = chk(iterate);
c.count(count);
c.projection(projection);
return aseq(async function* () {
for (let i = 0; i < count; i++) {
yield pull(projection(i));
}
});
}
aseq.iterate = iterate;
/**
* Creates an {@link ASeq} of numbers in the specified range.
*
* @param start Starting number of the range.
* @param end Ending number of the range (exclusive).
* @param size Step size for the range. Defaults to 1.
* @returns An {@link ASeq} of numbers in the specified range.
*/
function range(start, end, size = 1) {
const c = chk(range);
c.size(size);
c.start(start);
c.end(end);
return aseq(seq.range(start, end, size));
}
aseq.range = range;
/**
* Checks if the provided input is an {@link ASeq}.
*
* @param input Input to check.
* @returns `true` if the input is an {@link ASeq}, otherwise `false`.
*/
function is(input) {
return input instanceof ASeq;
}
aseq.is = is;
/**
* Creates an {@link ASeq} that throws an error when iterated.
*
* @param thrower Function that returns the error to throw.
* @returns An {@link ASeq} that throws the specified error when iterated.
*/
function throws(thrower) {
thrower = chk(throws).thrower(thrower);
return aseq(() => {
throw thrower();
});
}
aseq.throws = throws;
})(aseq || (aseq = {}));
loadCheckers(aseq);
//# sourceMappingURL=aseq.ctor.js.map