doddle
Version:
Tiny yet feature-packed (async) iteration toolkit.
140 lines • 4.2 kB
JavaScript
import { pull } from "./doddle/index.js";
export function _iter(input) {
return input[Symbol.iterator]();
}
export function _aiter(input) {
return input[Symbol.asyncIterator]();
}
export function _xiter(input) {
return isAsyncIterable(input) ? _aiter(input) : _iter(input);
}
export function isObject(value) {
return typeof value === "object" && value != null;
}
export function isFunction(value) {
return typeof value === "function";
}
export function isArrayLike(value) {
return isObject(value) && isInt(value.length);
}
export function isIterable(value) {
return isObject(value) && isFunction(value[Symbol.iterator]);
}
export const orderedStages = [undefined, "before", "after", "both"];
export const isInt = Number.isSafeInteger;
export const isBool = (value) => !!value === value;
export const isPair = (value) => Array.isArray(value) && value.length === 2;
export const isPosInt = (value) => isInt(value) && value > 0;
export function isAsyncIterable(value) {
return isObject(value) && isFunction(value[Symbol.asyncIterator]);
}
export function isReadableStream(value) {
return isObject(value) && isFunction(value.getReader);
}
export function isNextable(value) {
// Checks if value is an iterator
return isObject(value) && isFunction(value.next);
}
export function getClassName(something) {
if (something === null) {
return "null";
}
if (!isObject(something)) {
return typeof something;
}
const ctorName = something.constructor?.name ?? something?.[Symbol.toStringTag] ?? "Object";
return ctorName;
}
export function getValueDesc(object) {
if (object == null) {
return `${object}`;
}
if (isFunction(object)) {
return `function ${object.name || "<anonymous>"}`;
}
if (typeof object === "bigint") {
return `${object}n`;
}
if (typeof object === "symbol") {
return object.description;
}
if (typeof object === "string") {
if (object.length > 30) {
object = object.slice(0, 30) + "⋯";
}
return `"${object}"`;
}
if (isObject(object)) {
if (isDoddle(object)) {
return object.toString();
}
if (isNextable(object)) {
return `iterator ${getClassName(object)}`;
}
else if (isIterable(object)) {
return `iterable ${getClassName(object)}`;
}
else if (isAsyncIterable(object)) {
return `async iterable ${getClassName(object)}`;
}
else if (isDoddle(object)) {
return object.toString();
}
else if (isThenable(object)) {
return `a Promise`;
}
else {
return `object ${getClassName(object)}`;
}
}
return `${object}`;
}
/**
* Checks if the given value is a thenable.
*
* @param what The value to check.
*/
export function isThenable(what) {
return isObject(what) && isFunction(what.then);
}
export function isDoddle(value) {
return isObject(value) && isFunction(value.pull);
}
export function returnKvp(input, key, value) {
key = pull(key);
if (isAsyncIterable(input) && isThenable(key)) {
return key.then(key => [pull(key), value]);
}
return [key, value];
}
export function shuffleArray(array) {
for (let i = array.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
const temp = array[i];
array[i] = array[j];
array[j] = temp;
}
return array;
}
export function createCompare(desc) {
const baseCompare = (a, b) => (desc ? -1 : 1) * (a < b ? -1 : a > b ? 1 : 0);
return (a, b) => {
if (Array.isArray(a) && Array.isArray(b)) {
for (let i = 0; i < a.length; i++) {
const result = baseCompare(a[i], b[i]);
if (result !== 0) {
return result;
}
}
return 0;
}
return baseCompare(a, b);
};
}
export function createCompareKey(desc) {
const compare = createCompare(desc);
return (a, b) => {
return compare(a[0], b[0]);
};
}
//# sourceMappingURL=utils.js.map