sanctuary-lourdes

An utils library created by and for Sanctuary

Usage no npm install needed!

<script type="module">
  import sanctuaryLourdes from 'https://cdn.skypack.dev/sanctuary-lourdes';
</script>

README

Sanctuary Lourdes

An utils library created by and for Sanctuary

Get started

Installation

npm i sanctuary-lourdes
# OR
yarn add sanctuary-lourdes

Usage

create instance of Sanctuary Lourdes near your instance of Sanctuary

import sanctuary from 'sanctuary';
import {create} from 'sanctuary-lourdes';

const CHECK_TYPES_SANCTUARY = process.env.CHECK_TYPES_SANCTUARY === 'true';

const S = sanctuary.create ({
  checkTypes: CHECK_TYPES_SANCTUARY,
  env: sanctuary.env
});

const Sl = create({checkTypes: CHECK_TYPES_SANCTUARY});

API

Array

nth :: NonNegativeInteger -> Array a -> Maybe a

Get the N th elements of array

> Sl.nth (0) ([])
Nothing

> Sl.nth (1) ([1, 2, 3])
Just (2)

> Sl.nth (7) ([1, 2, 3])
Nothing

indexOf :: a -> Array a -> Maybe NonNegativeInteger

Get the first index of an array which corresponding to an item

> Sl.indexOf ('red') (['red', 'green', 'blue'])
Just (0)

> Sl.indexOf ('yellow') (['red', 'green', 'blue'])
Nothing

> Sl.indexOf ({name: "white", hex: "#fff"})
.            ([{name: "white", hex: "#fff"}, {name: "black", hex: "#000"}])
Just (0)

splitEach :: PositiveInteger -> Array a -> Array Array a

Split an array on sub-array of size N

> Sl.splitEach (3) ([1, 2, 3, 4, 5, 6, 7, 8, 9])
[[1, 2, 3], [4, 5, 6], [7, 8, 9]]

> Sl.splitEach (2) ([1, 2, 3, 4, 5, 6, 7])
[[1, 2], [3, 4], [5, 6], [7]]

intersperse :: a -> Array a -> Array a

Separate each item by an item.

> Sl.intersperse ("b") (["a", "c"])
["a", "b", "c"]

> Sl.intersperse ("b") (["a"])
["a"]

> Sl.intersperse ("b") ([])
[]

Regex

extractString :: Regex -> String -> Maybe String

Get the first group match in a string

> const extractStringExample = Sl.extractString (/hello ([a-z]*)!/);

> extractStringExample ('hello john!')
Just ("john")

> extractStringExample ('hello bob!')
Just ("bob")

> extractStringExample ('hello 123!')
Nothing

> extractStringExample ('hi john!')
Nothing

replace :: Regex -> String -> String -> String

Replace a substring with a RegExp

> Sl.replace (/bob/) ('john') ('hello bob')
"hello john"

> Sl.replace (/a/gi) ('o') ('Aaaaahhhh')
"ooooohhhh"

Logic

allPass :: Array (a -> Boolean) -> a -> Boolean

Return true if all predicates return true, else return false

> const isEvenNumber = x => x%2 === 0;
> const isPositiveNumber  = x => x > 0;
> const isPositiveEvenNumber = Sl.allPass ([isEvenNumber, isPositiveNumber]);

> isPositiveEvenNumber (0)
false

> isPositiveEvenNumber (1)
false

> isPositiveEvenNumber (-2)
false

> isPositiveEvenNumber (2)
true

anyPass :: Array (a -> Boolean) -> a -> Boolean

Return true if one of predicates return true, else return false

> const isSix = x => x === 6;
> const isNegative  = x => x < 0;
> const isNegativeOrSix = Sl.anyPass ([isNegative, isSix]);

> isNegativeOrSix (0)
false

> isNegativeOrSix (1)
false

> isNegativeOrSix (-2)
true

> isNegativeOrSix (6)
true

cond :: Array Pair (a -> Boolean) (a -> b) -> a -> Either a b

Apply transformer predicate return true anc return a Right value If any predicate return true, it will return initial value in Left Value

> const condExample = Sl.cond ([
.   S.Pair (S.test (/^[a-zA-Z]+$/)) (S.toUpper),
.   S.Pair (S.test (/[a-zA-Z]+/)) (S.toLower),
. ]);

> condExample ('hello')
Right ("HELLO")

> condExample ('HELLO!')
Right ("hello!")

> condExample ('123!')
Left ("123!")

Lens

Use implementation created by David Chambers

view :: Lens s a -> s -> a

Allow to get a value by a Lens

> const email = Sl.lens (user => user.email) (email => user => ({...user, email}));
> const user = {id: 1, email: 'dc@davidchambers.me'};

> Sl.view (email) (user)
dc@davidchambers.me

over :: Lens s a -> (a -> a) -> s -> s

Allow to set a value by a Lens

> const email = Sl.lens (user => user.email) (email => user => ({...user, email}));
> const user = {id: 1, email: 'dc@davidchambers.me'};

> Sl.over (email) (S.toUpper) (user)
{id: 1, email: 'DC@DAVIDCHAMBERS.ME'}

lensProp :: String -> Lens s a

Create a Lens for an object property

> const user = {id: 1, email: 'dc@davidchambers.me'};

> Sl.view (Sl.lensProp('email')) (user)
'dc@davidchambers.me'

> Sl.over (Sl.lensProp('email')) (S.toUpper) (user)
{id: 1, email: 'DC@DAVIDCHAMBERS.ME'}

lensProps :: Array String -> Lens s a

Create a Lens for an object property path

> const example = {a: {b: {c: 1}}};

> Sl.view (Sl.lensProps (['a', 'b', 'c']))
.         (example)
1

> Sl.over (Sl.lensProps (['a', 'b', 'c']))
.         (S.add (1))
.         (example)
{a: {b: {c: 2}}}

Maybe

toMaybe :: (a -> Boolean) -> a -> Maybe a

Wrapping value in Maybe depending on predicate

> Sl.toMaybe (x => !!x) (null)
Nothing

> Sl.toMaybe (x => !!x) (undefined)
Nothing

> Sl.toMaybe (x => !!x) (1)
Just (1)

Either

toEither :: (a -> Boolean) -> (a -> b) -> a -> Either b a

Convert to Either depending on predicate

> const toEven = Sl.toEither (x => x % 2 === 0)
.                            (x => `${x} is not a even number`);

> toEven (1)
Left ("1 is not a even number")

> toEven (2)
Right (2)

Fluture

flMap :: PositiveInteger -> (a -> Fluture b c) -> Array a -> Fluture b Array c

Apply a function that return a Fluture on each item of an array and return a Fluture

> const array = [1, 2, 3, 4, 5];
> const f1 = Sl.flMap (1) (x => resolve (1 + x)) (array);
> const f2 = Sl.flMap (1) (x => reject ("error: " + x)) (array);

> fork (log ('rejection')) (log ('resolution')) (f1)
[resolution]: [2, 3, 4, 5, 6]

> fork (log ('rejection')) (log ('resolution')) (f2)
[rejection]: "error: 1"

toFluture :: (a -> Boolean) -> (a -> b) -> a -> Fluture b a

Convert to a Fluture depending on predicate

> const toOdd = Sl.toFluture (x => x % 2 !== 0)
.                            (x => `${x} is not a odd number`);

> fork (log ('rejection')) (log ('resolution')) (toOdd (2))
[rejection]: "2 is not a odd number"

> fork (log ('rejection')) (log ('resolution')) (toOdd (1))
[resolution]: 1

maybeToFluture :: b -> Maybe a -> Fluture b a

Convert a Maybe to a Fluture

> const f1 = Sl.maybeToFluture ("not a number") (S.Just (1));
> const f2 = Sl.maybeToFluture ("not a number") (S.Nothing);

> fork (log ('rejection')) (log ('resolution')) (f1)
[resolution]: 1

> fork (log ('rejection')) (log ('resolution')) (f2)
[rejection]: "not a number"

eitherToFluture :: Either a b -> Fluture a b

Convert an Either to a Fluture

> const f1 = Sl.eitherToFluture (S.Right (1));
> const f2 = Sl.eitherToFluture (S.Left ("error"));

> fork (log ('rejection')) (log ('resolution')) (f1)
[resolution]: 1

> fork (log ('rejection')) (log ('resolution')) (f2)
[rejection]: "error"