npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

scootloops

v2.0.0

Published

Advanced JavaScript iteration utilities providing powerful patterns for array operations, async flows, tree traversal, and performance optimization not available in native JavaScript.

Readme

scootloops

Build Status

scootloops is a JavaScript utility library that provides advanced iteration patterns and utilities not directly available in native JavaScript. It offers functions for performance optimization, complex data structure traversal, advanced control flow, parallel processing, and data transformation.

Installation

npm install scootloops

Usage

import { upLoop, times, filterIt, parallelIt, chunkIt } from 'scootloops';

Core Functions

Loop Functions

upLoop

Loops through a range of numbers in ascending order with optional step and early exit support.

upLoop(start, end, callback, step = 1)

Parameters:

  • start (Number): Starting number
  • end (Number): Ending number (exclusive)
  • callback (Function): Function called for each iteration
  • step (Number, optional): Increment step (default: 1)

Return false from callback to break early.

// Basic usage
upLoop(1, 6, (i) => console.log(i)); // 1, 2, 3, 4, 5

// With step
upLoop(0, 10, (i) => console.log(i), 2); // 0, 2, 4, 6, 8

// Early exit
upLoop(1, 100, (i) => {
    console.log(i);
    if (i === 5) return false; // stops at 5
});

downLoop

Loops through a range of numbers in descending order.

downLoop(start, end, callback, step = 1)
// Basic usage
downLoop(5, 0, (i) => console.log(i)); // 5, 4, 3, 2, 1

// With step
downLoop(20, 0, (i) => console.log(i), 3); // 20, 17, 14, 11, 8, 5, 2

times

Executes a callback a specified number of times, passing the index (0-based).

times(count, callback)
// Execute 5 times
times(5, (i) => console.log(`Iteration ${i}`));

// Create array
const randoms = [];
times(10, () => randoms.push(Math.random()));

// Early exit
times(100, (i) => {
    if (i === 10) return false;
});

Array Utilities

filterIt

Filters arrays using string-based operators. Supports property access for objects.

filterIt(array, condition, value)

Basic filtering:

const numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];

filterIt(numbers, 'even'); // [2, 4, 6, 8, 10]
filterIt(numbers, 'odd'); // [1, 3, 5, 7, 9]
filterIt(numbers, 'greaterThan', 5); // [6, 7, 8, 9, 10]
filterIt(numbers, 'between', [3, 7]); // [3, 4, 5, 6, 7]

Object property filtering:

const people = [
    { name: 'John', age: 25 },
    { name: 'Jane', age: 35 },
    { name: 'Bob', age: 40 }
];

filterIt(people, 'age.greaterThan', 30);
// [{ name: 'Jane', age: 35 }, { name: 'Bob', age: 40 }]

filterIt(people, 'name.startsWith', 'J');
// [{ name: 'John', age: 25 }, { name: 'Jane', age: 35 }]

Available operators:

Numeric: even, odd, greaterThan, lessThan, between

String: startsWith, endsWith, contains, camelCase, matches (regex)

Type checking: isObject, isClass, isArray, isNumber, isString

Value checking: exactMatch, truthy, falsy, isEmpty, hasLength

sumIt

Sums all elements in an array with optional initial value.

sumIt(array, initialValue = 0)
sumIt([1, 2, 3, 4, 5]); // 15
sumIt([1, 2, 3], 10); // 16

chunkIt

Divides an array into chunks of specified size.

const chunks = chunkIt([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 3);
// [[1, 2, 3], [4, 5, 6], [7, 8, 9], [10]]

windowIt

Creates sliding windows from an array.

const windows = windowIt([1, 2, 3, 4, 5], 3);
// [[1, 2, 3], [2, 3, 4], [3, 4, 5]]

// With step
const steppedWindows = windowIt([1, 2, 3, 4, 5, 6], 2, 2);
// [[1, 2], [3, 4], [5, 6]]

zipIt

Zips multiple arrays into tuples.

const zipped = zipIt([1, 2, 3], ['a', 'b', 'c'], [true, false, true]);
// [[1, 'a', true], [2, 'b', false], [3, 'c', true]]

Advanced Functions

Async Utilities

parallelIt

Processes items in parallel with concurrency control.

const results = await parallelIt(
    [1, 2, 3, 4, 5],
    async (item) => {
        const response = await fetch(`https://api.example.com/${item}`);
        return response.json();
    },
    2 // max 2 concurrent requests
);

retryIt

Executes a function with automatic retry logic and exponential backoff.

const result = await retryIt(
    async (attempt) => {
        const response = await fetch('https://api.example.com/data');
        if (!response.ok) throw new Error('Failed');
        return response.json();
    },
    {
        retries: 5,
        delay: 1000,
        exponential: true
    }
);

asyncIterateIt

Processes items asynchronously with controlled concurrency and optional delays.

const results = await asyncIterateIt(
    urls,
    async (url) => {
        const response = await fetch(url);
        return response.json();
    },
    {
        concurrency: 3,
        delay: 500
    }
);

Performance Optimization

memoizeIt

Creates a memoized version of a function.

const fibonacci = (n) => {
    if (n <= 1) return n;
    return fibonacci(n - 1) + fibonacci(n - 2);
};

const memoizedFib = memoizeIt(fibonacci);
console.log(memoizedFib(40)); // Fast even for large numbers

throttleIt

Creates a throttled function (max once per interval).

const throttledScroll = throttleIt(() => {
    console.log('Scroll handled');
}, 200);

window.addEventListener('scroll', throttledScroll);

debounceIt

Creates a debounced function (delays invocation).

const debouncedSearch = debounceIt((query) => {
    console.log(`Searching for: ${query}`);
}, 300);

searchInput.addEventListener('input', (e) => {
    debouncedSearch(e.target.value);
});

Tree & Deep Object Utilities

deepIt

Iterates through nested objects/arrays.

const nestedObj = {
    a: 1,
    b: { c: 2, d: [3, 4, { e: 5 }] }
};

deepIt(nestedObj, (value, path) => {
    console.log(`${path}: ${value}`);
});

dfsIt

Traverses a tree structure using depth-first search.

const tree = {
    value: 'root',
    children: [
        { value: 'A', children: [{ value: 'A1' }, { value: 'A2' }] },
        { value: 'B', children: [{ value: 'B1' }] }
    ]
};

dfsIt(tree, (node, depth) => {
    console.log(`${depth}: ${node.value}`);
});
// Output: 0: root, 1: A, 2: A1, 2: A2, 1: B, 2: B1

bfsIt

Traverses a tree structure using breadth-first search.

bfsIt(tree, (node) => {
    console.log(node.value);
});
// Output: root, A, B, A1, A2, B1

Functional Programming

pipeIt

Composes functions left-to-right.

const addTwo = (x) => x + 2;
const multiplyByThree = (x) => x * 3;
const square = (x) => x * x;

const calculate = pipeIt(addTwo, multiplyByThree, square);
console.log(calculate(5)); // ((5 + 2) * 3)² = 441

Breaking Changes from v1.x

  • Removed mapIt - Use native array.map() instead
  • Removed forEach - Use native array.forEach() or array.filter().forEach()
  • Renamed reduceIt to sumIt - Now only sums arrays. For custom reducers, use native array.reduce()
  • upLoop and downLoop now support step parameter and early exit
  • filterIt property access fixed and new operators added
  • parallelIt now processes items concurrently (not sequentially)

Contributing

Contributions are welcome! Feel free to open a pull request.

License

MIT License