Unction.js
[DEPRECATED] A set of type annotated FP functions that enforce currying and composability
Install / Use
/learn @krainboltgreene/Unction.jsREADME
DEPRECATED: This library is too large to keep in one repository. I have moved to a multi-repository solution: github.com/unctionjs
@unction/*
A set of very useful function. These functions are bound by these principles:
- All functions will have type annotations.
- All functions will only take a single argument.
- All functions are curried.
- All inner functions will be named based on the outer function and it's argument name.
- Functions that deal with key values will take KeyChains (a list of keys).
- Functions that deal with types will take their string name form.
- Functions that mutate the original value, though rare, will have a suffix of
M. - Functions that take or return promises will have a suffix of
P. - Functions that can work on one type of Iterable can work on another type, covering: - List (Array, Set, WeakSet) - Record (object, Map, WeakMap) - String - Stream (xstream)
![Tests][BADGE_TRAVIS] ![Stability][BADGE_STABILITY] ![Dependencies][BADGE_DEPENDENCY]
using
Each function is a unique package with it's own source, transpiliation, and tests. To get a function simply install:
$ npm install --save-dev @unction/hammer@latest
and then import:
import hammer from "@unction/hammer"
@unction/allObjectP
({[key: KeyType]: any | Promise<any>}) => Promise<{[key: KeyType]: any}>
This takes an object where the values are probably promises and returns a promise that has that same object but with the resolved values.
Here's a good example of this function in use:
function signUp (attributes, slug) {
return function thunk (dispatch, getState, {client}) {
return allObjectP({
loading: startLoading(slug),
session: pushSession(attributes, client)
})
.then(({session}) => {
return allObjectP({
merge: mergeResource(session),
current: storeCurrent(session.id),
account: pullAccount(session.relationship.account.data.id, client),
})
})
.then(({account}) => {
return {
merge: mergeResource(account),
current: storeCurrent(account.id),
}
})
.then(() => stopLoading(slug))
.then(() => dispatch({type: "signUp"}))
.catch(logger.error.bind(error))
}
}
If we use allP or Promise.all we're getting an array back, but that's annoying to destructure. The allObjectP function gives us the concurrency we want with a named interface for the returned resolutions.
@unction/allP
Array<any | Promise<any>> -> Promise<Array<any>>
A port of the Promise.all() function.
Credit: @keithamus
@unction/always
any -> any -> any
Always returns the value given when called
always(1)() // 1
always(1)(0) // 1
@unction/append
any -> Array<any> -> Array<any>
Takes a value and puts it at the end of the given list
append(4)([5]) // => [5, 4]
@unction/appendM
any -> Array<any> -> Array<any>
Takes an array and an item and returns the combination of both, appended.
NOTE: This mutates the array
const data = [1, 2, 3]
appendM(4)(data)
Would return:
[1, 2, 3, 4]
@unction/applicator
(ValueType -> any) -> any
Takes a function and a value and applies that function to that value.
applicator(inc)(1) // 1
@unction/applicators
Iterable<ValueType -> ValueType> -> Iterable<ValueType> -> Array<ValueType>
Takes a list of functions and a list of values and applies the values to the functions.
applicators([
recordfrom(["point", "x"]),
recordfrom(["point", "y"]),
recordfrom(["point", "z"]),
])([
40.453,
2.2,
423.0,
])
returns
[
{point: {x: 40.453}},
{point: {y: 2.2}},
{point: {z: 423.0}},
]
applicators({
x: inc,
y: dec
})({
x: -1,
y: 1
})
returns
{
x: 0,
y: 0
}
@unction/arrayify
any -> [any] | Array<any>
Takes a value and turns it into an array of that value, unless the value is already an array.
arrayify("a")
returns
["a"]
arrayify(["a"])
returns
["a"]
@unction/aside
Array<(any => any)> -> any -> any
Use this function to do thing aside of a main pipeline.
export default function generateGraph () {
return pipe(
aside([format, log]),
processData
)
}
@unction/attach
KeyType -> ValueType -> IterableType -> IterableType
A polymorphic way to attach a value to an iterable
attach("hello")("world")({}) // => {hello: "world"}
@unction/cascadingKeyChain
Array<UnfinishedKeyChainType> -> IterableType -> ValueType
Cascades through multiple keychains in order to arrive at a value. Null keys are replaced with the previous keychain's value.
cascadingKeyChain(
[
["ephemeral", "current", "session"],
["resources", "sessions", null, "relationships", "account", "data", "id"],
["resources", "accounts", null, "attributes", "name"]
]
)(
{
ephemeral: {current: {session: "1"}},
resources: {
sessions: {
1: {
id: "1",
relationships: {account: {data: {id: "2"}}},
},
},
accounts: {
2: {
id: "2",
attributes: {name: "Kurtis Rainbolt-Greene"},
},
},
},
}
)
returns
"Kurtis Rainbolt-Greene"
@unction/catchP
(any -> any) -> Promise<any> -> Promise<any>
A port of the Promise.prototype.catch() function.
Credit: @keithamus
@unction/compact
Array<any> -> Array<mixed>
Takes a collection (Array or Object) and returns a copy of that value without null or undefined values.
avatarUrls // => [null, "/1.jpg", null, "/3.jpg"]
compact(avatarUrls) // => ["/1.jpg", "/3.jpg"]
head(users) // {"avatar": null, "name": "Kurtis Rainbolt-Greene"}
compact(head(users)) // {"name": "Kurtis Rainbolt-Greene"}
@unction/computedProp
(IterableType -> any) -> Keychain -> IterableType -> IterableType
Given an object this function will return that object but with a new property, where the value is computed. The computation is given the object you'll be copying.
const computer = ({id, attributes: {username}}) => `${username}#${id}`
const key = "tag"
const payload = {
id: "1",
attributes: {
username: "krainboltgreene"
}
}
computedProp(computer)(key)(payload)
Would return:
{
id: "1",
tag: "krainboltgreene#1",
attributes: {
username: "krainboltgreene"
}
}
const multiKey = ["attributes", "tag"]
computedProp(computer)(key)(payload)
Would return:
{
id: "1",
attributes: {
tag: "krainboltgreene#1",
username: "krainboltgreene"
}
}
@unction/couple
any -> any -> [any, any]
Takes any value and then any value and returns an array containing those values.
couple(4)(5) // => [4, 5]
@unction/domEvents
DOMEventsConfigurationType -> DOMEventNameType -> DOMStreamType -> DOMEventStreamType
Takes a configuration, an event name, and a DOM source and returns an observable of that event type
domEvents({})("click")(DOM)
returns
--click--click--click-->
@unction/domEventsMany
domEventsManyConfigurationType -> (string | Array<DOMEventNameType>) -> DOMEventStreamType
Takes many events or * and returns an observable of those events
domEventsMany({})(["click", "input"])(DOM)
returns
--click--input--input--click--input
domEventsMany({})("*")(DOM)
returns
--click--input--hover--change--click-->
@unction/endsWith
string -> string -> boolean
Determines if a given subset of text is at the end of another set of text.
endsWith("!")("Hello, world!") // true
@unction/everyP
(Array<any | Promise<any>>) -> Promise<[ResolvedPromisesType, RejectedPromisesType]>
Returns both resolved and rejected promises as distinct lists.
@unction/flattenTree
((any -> any) -> IterableType -> IterableType) -> (any -> any) -> number -> IterableType -> IterableType
Takes a tree and creates a single object where the root keys are conjoined nested keys.
flattenTree({
data: {
profile: {
name: "Kurtis Rainbolt-Greene"
age: 24
},
metadata: {
interval: "10s"
},
location: "http://api.example.com/profiles/24"
}
})
Would return:
{
"data-profile-name": "Kurtis Rainbolt-Greene",
"data-profile-age": 24,
"data-interval": "10s",
"data-location": "Kurtis Rainbolt-Greene"
}
@unction/flip
(any -> any) -> any -> any -> any
Flips a function's first and second arguments.
flip(key)({aaa: "1"})("aaa") // "1"
@unction/forEach
(any -> KeyType -> any) -> IterableType -> IterableType
Takes any kind of iterable object and figures out the best way to iterate over it.
forEach((x) => y)([])
forEach((x) => y)(new Map)
forEach((x) => y)({})
@unction/fresh
IterableType -> IterableType
Takes a iterable and returns an empty fresh version of that iterable.
fresh({aaa: "aaa"}) // {}
fresh(["aaa"]) // []
fresh({}) // {}
fresh([]) // []
@unction/hammer
KeyType -> IterableType -> IterableType
Use this to de-nest a nested object.
const payload = {
id: 1
attributes: {
name: "Kurtis Rainbolt-Greene",
age: 26
}
}
hammer("attributes")(payload)
Which returns:
{
id: 1,
name: "Kurtis Rainbolt-Greene",
age: 26
}
@unction/ifThenElse
PredicateType -> (any -> any) -> (any -> any) -> any
Based on a predicate it passes the value to a consequent or alternative fun
