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 🙏

© 2024 – Pkg Stats / Ryan Hefner

bplus-composer

v1.0.6

Published

A functional composition library

Downloads

31

Readme

BPLUS-COMPOSER

A functional composition library for TypeScript based on F# and Linq. The Linq implementation is fully lazy with the exception of the few functions that require a full iterable evaluation.

pipeline coverage

Note

This project is maintained over at GitLab: https://gitlab.com/adleatherwood/bplus-composer

Install

https://www.npmjs.com/package/bplus-composer

npm i bplus-composer

Option

An option is defined as either having a value or not.

export type Option<T> = T | undefined | null

You can deconstruct an option with either the match function...

let option = "some value"
let result = Option.match(option,
    success => success.split(" "),
    failure => [])

expect(result.length).toBe(2)

Or you can use the query function to enumerate the result. Undefined & null will result in an empty enumeration.

let option = "some value"
let result = Option.query(option)
    .select(text => text.split(" "))
    .single()

expect(result.length).toBe(2)

A typical example of how an option would appear in code.

let map = new Map([
    [1, { id: 1, first: "Larry", last: "Fine" }],
    [2, { id: 2, first: "Curly", last: "Howard" }],
    [3, { id: 3, first: "Moe", last: "Howard" }]
])

let result = map.get(2)
let initials = Option.query(result)
    .select(s => `${s.first[0]}.${s.last[0]}.`)
    .singleOrUndefined()

expect(initials).toBe("C.H.")

You can also test results for some or none.

let option = "test"
let success = Option.isSome(option)
let failure = Option.isNone(option)

expect(success).toBe(true)
expect(failure).toBe(false)

Result

A result either has a value or an error. Unlike the option, you need to construct a result as either a success or a failure.

let success = Result.success("test")
let failure = Result.failure("something went wrong")

You can deconstruct a result either the match function...

let result = Result.success("test")
let value = Result.match(result,
    success => "successful " + success,
    failure => "epic failure")

expect(value).toBe("successful test")

Or you can use the query function to enumerate the result. Failures will result in an empty enumeration.

let result = Result.success("test")
let value = Result.query(result)
    .select(text => "successful " + text)
    .select(text => text.toUpperCase())
    .single()

expect(value).toBe("SUCCESSFUL TEST")

You can also test results for success or failure.

let result = Result.success("test")
let success = Result.isSuccess(result)
let failure = Result.isFailure(result)

expect(success).toBe(true)
expect(failure).toBe(false)

Linq

I won't list all of the Linq functions that are implemented and how to use them. They are mostly all there and are used in a similar and intuitive manner as in C#. There are some differences worth mentioning. Although TypeScript offers enough flexibility for function overloads, they are generally very cumbersome and this library would have had an unmanageable number of them. Here are some of the more different arrangements:

OrderBy

In C#, you would use multiple subsequent Linq statements to sort data with secondary sorts. In this library, you will do it all in one statement.

let input = [5, 2, 4, 3, 1]
let actual = Linq.query(input)
    .orderBy(Asc.self())
    .toArray()
    .join()

expect(actual).toBe("1,2,3,4,5")

let input = [5, 2, 4, 3, 1]
let actual = Linq.query(input)
    .orderBy(Desc.self())
    .toArray()
    .join()

expect(actual).toBe("5,4,3,2,1")

Note the helper types of Asc and Desc. There are other functions on those type that will allow you to pass through custom key selectors and comparers. Like so:

let input = [[2, 1], [3, 2], [2, 3], [2, 2], [1, 3], [1, 2], [3, 3], [1, 1], [3, 1]]
let actual = Linq.query(input)
    .orderBy(Desc.by(t => t[0]), Asc.by(t => t[1]))
    .select(t => `${t[0]}${t[1]}`)
    .toArray()
    .join()

expect(actual).toBe("31,32,33,21,22,23,11,12,13")

MinOf & MaxOf

In C#, type specific extension methods either show or hide these functions base on specific types that this function can be performed on. In TypeScript we have no such luxury, so the function is always available. In this construct, you have to tell the function what you want to be matched.

let input = [3, 5, 1]
let actual = Linq.query(input)
    .maxOf(Compare.self())

expect(actual).toBe(5)

Again, there's a new helper called Compare that you can use to make these moments more readable. There are other functions on Compare that will allow you to pass through custom selectors and comparers.

DistinctBy & toMap & toSet

These function use the native Map & Set types. These types have restrictions on what types of value can be used as keys, etc. So the Linq functions are also restricted to these types.

let input = ["a", "b", "a", "c", "b", "a"]
let actual = Linq.query(input)
    .distinctBy(self)
    .toArray()
    .join()

expect(actual).toBe("a,b,c")

Notice the helper function self that can be used to select and return the item itself. This function is not necessary, but can make code more readable.

Icons made by Freepik from www.flaticon.com