An open API service indexing awesome lists of open source software.

https://github.com/commonlyjs/commonly

A modern utility library for JavaScript/TypeScript.
https://github.com/commonlyjs/commonly

commonly javascript typescript utilities

Last synced: about 2 months ago
JSON representation

A modern utility library for JavaScript/TypeScript.

Awesome Lists containing this project

README

        



Build Status


Coverage Status


Codecov Status


Join Gitter










The most comprehensive modern utility library for JavaScript/TypeScript.


Explore the API »




Report a bug
  ·  
Request a feature




Table of Contents
------------------
* [Overview](#overview)
* [Why Commonly?](#why-commonly)
* [Key features](#key-features)
* [Comparision to other libraries](#comparision-to-other-libraries)
* [Enhance your experience](#enhance-your-experience)
* [Getting started](#getting-started)
* [Installation](#installation)
* [Examples](#examples)
* [Documentation](#documentation)
* [Articles](#articles)
* [API reference](#api-reference)
* [Cookbook](#cookbook)
* [Roadmap](#roadmap)

Overview
---------
> Keep in mind that not everything is implemented yet, for a preview of upcoming version use a `@next` tag.
> See what's done and what's next on the [roadmap](#roadmap).

### Why Commonly?
Commonly is an unopinionated general-purpose library that expands on the JavaScript API which you can adjust to any codebase.

#### Key features
* Every function is pure, none will ever mutate your data.
* Extensible protocol-based architecture, every function is bound to work with your custom data structures.
* Process often overlooked data types with ease, operate on a Map, Set, HTMLCollection, NodeList and more *(+24)*.
* Builtin interoperability with your favorite libraries.
* Support for Streams/Observables: [RxJS](https://github.com/ReactiveX/rxjs), [Most](https://github.com/cujojs/most), [flyd](https://github.com/paldepind/flyd).
* Support for immutable data structures: [Immutable.js](https://github.com/immutable-js/immutable-js), [mori](https://github.com/swannodette/mori).

#### Comparision to other libraries



Lodash/Underscore


About
A rich and battle-tested utility library with many useful utilities.


Dissimilarity



  • TypeScript is not officially supported.

    Definitions from @types are maintained by external contributors.


  • Utilities are limited to operate only on plain objects and arrays.

    There is no support for other iterable collections (TypedArray, Map, Set, etc.).


  • Any operation performed on collection is done eagerly.


  • Does not follow iteratee-first data-last approach.

    When practising functional programming this can be helpful.





Ramda/Rambda


About
A functional programming oriented utility library focused on transformations of data.


Dissimilarity



  • TypeScript is not officially supported.

    Definitions from @types are maintained by external contributors.


  • Utilities are limited to operate only on plain objects and arrays.

    There is no support for other iterable collections (TypedArray, Map, Set etc.).


  • Any operation performed on collection is done eagerly.


  • Common utilities which are not related to functional programming are missing.





Lazy.js


About
A library in which manipulation of data is done lazily.


Dissimilarity



  • TypeScript is not officially supported.

    Definitions from @types are maintained by external contributors.


  • An object-oriented API based on a builder pattern (see lodash/chain function).

    You chain methods together and then you end it with a .build() method.


  • Operates solely on iterators without acknowledging the source's shape.

    This means you cannot transform your structure to a shape other than an array.




### Enhance your experience


Run-time type system


You are protected from common mistakes you often make by a dynamic type checking.
An error with a detailed message will be thrown whenever either an argument is of the wrong type or you tried to apply too many of them.




Evaluation is done eagerly as you provide arguments to a function individually to improve error reporting for partially applied functions.









Tightly typed


Discover the API by simply typing.
Each library's member is strictly typed, do not let those silly type errors slip by.




Every functional utility comes with complete type definitions.

No more untyped compose, partial and curry.













Inline documentation


Easily learn about details of a function on the fly.
We carefully document our code, so you will never have to browse manually through the documentation again.




Whenever you feel lost, see included external resources attached as links or just try out included examples.







Getting started
----------------
This library comes in multiple packages, you match and choose whichever you need.

Some of the packages may have dependencies, often only related to the problem they are solving.
An example of such is the `@commonly/type` package, from which only TypeScript users can benefit.
Another example is a package that may require a specific environment, like a browser or a Node.js-based one.

When a package requires such, it should state so in its manifest file, a package.json, and the documentation.

### Installation
As an example, we will install a couple of core packages.
```shell script
npm install @commonly/function @commonly/iterable @commonly/math @commonly/number @commonly/string
```
**Users of TypeScript**, remember to install the `@commonly/type` package, it contains type definitions used in other packages.

### Examples
#### Simplify your code with the help of a library
```typescript
import { flatten, partition } from "@commonly/iterable"

const quicksort = (numbers) => {
if (numbers.length < 2) {
return numbers
} else {
const [ pivot, ...remainder ] = numbers
const [ lesser, greater ] = partition(number => number <= pivot, remainder)
return flatten([ quicksort(lesser), pivot, quicksort(greater) ])
}
}
```

#### Extend capabilities of the library with only few lines of code
```typescript
//- react-utilities.ts
import { concat, filter, join, reverse } from "@commonly/iterable"
import { isTruthy } from "@commonly/reflect"

export const css = (...varargs) => {
const [ modifiers, ...named ]: [ object, string[] ] = reverse(varargs)
const classes = concat(named, Object.keys(filter(isTruthy, modifiers)))
return join(" ", classes)
}

//- Toast.tsx
import React from "react"
import { css } from "./react-utilities"

export default function Toast({ message, color, visible }) {
return (


It's a toast: {message}.

)
}
```

#### Operate on any common data structure with only a single set of API
```typescript
import { Observable } from "rxjs"
import { filter, map } from "@commonly/iterable"

document.body.innerHTML = `
Try to guess a number from 1 to 10!

`

const inputValues = Observable.fromEvent(document.querySelector("input"), "change")

inputValues
|> map(event => event.target.value)
|> filter(guess => guess === Math.floor(Math.random() * 10 + 1))
|> map(() => window.alert("Good guess!"))
```

#### Adjust your data structures to leverage the capabilities of the library
```typescript
//- Vector.ts
import { Operand } from "@commonly/protocol"

export default class Vector implements Operand {
constructor(x, y) {
this.x = x
this.y = y
}

get magnitude() {
return Math.sqrt(this.x * this.x + this.y * this.y)
}

// Let us use `add` function on instances of the `Vector` type.
// Note: You can only affect the behaviour of functions which expects a specific contract.
[Operand.augend](addend) {
return new Vector(this.x + addend.x, this.y + addend.y)
}
}

//- Arrow.ts
import Vector from "./Vector"

export default class Arrow extends Vector {
constructor() {
super(0, 0)
}
}

//- Bow.ts
import { add } from "@commonly/math"
import Vector from "./Vector"
import Arrow from "./Arrow"

export default class Bow {
shoot(arrow: Arrow) {
const force = new Vector(Math.random() - Math.random(), Math.random() - Math.random())
return add(arrow, force)
}
}

//- Quiver.ts
import { Iterable, Reducible } from "@commonly/protocol"
import Arrow from "./Arrow"

class Quiver implements Iterable, Reducible {
constructor() {
this.arrows = []
}

insert(arrow: Arrow) {
this.arrows.push(arrow)
return this
}

draw() {
return this.arrow.pop()
}

[Iterable.iterator]*() {
for (const arrow of this.arrows) {
yield arrow
}
}

[Reducible.reducer]() {
const reducer = (quiver, arrow) => {
quiver.insert(arrow)
return quiver
}

return reducer
}
}

//- index.ts
import { map } from "@commonly/iterable"

const bow = new Bow()
const quiver = new Quiver()
.insert(new Arrow())
.insert(new Arrow())
.insert(new Arrow())

const projectiles = map(bow.shoot, quiver)
for (const projectile of projectiles) {
console.log(`An ${projectile.constructor.name} projectile is flying at speed: ${projectile.magnitude}.`)
}
```

Documentation
--------------
We do our best to provide you with the most complete documentation to deliver you a wonderful developer experience.
To achieve this we write the cleanest code possible, annotate every bit of every function with types and inline documentation,
maintain human-readable unit tests in a [behavior-driven development](https://en.wikipedia.org/wiki/Behavior-driven_development) fashion and produce helpful content with examples.

### Articles
You can find articles on more advanced uses on [commonlyjs.com/articles/](https://commonlyjs.com/articles/).

### API reference
Every member of our API can be found here on [commonlyjs.com/api/](https://commonlyjs.com/api/).
Alternatively you can browse `packages//docs/` directory if you prefer to read those in a markdown format.
Both documents are in sync, you will never find any to be out of date.

### Cookbook
Whenever you find yourself in need of some basic functionality, try browsing our ready to copy-paste recipses on [commonlyjs.com/cookbook/](https://commonlyjs.com/cookbook/).

Roadmap
--------
### 1.x-next
* [x] Automate the package publication process and a generation of the package's documentation.
* [ ] Update every function's JSDoc to include [Damas–Hindley–Milner type](https://en.wikipedia.org/wiki/Hindley%E2%80%93Milner_type_system) signature.
* [ ] Implement a runtime type checking for every included function based on [Algorithm W](https://en.wikipedia.org/wiki/Hindley%E2%80%93Milner_type_system#Algorithm_W).
* [ ] Produce more content:
* [ ] Cookbook with simple recipes.
* [ ] Guidelines for contributors.
* [ ] Couple of articles:
* [ ] Introduction to the library.
* [ ] Improve stack traces and debugging for functions decorated with `curry`, `compose` and `partial`.
* [ ] Provide complete set of core packages:
* [ ] `@commonly/data`
* [ ] `@commonly/data/Deque`
* [ ] `@commonly/data/BinaryTree`
* [ ] `@commonly/data/Matrix`
* [ ] `@commonly/data/MultiwayTree`
* [ ] `@commonly/data/Stack`
* [ ] `@commonly/data/Queue`
* [ ] `@commonly/data/Vector`
* [ ] `@commonly/function`
* [x] `@commonly/function/compose`
* [x] `@commonly/function/curry`
* [x] `@commonly/function/debounce`
* [x] `@commonly/function/identity`
* [ ] `@commonly/function/memoize`
* [x] `@commonly/function/negate`
* [x] `@commonly/function/noop`
* [x] `@commonly/function/partial`
* [ ] `@commonly/function/pipe`
* [ ] `@commonly/function/reduced`
* [ ] `@commonly/function/reducer`
* [x] `@commonly/function/tap`
* [x] `@commonly/function/throttle`
* [ ] `@commonly/iterable`
* [ ] `@commonly/iterable/adjust`
* [ ] `@commonly/iterable/append`
* [x] `@commonly/iterable/chain`
* [ ] `@commonly/iterable/concat`
* [x] `@commonly/iterable/distinct`
* [x] `@commonly/iterable/drop`
* [x] `@commonly/iterable/dropWhile`
* [x] `@commonly/iterable/every`
* [x] `@commonly/iterable/filter`
* [x] `@commonly/iterable/find`
* [x] `@commonly/iterable/flatten`
* [x] `@commonly/iterable/head`
* [ ] `@commonly/iterable/includes`
* [ ] `@commonly/iterable/insert`
* [x] `@commonly/iterable/last`
* [x] `@commonly/iterable/map`
* [x] `@commonly/iterable/nth`
* [x] `@commonly/iterable/partition`
* [x] `@commonly/iterable/partitionBy`
* [ ] `@commonly/iterable/prepend`
* [ ] `@commonly/iterable/range`
* [x] `@commonly/iterable/reduce`
* [ ] `@commonly/iterable/repeat`
* [x] `@commonly/iterable/reverse`
* [x] `@commonly/iterable/size`
* [x] `@commonly/iterable/slice`
* [x] `@commonly/iterable/some`
* [x] `@commonly/iterable/sort`
* [x] `@commonly/iterable/tail`
* [x] `@commonly/iterable/take`
* [x] `@commonly/iterable/takeWhile`
* [x] `@commonly/iterable/transduce`
* [ ] `@commonly/iterable/zip`
* [ ] `@commonly/logic`
* [ ] `@commonly/logic/and`
* [ ] `@commonly/logic/nand`
* [ ] `@commonly/logic/not`
* [ ] `@commonly/logic/or`
* [ ] `@commonly/logic/xnor`
* [ ] `@commonly/logic/xor`
* [ ] `@commonly/math`
* [x] `@commonly/math/add`
* [ ] `@commonly/math/ceil`
* [x] `@commonly/math/decrement`
* [x] `@commonly/math/divide`
* [ ] `@commonly/math/floor`
* [x] `@commonly/math/increment`
* [x] `@commonly/math/maximum`
* [ ] `@commonly/math/mean`
* [ ] `@commonly/math/median`
* [x] `@commonly/math/minimum`
* [ ] `@commonly/math/modulo`
* [x] `@commonly/math/multiply`
* [ ] `@commonly/math/round`
* [x] `@commonly/math/subtract`
* [ ] `@commonly/number`
* [ ] `@commonly/number/clamp`
* [ ] `@commonly/number/inRange`
* [ ] `@commonly/number/random`
* [ ] `@commonly/reflect`
* [x] `@commonly/reflect/isArray`
* [x] `@commonly/reflect/isBoolean`
* [x] `@commonly/reflect/isError`
* [x] `@commonly/reflect/isFunction`
* [x] `@commonly/reflect/isMap`
* [x] `@commonly/reflect/isNil`
* [x] `@commonly/reflect/isNull`
* [x] `@commonly/reflect/isNumber`
* [x] `@commonly/reflect/isObject`
* [x] `@commonly/reflect/isPrimitve`
* [x] `@commonly/reflect/isPromise`
* [x] `@commonly/reflect/isReduced`
* [x] `@commonly/reflect/isRegExp`
* [x] `@commonly/reflect/isSet`
* [x] `@commonly/reflect/isString`
* [x] `@commonly/reflect/isSymbol`
* [x] `@commonly/reflect/isUndefined`
* [ ] `@commonly/string`
* [ ] `@commonly/string/camelcase`
* [ ] `@commonly/string/capitalize`
* [ ] `@commonly/string/constantcase`
* [ ] `@commonly/string/dashcase`
* [ ] `@commonly/string/lowercase`
* [ ] `@commonly/string/pascalcase`
* [ ] `@commonly/string/snakecase`
* [ ] `@commonly/string/traincase`
* [ ] `@commonly/string/trim`
* [ ] `@commonly/string/uppercase`
* [ ] `@commonly/string/words`
* [ ] `@commonly/transducer`
* [x] `@commonly/transducer/xchain`
* [ ] `@commonly/transducer/xconcat`
* [x] `@commonly/transducer/xdistinct`
* [x] `@commonly/transducer/xdrop`
* [x] `@commonly/transducer/xdropWhile`
* [x] `@commonly/transducer/xevery`
* [x] `@commonly/transducer/xfilter`
* [x] `@commonly/transducer/xfind`
* [x] `@commonly/transducer/xflatten`
* [x] `@commonly/transducer/xhead`
* [x] `@commonly/transducer/xlast`
* [x] `@commonly/transducer/xmap`
* [x] `@commonly/transducer/xnth`
* [x] `@commonly/transducer/xpartition`
* [x] `@commonly/transducer/xpartitionBy`
* [ ] `@commonly/transducer/xrange`
* [x] `@commonly/transducer/xrepeat`
* [x] `@commonly/transducer/xreverse`
* [x] `@commonly/transducer/xsize`
* [x] `@commonly/transducer/xslice`
* [x] `@commonly/transducer/xsome`
* [x] `@commonly/transducer/xsort`
* [x] `@commonly/transducer/xtail`
* [x] `@commonly/transducer/xtake`
* [x] `@commonly/transducer/xtakeWhile`
* [ ] `@commonly/type`
* [x] `@commonly/type/Comparator`
* [x] `@commonly/type/Identity`
* [x] `@commonly/type/Mapper`
* [x] `@commonly/type/Nil`
* [x] `@commonly/type/Predicate`
* [x] `@commonly/type/Primitive`
* [ ] `@commonly/type/Reduced`
* [x] `@commonly/type/Reducer`
* [x] `@commonly/type/Transducer`
* [ ] Provide complete set of auxiliary packages:
* [ ] `@commonly/async`
* [ ] `@commonly/dom`
* [ ] `@commonly/fs`
* [ ] Enable interoperability with data structures from popular JavaScript libraries:
* [ ] Immutable: [Immutable.js](https://github.com/immutable-js/immutable-js)
* [ ] Immutable: [mori](https://github.com/swannodette/mori)
* [ ] Stream/Observable: [RxJS](https://github.com/ReactiveX/rxjs)
* [ ] Stream/Observable: [Most](https://github.com/cujojs/most)
* [ ] Stream/Observable: [flyd](https://github.com/paldepind/flyd)