fp-ts-std
Version:
The missing pseudo-standard library for fp-ts.
100 lines (99 loc) • 3.63 kB
JavaScript
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;
};