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

@konker.dev/neverthrow-r

v0.0.1

Published

Extension for neverthrow to add a requirements/dependencies channel

Readme

neverthrow-r

An extension for neverthrow that adds a third channel — R, for requirements / dependencies — to Result and ResultAsync.

Inspired by effect-ts, but deliberately small: neverthrow-r is a thin layer of curried, pipe-friendly functions over neverthrow. There is no runtime, no context machinery, no scheduler — just two type aliases and a set of operators that thread an R parameter through your existing neverthrow chains.

Install

pnpm add @konker.dev/neverthrow-r neverthrow

neverthrow is a peer dependency.

Core types

type ResultR<R, T, E> = (r: R) => Result<T, E>;
type ResultAsyncR<R, T, E> = (r: R) => ResultAsync<T, E>;

A value of type ResultR<R, T, E> is a function that, given an R, produces a neverthrow Result<T, E>. R defaults to unknown (no specific requirements).

When two steps are chained, their requirement types are combined with intersection: a chain of ResultR<R1, A, E1> and (a: A) => ResultR<R2, B, E2> produces ResultR<R1 & R2, B, E1 | E2>.

pipe

neverthrow-r ships a small value-piping pipe implementation. It applies functions from left to right, preserves the inferred output type through the chain, and supports up to 20 function arguments:

import { pipe } from '@konker.dev/neverthrow-r';

If you already use a value-piping pipe from another library (e.g. effect, fp-ts, remeda), the operators remain shape-compatible with those too.

Quick example

import { andThen, asks, pipe, provide, type ResultR } from '@konker.dev/neverthrow-r';

const loadUser =
  (id: string): ResultR<{ db: Db }, User, DbError> =>
  (r) =>
    r.db.findUser(id);

const greet = (user: User): ResultR<{ logger: Logger }, string, never> =>
  asks((r) => {
    r.logger.info(`greeting ${user.name}`);
    return `Hello, ${user.name}`;
  });

const program = (id: string) => pipe(loadUser(id), andThen(greet));
//    ^? ResultR<{ db: Db } & { logger: Logger }, string, DbError>

const result = provide(program('u-1'), { db, logger });
//    ^? Result<string, DbError>

Note how program's requirement type is the intersection of the two steps' requirements — that intersection is built up automatically as you chain.

Async example with do-notation

import { okAsync } from 'neverthrow';
import { bindAsyncR, doAsyncR, fromResultAsync, pipe, provide } from '@konker.dev/neverthrow-r';

const program = pipe(
  doAsyncR(),
  bindAsyncR('user', () => (r: { db: Db }) => r.db.findUserAsync('u-1')),
  bindAsyncR('greeting', ({ user }) => fromResultAsync(okAsync(`Hello, ${user.name}`)))
);

const result = await provide(program, { db });
// result.value === { user: User, greeting: string }

Each bindAsyncR step:

  • accumulates a named value onto the success scope,
  • contributes its own requirements to the chain's R,
  • short-circuits the whole chain on the first Err.

Note that doAsyncR() (and doR()) is called without a generic type argument here. R defaults to unknown and the chain's accumulated requirements are built up automatically by each bindAsyncR step — because unknown & X = X. You only need an explicit doAsyncR<MyEnv>() if you want to constrain the chain to a known environment up front (so that subsequent steps requiring anything outside MyEnv become type errors).

Partial provision

import { provideSome } from '@konker.dev/neverthrow-r';

declare const program: ResultR<{ db: Db; logger: Logger }, User, Error>;

// inject the logger now, leave db for later
const stillNeedsDb = provideSome(program, { logger });
//  ^? ResultR<{ db: Db }, User, Error>

const result = provide(stillNeedsDb, { db });

provideSome whole-replaces the provided keys (no deep merge); the returned ResultR requires whatever keys were not provided.

API

Constructors

  • okR(value), errR(error) — lift into ResultR
  • okAsyncR(value), errAsyncR(error) — lift into ResultAsyncR
  • fromResult(r), fromResultAsync(ra) — lift an existing neverthrow value
  • asks(f) — build a ResultR from a selector over the environment
  • ask()asks(r => r), returns the full environment

Pipe

pipe(value, ...fns) — apply up to 20 unary functions from left to right.

Sync operators (over ResultR)

map, mapErr, andThen, orElse, match, andTee, orTee, andThrough

Async operators (over ResultAsyncR)

mapAsync, mapErrAsync, andThenAsync, orElseAsync, matchAsync, andTeeAsync, orTeeAsync, andThroughAsync

Sync → async bridges

asyncMap, asyncAndThen, asyncAndThrough — take a ResultR, return a ResultAsyncR.

Do-notation

doR, bindR, doAsyncR, bindAsyncR — accumulate named values into a success-channel scope while threading R.

Provision

  • provide(rr, deps) — supply all requirements, return the underlying Result / ResultAsync.
  • provideSome(rr, partial) — supply some requirements, return a ResultR over the remaining ones.

API Reference

Full auto-generated reference docs (signatures, types, module summaries) live in ./docs/reference/. They're regenerated from source on every ci run and a staleness check fails the build if they drift.

License

ISC