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

lorgnette

v1.2.0

Published

Lenses. Helpers for immutable collections.

Downloads

238

Readme

lorgnette

NPM Version NPM License Build Status Coverage Status

A set of lenses

Lenses are helper objects to retrieve or update data in immutable collections.

Basics

Lens is an object which allows to access object properties. Any lens has to implement next three methods:

get(obj)                // returns extracted property

set(obj, value)         // clones object and returns it with altered property

update(obj, callback)   // same as set but callback is called to get new value

Methods get and update return new object instead of modifying given one.

Maybe

Method get returns a value wrapped in Maybe monad. Maybe instance has following methods:

isJust()
isNothing()
getOr(orElse)           // unpacks value or returns `orElse`
then(func)              // also known as `bind`, `>>=` or `flatMap`
recover(func)           // calls given callback for `Nothing` only

Some examples:

import {nothing, just} from 'lorgnette';

just('value').getOr('anotherValue')     // returns 'value'
nothing.getOr('anotherValue')           // returns 'anotherValue'


function appendBang(s) {
  return just(s + '!');
}

nothing.then(appendBang)                // returns Nothing
just('value').then(appendBang)          // returns Just('value!')
just('value').then(() => nothing))      // returns Nothing

nothing.recover(() => 42)               // returns Just(42)
just('value').recover(() => 42)         // returns just('value')

Predefined lenses

prop

Lens prop allows access to object properties by name.

import { lens } from 'lorgnette';

let age = lens.prop('age'); // create lens to access property age

age.get({name: 'John'}) // returns Nothing

age.get({name: 'John', age: 42}) // returns Just(42)

age.set({name: 'John', age: 42}, 24) // returns {name: 'John', age: 24}

age.update({name: 'John', age: 42}, x => x + 1) // returns {name: 'John', age: 43}

This lens can also be configured to return default value instead of Nothing when property does not exist.

import { lens } from 'lorgnette';

let age = lens.prop('age', 18); // create lens to access property age

age.get({name: 'John'}) // returns Just(18)

age.get({name: 'John', age: 42}) // returns Just(42)

at

Lens at allows access to array elements by given index.

import { lens } from 'lorgnette';

let second = lens.at(1);

second.get([]) // returns Nothing

second.get([1, 2, 3, 4, 5]) // returns Just(2)

second.set([1, 2, 3, 4, 5], 7) // returns [1, 7, 3, 4, 5]

second.update([1, 2, 3, 4, 5], x => x + 7) // returns [1, 9, 3, 4, 5]


// negative index is also accepted
let last = lens.at(-1);

last.get([1, 2, 3, 4, 5]) // returns Just(5)

last.set([1, 2, 3, 4, 5], 7) // returns [1, 2, 3, 4, 7]

first

Lens first is similar to at(0) but it prepends new value when set or update is called.

import { lens } from 'lorgnette';

let first = lens.first();

first.get([]) // returns Nothing

first.get([1, 2, 3, 4, 5]) // returns Just(1)

first.set([1, 2, 3, 4, 5], 7) // returns [7, 1, 2, 3, 4, 5]

first.update([1, 2, 3, 4, 5], x => '' + x) // returns ['undefined', 1, 9, 3, 4, 5]

last

Lens last is similar to at(-1) but it appends new value when set or update is called.

import { lens } from 'lorgnette';

let last = lens.last();

last.get([]) // returns Nothing

last.get([1, 2, 3, 4, 5]) // returns Just(5)

last.set([1, 2, 3, 4, 5], 7) // returns [1, 2, 3, 4, 5, 7]

last.update([1, 2, 3, 4, 5], x => '' + x) // returns [1, 9, 3, 4, 5, 'undefined']

firstOf/lastOf

Lenses firstOf / lastOf allow access to array elements by predicate. firstOf' looks for an element satisfying a predicate from the beginning of an array. lastOf` does the same but searched backward.

import { lens } from 'lorgnette';

let second = lens.firstOf(obj => obj.id === 2);

second.get([]) // returns Nothing

second.get([{id: 1}, {id: 2}, {id: 3}, {id: 4}, {id: 5}]) // returns Just({id: 2})

second.set([{id: 1}, {id: 2}, {id: 3}, {id: 4}, {id: 5}], 7) // returns [{id: 1}, 7, {id: 3}, {id: 4}, {id: 5}]

second.update([{id: 1}, {id: 2, x: 4}, {id: 3}, {id: 4}, {id: 5}], ({x}) => x + 7) // returns [{id: 1}, 11, {id: 3}, {id: 4}, {id: 5}]

Chaining

Lenses can be chained so access to nested properties is possible.

import { lens } from 'lorgnette';

let lastCartItem = lens.prop('items', []).last();

let cart = {
  items: [
    'potato',
    'cheese'
  ]
};

lastCartItem.get(cart) // returns Just('cheese')
lastCartItem.set(cart, 'carrot') // returns { items: ['potato', 'cheese', 'carrot'] }

Multilens

Sometimes it is usefull to access multiple properties at once. Multilens allows to do this.

import { lens, multi } from 'lorgnette';

let lastCartItem = lens.prop('items', []).last();
let totalCount = lens.prop('total');
let cartLens = multi(lastCartItem, totalCount);

let cart = {
  total: 2,
  items: [
    'potato',
    'cheese'
  ]
};

cartLens.get(cart) // returns [Just('cheese'), Just(2)]

cartLens.set(cart, 'carrot', 3)
// returns
// {
//   total: 3,
//   items: ['potato', 'cheese', 'carrot']
// }

cartLens.update(cart, () => 'carrot', x => x + 1)
// returns
// {
//   total: 3,
//   items: ['potato', 'cheese', 'carrot']
// }