UNPKG

fp-ts-std

Version:

The missing pseudo-standard library for fp-ts.

100 lines (99 loc) 3.63 kB
import * as M from "fp-ts/Map"; import * as NEA from "fp-ts/NonEmptyArray"; import * as O from "fp-ts/Option"; import { not } from "fp-ts/Predicate"; import * as R from "fp-ts/Record"; import { constant, flow, pipe } from "fp-ts/function"; import { invoke, isInstanceOf, uncurry2, when } from "./Function"; import * as A from "fp-ts/Array"; import { mapSnd } from "fp-ts/Tuple"; import * as Str from "fp-ts/string"; import { fromIterable, getDisorderedEq } from "./Array"; import { prepend } from "./String"; import { withFst } from "./Tuple"; const constructor = (x) => new URLSearchParams(x); export const empty = constructor(undefined); export const isEmpty = u => Array.from(u.keys()).length === 0; export const fromString = constructor; export const toString = (x) => x.toString(); export const toLeadingString = flow(toString, when(not(Str.isEmpty))(prepend("?"))); export const fromTuples = constructor; export const singleton = (k) => (v) => fromTuples([[k, v]]); export const toTuples = (x) => pipe(x.entries(), fromIterable); export const fromRecord = flow(R.foldMapWithIndex(Str.Ord)(A.getMonoid())((k, vs) => pipe(vs, A.map(withFst(k)))), fromTuples); export const toRecord = (x) => R.fromFoldableMap(NEA.getSemigroup(), A.Foldable)(toTuples(x), mapSnd(NEA.of)); const EqValues = getDisorderedEq(Str.Ord); export const Eq = { equals: (xs, ys) => { if (size(xs) !== size(ys)) return false; const ks = pipe(xs, keys, A.concat(keys(ys)), A.uniq(Str.Eq)); for (const k of ks) { const mxvs = lookup(k)(xs); const myvs = lookup(k)(ys); if (O.isNone(mxvs) || O.isNone(myvs)) return false; if (!EqValues.equals(mxvs.value, myvs.value)) return false; } return true; }, }; export const clone = constructor; export const isURLSearchParams = isInstanceOf(URLSearchParams); export const lookupFirst = (k) => flow(invoke("get")([k]), O.fromNullable); export const getParam = lookupFirst; export const lookup = (k) => flow(invoke("getAll")([k]), NEA.fromArray); export const getAllForParam = lookup; export const upsertAt = (k) => (v) => (x) => { const y = clone(x); y.set(k, v); return y; }; export const setParam = upsertAt; export const appendAt = (k) => (v) => (x) => { const y = clone(x); y.append(k, v); return y; }; export const deleteAt = (k) => x => { const y = clone(x); y.delete(k); return y; }; export const keys = (x) => fromIterable(x.keys()); export const values = (x) => fromIterable(x.values()); export const size = (x) => x.size; export const concatBy = (f) => (xs) => ys => { const zs = clone(empty); const ks = pipe(xs, keys, A.concat(keys(ys)), A.uniq(Str.Eq)); for (const k of ks) { const xvs = xs.getAll(k); const yvs = ys.getAll(k); const zvs = A.isNonEmpty(xvs) && A.isNonEmpty(yvs) ? f(k)([xvs, yvs]) : A.concat(yvs)(xvs); for (const zv of zvs) zs.append(k, zv); } return zs; }; export const Semigroup = { concat: (x, y) => concatBy(constant(uncurry2(A.concat)))(x)(y), }; export const Monoid = { ...Semigroup, empty, }; export const fromMap = flow(M.foldMapWithIndex(Str.Ord)(A.getMonoid())((k, vs) => pipe(vs, A.map(withFst(k)))), fromTuples); export const toMap = (x) => { const m = new Map(); for (const [k, v] of x.entries()) { const prev = M.lookup(Str.Eq)(k)(m); if (O.isSome(prev)) m.set(k, A.append(v)(prev.value)); else m.set(k, NEA.of(v)); } return m; };