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

@rslike/iter

v1.0.0

Published

JavaScript Iteration library

Readme

@rslike/iter

Rust-inspired lazy iterator library for JavaScript and TypeScript.

Wraps any Iterable<T> and provides chainable adapter and consumer methods modelled after Rust's Iterator and DoubleEndedIterator traits. Adapter methods are lazy — they return new iterator instances backed by generators and do no work until a consumer is called.

Features

  • Lazy by default — adapters only run when a consumer is called
  • Mirrors Rust's Iterator and DoubleEndedIterator traits
  • Iter.from(source, mapFn?) — backward-compatible with Array.from
  • DoubleEndedIter — iterate from both front and back
  • Peekable — look at the next element without consuming it
  • Integrates with @rslike/std (Option) and @rslike/cmp (Ord, Eq)
  • First-class CJS and ESM support
  • TypeScript ready — .d.ts types included

Installation

npm i @rslike/iter
# or
pnpm add @rslike/iter
yarn add @rslike/iter
bun add @rslike/iter

Quick start

import { iter } from "@rslike/iter";

iter([1, 2, 3, 4, 5])
  .filter(x => x % 2 === 0)
  .map(x => x * 10)
  .collect();
// [20, 40]

API

Factory functions

iter(source)

Creates an Iter<T> from any iterable.

import { iter } from "@rslike/iter";

iter([1, 2, 3]).map(x => x * 2).collect();            // [2, 4, 6]
iter("hello").collect();                               // ["h", "e", "l", "l", "o"]
iter(new Set([1, 2, 3])).filter(x => x > 1).collect(); // [2, 3]

function* naturals() { let i = 0; while (true) yield i++; }
iter(naturals()).take(5).collect();                    // [0, 1, 2, 3, 4]

doubleEndedIter(array)

Creates a DoubleEndedIter<T> from an array, supporting iteration from both ends.

import { doubleEndedIter } from "@rslike/iter";

const dei = doubleEndedIter([1, 2, 3, 4]);
dei.next();     // Some(1)
dei.nextBack(); // Some(4)
dei.next();     // Some(2)
dei.nextBack(); // Some(3)
dei.next();     // None

Iter<T>

Static

| Method | Description | |---|---| | Iter.from(source) | Create from any iterable (like Array.from) | | Iter.from(source, mapFn) | Create with a mapping function — mapFn(value, index) |

import { Iter } from "@rslike/iter";

Iter.from([1, 2, 3], x => x * 2).collect();        // [2, 4, 6]
Iter.from("abc", (c, i) => `${i}:${c}`).collect(); // ["0:a", "1:b", "2:c"]

Adapters (lazy)

| Method | Description | |---|---| | .map(fn) | Transform each element | | .filter(fn) | Keep elements matching predicate | | .filter_map(fn) | Map then keep Some results (see @rslike/std) | | .flatMap(fn) | Map each element to an iterable and flatten one level | | .flatten() | Flatten one level of nested iterables | | .enumerate() | Yield [index, value] pairs | | .take(n) | Yield at most n elements | | .skip(n) | Skip the first n elements | | .takeWhile(fn) | Yield while predicate holds, stop at first failure | | .skipWhile(fn) | Skip while predicate holds, yield the rest | | .chain(other) | Append another iterable | | .zip(other) | Pair elements; stops at the shorter iterator | | .inspect(fn) | Call fn on each element without changing it (debug) | | .stepBy(n) | Yield every n-th element starting from the first | | .peekable() | Wrap in a Peekable to look ahead without consuming | | .dedup() | Remove consecutive duplicates (uses @rslike/cmp Eq) | | .dedupBy(fn) | Remove consecutive duplicates using a custom equality function | | .sorted() | Collect and sort using @rslike/cmp Ord | | .sortBy(fn) | Collect and sort using a custom comparator | | .rev() | Collect and yield in reverse order |

Consumers (eager)

| Method | Description | |---|---| | .collect() | Gather all elements into an array | | .toArray() | Alias for collect() | | .forEach(fn) | Call fn on each element | | .fold(init, fn) | Reduce with an initial value | | .reduce(fn) | Reduce without initial value, returns Option<T> | | .count() | Count remaining elements | | .last() | Return the last element as Option<T> | | .nth(n) | Return the n-th element (0-indexed) as Option<T> | | .find(fn) | First element matching predicate as Option<T> | | .position(fn) | Index of first match as Option<number> | | .any(fn) | true if any element matches | | .all(fn) | true if all elements match | | .sum() | Sum all numbers | | .product() | Multiply all numbers | | .min() | Minimum using < operator, returns Option<T> | | .max() | Maximum using > operator, returns Option<T> | | .minBy(fn) | Minimum using a custom comparator | | .maxBy(fn) | Maximum using a custom comparator | | .minCmp() | Minimum using @rslike/cmp Ord | | .maxCmp() | Maximum using @rslike/cmp Ord | | .minByKey(fn) | Minimum by an extracted Ord key | | .maxByKey(fn) | Maximum by an extracted Ord key | | .cmp(other) | Lexicographic comparison using @rslike/cmp | | .eqBy(other) | Element-wise equality using @rslike/cmp | | .unzip() | Split [A, B] pairs into [A[], B[]] |


Peekable<T>

Extends Iter<T>. Created via .peekable().

| Method | Description | |---|---| | .peek() | Return Option<T> of the next element without consuming it | | .next() | Consume and return the next element as Option<T> |

import { iter } from "@rslike/iter";

const p = iter([1, 2, 3]).peekable();
p.peek(); // Some(1)
p.peek(); // Some(1) — same value, not consumed
p.next(); // Some(1) — consumed
p.peek(); // Some(2)

DoubleEndedIter<T>

Extends Iter<T>. Created via doubleEndedIter(array) or DoubleEndedIter.from(array). Backed by an array with front and back cursors that share state, so next() and nextBack() can be freely interleaved.

Adapters (map, filter, take, skip, filter_map) on DoubleEndedIter eagerly evaluate the remaining slice to preserve double-ended capability and return a new DoubleEndedIter.

Additional methods

| Method | Description | |---|---| | .nextBack() | Advance from the back, returns Option<T> | | .rfold(init, fn) | Fold from the back | | .rfind(fn) | Find from the back, returns Option<T> | | .rposition(fn) | Index of first match from the back, returns Option<number> | | .rev() | Return remaining elements as a new DoubleEndedIter in reverse |

import { doubleEndedIter } from "@rslike/iter";

doubleEndedIter([1, 2, 3]).rfold("", (acc, x) => acc + x); // "321"
doubleEndedIter([1, 2, 3, 4]).rfind(x => x < 3);           // Some(2)
doubleEndedIter([1, 2, 3, 2, 1]).rposition(x => x === 2);  // Some(3)

Integration with @rslike/std

Consumer methods that may return no value (find, reduce, last, min, max, etc.) return Option<T> from @rslike/std instead of T | undefined.

import { iter } from "@rslike/iter";

iter([1, 2, 3]).find(x => x > 5); // None
iter([1, 2, 3]).find(x => x > 1); // Some(2)

iter([1, 2, 3]).reduce((a, b) => a + b); // Some(6)
iter<number>([]).reduce((a, b) => a + b); // None

The .filter_map(fn) adapter accepts a function returning Option<U> and only yields the unwrapped Some values:

import { iter } from "@rslike/iter";
import { Some, None } from "@rslike/std";

iter([1, 2, 3, 4, 5])
  .filter_map(x => x > 3 ? Some(x * 10) : None())
  .collect();
// [40, 50]

Related packages

License

MIT © Vitali Haradkou