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

bs-yarp

v0.3.1

Published

ReasonML Result Promise

Readme

npm Build Status

Yet Another Reason Promise

This project has taken a lot of inspiration the future library. Also many bucklescript/reason Promise libraries exists. However this version focuses on the premise that a promise library should internally prepare for the possibility of failures -> thus Belt.Result.t is integral part of this library.

Install

npm install bs-yarp

And to your bsconfig.json:

"bs-dependencies": [..., "bs-yarp", ...],

Safe to open the whole BsYarp, only singular Promise module is imported:

open BsYarp;

Usage examples

Type:

Promise.t('a)  /* Promise will resolve with ok-value ('a) or with error (exn) */

Create Promise

  • From Js.Promise.t : Promise.fromJs(jsPromise);
  • From a value: Promise.fromValue("example");
    • The given value is internally set as Ok-value.
  • From a Belt.Result.t value: Promise.fromResult(res);
    • Internally set as Ok or Error -value depending on the given result.
  • With Promise.make which uses resolve callback:
    Promise.make(resolve =>
      setTimeout(() => resolve(Result.Ok("example")), 500)
      -> ignore
    );
    The resolve callback takes an argument of type Belt.Result.t('a, exn)
  • With Promise.makeWithCb which is more compatible with the node.js callback convention:
    type nodeCb('a, 'e) = (Js.Nullable.t('e), Js.Nullable.t('a)) => unit;
    [@bs.val] [@bs.module "fs"] external readFile: string => string => nodeCb('a, 'e) => unit = "";
    
    Promise.makeWithCb(callback => readFile("example.txt", "utf8", callback));
    • The error type is generic 'e here. The makeWithCb will auto-convert any kind of 'e into exn as long as the 'e can be inferred consistently into some type. This is similar to the way reason converts all kinds of errors thrown inside of try() into exn type.
  • API section below contains type descriptions of all the functions.

Action and catch

promise
-> Promise.tapOk(value => Js.log("Example: " ++ value))
-> Promise.catch(e => Js.log("Error: " ++ Js.String.make(e)));

A common pattern where tapOk executes the desired effects for the resolved value or alternatively catch is executed in case of error. The chain terminates with unit (no additional ->ignore needed to terminate the fast forward chain in this case)

Transformations

Promise.fromValue(123)
-> Promise.mapOk(v => (v + 45) * 3)
-> Promise.flatMapOk(v => fnReturningAPromise(v))
-> Promise.tapOk(x => Js.log(x))
-> Promise.toJs()  /* to Js.Promise.t */

About Promise.toJs():

  • Because Js.Promise.t is used underneath and it takes exn types of error values, it means that rejected promises will unavoidably have complex [["Test.SomeError",21],"example"] types of contents in the js side which may seem confusing at first when e.g. logged to application logs.

API:

  • type: t('a)

    • This Promise type. Internal details encapsuled.
  • make: ((Result.t('a, exn) => unit) => unit) => t('a)

    • Make new using resolver.
  • makeWithCb: (((Js.Nullable.t('e), Js.Nullable.t('a)) => unit) => unit) => t('a)

    • Make new with a node callback.
  • fromValue: 'a => t('a)

    • Make new from ok value. Immediately resolved.
  • fromError: exn => t('a)

    • Make new from error value. Immediately resolved as error.
  • fromResult: Result.t('a, exn) => t('a)

    • Make new from result. Immediately resolved as Ok or Error.
  • fromJs: Js.Promise.t('a) => t('a)

    • Make new based on jsPromise. Resolves as Ok when the jsPromise is resolved or as Error if the JsPromise is rejected.
  • fromJsWithErrorConverter: Js.Promise.t('a) => (Js.Promise.error => exn) => t('a)

    • Same as fromJs but you can provide custom error converter (Js.Promise.error => exn)
  • toJs: t('a) => Js.Promise.t('a)

    • Returns a jsPromise. If rejected, the ocaml error (always of type exn) is passed as is.
  • toJsWithErrorConversion: t('a) => Js.Promise.t('a)

    • Returns a jsPromise. If rejected, the ocaml error is internally converted into a js Error (Js.Exn.t) on rejection.
  • tapResult: t('a) => (Result.t('a, exn) => unit) => t('a)

    • With promise, execute the consumer with the internal result when it is resolved. Any exceptions thrown by consumer are ignored. Returns a promise which is identical to the given promise.
  • getResult: t('a) => (Result.t('a, exn) => unit) => unit

    • Like tapResult but without return value.
  • tapOk: t('a) => ('a => unit) => t('a)

    • With promise, execute the consumer with the resolved ok value. Any exceptions thrown by the consumer are ignored. Returns a promise which is identical to the given promise.
  • tapError: t('a) => (exn => unit) => t('a)

    • Similar to tapOk, but error value is passed to the consumer.
  • catch: t('a) => (exn => unit) => unit

    • Like tapError but without return value.
  • mapOk: t('a) => ('a => 'b) => t('b)

    • With promise, map ok-value with the given function. Returned promise will either contain the new ok-value or an error value if the function throws an exception.
  • mapError: t('a) => (exn => exn) => t('a)

    • With promise, map error-value with the given function. If the function throws an exception, that too is catched.
  • mapResult: t('a) => (Result.t('a, exn) => Result.t('b, exn)) => t('b)

    • With promise, map Belt.Result.t into another Belt.Result.t. If function throws an exception it is mapped as Error result.
  • mapOkResult: t('a) => ('a => Result.t('b, exn)) => t('b)

    • With promise, map ok value into Result.t. If function throws an exception it is mapped as Error result.
  • mapErrorResult: t('a) => (exn => Result.t('a, exn)) => t('a)

    • With promise, map error into Result.t. If function throws an exception it is mapped as Error result.
  • flatMap: t('a) => (Result.t('a, exn) => t('b)) => t('b)

    • With promise, bind the function which returns the resulting promise. No exception catching at this level.
  • flatMapOk: t('a) => ('a => t('b)) => t('b)

    • With promise, bind ok value to the function which returns the resulting promise. No exception catching at this level.
  • flatMapError: t('a) => (exn => t('a)) => t('a)

    • With promise, bind error value the function which returns the resulting promise. No exception catching at this level.
  • all: list(t('a)) => t(list('a))

    • Turn list of promises (of homogeneous type) into a promise of list.
  • all2: (t('a), t('b)) => t(('a, 'b))

    • Tuple of heterogeneous promises into a promise of tuple.
  • all3: (t('a), t('b), t('c)) => t(('a, 'b, 'c))

  • all4: (t('a), t('b), t('c), t('d)) => t(('a, 'b, 'c, 'd))

  • all5: (t('a), t('b), t('c), t('d), t('e)) => t(('a, 'b, 'c, 'd, 'e))

  • all6: (t('a), t('b), t('c), t('d), t('e), t('f)) => t(('a, 'b, 'c, 'd, 'e, 'f))

  • map2: t('a) => t('b) => ((Result.t('a, exn), Result.t('b, exn)) => Result.t('z, exn)) => t('z)

    • map2 takes 3 arguments: 2 heterogeneous promises and a bi-function which combines results into a combined result. Returned promise will contain the combined result.
  • map3: t('a) => t('b) => t('c) => ((Result.t('a, exn), Result.t('b, exn), Result.t('c, exn)) => Result.t('z, exn)) => t('z)

  • map4: t('a) => t('b) => t('c) => t('d) => ((Result.t('a, exn), Result.t('b, exn), Result.t('c, exn), Result.t('d, exn)) => Result.t('z, exn)) => t('z)

  • map5: t('a) => t('b) => t('c) => t('d) => t('e) => ((Result.t('a, exn), Result.t('b, exn), Result.t('c, exn), Result.t('d, exn), Result.t('e, exn)) => Result.t('z, exn)) => t('z)

  • map6: t('a) => t('b) => t('c) => t('d) => t('e) => t('f) => ((Result.t('a, exn), Result.t('b, exn), Result.t('c, exn), Result.t('d, exn), Result.t('e, exn), Result.t('f, exn)) => Result.t('z, exn)) => t('z)