@typed/fp
Version:
Data Structures and Resources for fp-ts
381 lines • 9.21 kB
JavaScript
/**
* `Ref` is an abstraction for managing data-driven applications using [Env](./Env.ts.md).
* @since 0.11.0
*/
import * as Ap from 'fp-ts/Apply';
import * as B from 'fp-ts/boolean';
import { EqStrict } from 'fp-ts/Eq';
import { flow, pipe } from 'fp-ts/function';
import { concatAll } from 'fp-ts/Monoid';
import * as RA from 'fp-ts/ReadonlyArray';
import * as E from './Env';
import * as EO from './EnvOption';
import * as KV from './KV';
import * as O from './Option';
import * as RS from './ReaderStream';
import * as RSO from './ReaderStreamOption';
import * as S from './struct';
const allBooleans = E.map(concatAll(B.MonoidAll));
/**
* @since 0.11.0
* @category URI
*/
export const URI = '@typed/fp/Ref';
/**
* @since 0.11.0
* @category Constructor
*/
export const fromKV = (kv) => ({
...kv,
get: KV.get(kv),
has: KV.has(kv),
set: KV.set(kv),
update: KV.update(kv),
remove: KV.remove(kv),
values: KV.listenToValues(kv),
});
/**
* @since 0.11.0
* @category Constructor
*/
export const kv = flow(KV.make, fromKV);
/**
* @since 0.12.0
* @category Instance Constructor
*/
export const FromKV = {
fromKV,
};
/**
* @since 0.11.0
* @category Combinator
*/
export const map = (f) => (ref) => ({
get: pipe(ref.get, E.map(f)),
has: ref.has,
set: flow(ref.set, E.map(f)),
update: (g) => pipe(ref.get, E.map(f), E.chainW(g), E.chainW(ref.set), E.map(f)),
remove: pipe(ref.remove, EO.map(f)),
values: pipe(ref.values, RSO.map(f)),
});
/**
* @since 0.11.0
* @category Instance
*/
export const Functor = {
map,
};
/**
* @since 0.11.0
* @category Combinator
*/
export const local = (f) => (ref) => ({
get: ref.get,
has: ref.has,
set: flow(f, ref.set),
update: (g) => ref.update(flow(g, E.map(f))),
remove: ref.remove,
values: ref.values,
});
/**
* @since 0.12.2
* @category Combinator
*/
export const localE = (f) => (ref) => ({
get: ref.get,
has: ref.has,
set: flow(f, E.chainW(ref.set)),
update: (g) => ref.update(flow(g, E.chainW(f))),
remove: ref.remove,
values: ref.values,
});
/**
* @since 0.11.0
* @category Combinator
*/
export const promap = (f, g) => (ref) => pipe(ref, local(f), map(g));
/**
* @since 0.12.2
* @category Combinator
*/
export const promapE = (f, g) => (ref) => pipe(ref, localE(f), chainEnvK(g));
/**
* @since 0.11.0
* @category Instance
*/
export const Profunctor = {
map,
promap,
};
/**
* @since 0.11.0
* @category Combinator
*/
export const ap = (fa) => (fab) => {
const get = pipe(fab.get, E.apW(fa.get));
const set = (i) => pipe(i, fab.set, E.apW(fa.set(i)));
return {
get,
has: pipe([], E.of, E.apTW(fa.has), E.apTW(fab.has), allBooleans),
set: (i) => pipe(i, fab.set, E.apW(fa.set(i))),
update: (f) => pipe(get, E.chainW(f), E.chainW(set)),
remove: pipe(fab.remove, EO.apW(fa.remove)),
values: pipe(fab.values, RSO.apW(fa.values)),
};
};
/**
* @since 0.11.0
* @category Instance
*/
export const Apply = {
map,
ap,
};
/**
* @since 0.11.0
* @category Combinator
*/
export const apFirst = Ap.apFirst(Apply);
/**
* @since 0.11.0
* @category Combinator
*/
export const apFirstW = apFirst;
/**
* @since 0.11.0
* @category Combinator
*/
export const apS = Ap.apS(Apply);
/**
* @since 0.11.0
* @category Combinator
*/
export const apSW = apS;
/**
* @since 0.11.0
* @category Combinator
*/
export const apSecond = Ap.apSecond(Apply);
/**
* @since 0.11.0
* @category Combinator
*/
export const apSecondW = apSecond;
/**
* @since 0.11.0
* @category Combinator
*/
export const apT = Ap.apT(Apply);
/**
* @since 0.11.0
* @category Combinator
*/
export const apTW = apT;
/**
* @since 0.11.0
* @category Typeclass Constructor
*/
export const getApplySemigroup = Ap.getApplySemigroup(Apply);
/**
* @since 0.11.0
* @category Combinator
*/
export const compose = (second) => (first) => ({
get: pipe(second.get, E.apFirstW(first.get)),
has: pipe(first.has, E.tupled, E.apTW(second.has), allBooleans),
set: flow(first.set, E.chainW(second.set)),
update: (f) => pipe(second.get, E.chainW(f), E.chainW(first.set), E.chainW(second.set)),
remove: pipe(second.remove, E.apFirstW(first.remove)),
values: pipe(second.values, RS.mergeFirst(
// Replicate all values into the second
pipe(first.values, RS.chainFirstEnvK(O.matchW(() => second.remove, flow(second.set, EO.fromEnv))))), RS.skipRepeatsWith(O.getEq(EqStrict))),
});
/**
* @since 0.11.0
* @category Instance
*/
export const Semigroupoid = {
compose,
};
/**
* @since 0.11.0
* @category Combinator
*/
export const provideSome = (provided) => (ref) => {
return {
get: pipe(ref.get, E.provideSome(provided)),
has: pipe(ref.has, E.provideSome(provided)),
set: flow(ref.set, E.provideSome(provided)),
update: flow(ref.update, E.provideSome(provided)),
remove: pipe(ref.remove, E.provideSome(provided)),
values: pipe(ref.values, RS.provideSome(provided)),
};
};
/**
* @since 0.11.0
* @category Combinator
*/
export const provideAll = provideSome;
/**
* @since 0.11.0
* @category Combinator
*/
export const useSome = (provided) => (ref) => {
return {
get: pipe(ref.get, E.useSome(provided)),
has: pipe(ref.has, E.useSome(provided)),
set: flow(ref.set, E.useSome(provided)),
update: flow(ref.update, E.useSome(provided)),
remove: pipe(ref.remove, E.useSome(provided)),
values: pipe(ref.values, RS.useSome(provided)),
};
};
/**
* @since 0.11.0
* @category Combinator
*/
export const useAll = useSome;
/**
* @since 0.11.0
* @category Instance
*/
export const UseSome = {
useSome,
};
/**
* @since 0.11.0
* @category Instance
*/
export const UseAll = {
useAll,
};
/**
* @since 0.11.0
* @category Instance
*/
export const ProvideSome = {
provideSome,
};
/**
* @since 0.11.0
* @category Instance
*/
export const ProvideAll = {
provideAll,
};
/**
* @since 0.11.0
* @category Instance
*/
export const Provide = {
useSome,
useAll,
provideSome,
provideAll,
};
/**
* @since 0.11.0
* @category Combinator
*/
export function chainEnvK(f) {
return (ref) => ({
get: pipe(ref.get, E.chainW(f)),
has: ref.has,
set: flow(ref.set, E.chainW(f)),
update: (g) => pipe(flow(f, E.chainW(g)), ref.update, E.chainW(f)),
remove: pipe(ref.remove, EO.chainEnvK(f)),
values: pipe(ref.values, RSO.chainEnvK(f)),
});
}
/**
* @since 0.11.0
* @category Combinator
*/
export function chainFirstEnvK(f) {
return (ref) => ({
get: pipe(ref.get, E.chainFirstW(f)),
has: ref.has,
set: flow(ref.set, E.chainFirstW(f)),
update: flow(ref.update, E.chainFirstW(f)),
remove: pipe(ref.remove, EO.chainFirstEnvK(f)),
values: pipe(ref.values, RSO.chainFirstEnvK(f)),
});
}
/**
* @since 0.11.0
* @category Combinator
*/
export function chainIOK(f) {
return pipe(f, E.fromIOK, chainEnvK);
}
/**
* @since 0.11.0
* @category Combinator
*/
export function chainFirstIOK(f) {
return pipe(f, E.fromIOK, chainFirstEnvK);
}
/**
* @since 0.11.0
* @category Combinator
*/
export function chainReaderK(f) {
return pipe(f, E.fromReaderK, chainEnvK);
}
/**
* @since 0.11.0
* @category Combinator
*/
export function chainFirstReaderK(f) {
return pipe(f, E.fromReaderK, chainFirstEnvK);
}
/**
* @since 0.11.0
* @category Combinator
*/
export function chainResumeK(f) {
return pipe(f, E.fromResumeK, chainEnvK);
}
/**
* @since 0.11.0
* @category Combinator
*/
export function chainFirstResumeK(f) {
return pipe(f, E.fromResumeK, chainFirstEnvK);
}
/**
* @since 0.11.0
* @category Combinator
*/
export function chainTaskK(f) {
return pipe(f, E.fromTaskK, chainEnvK);
}
/**
* @since 0.11.0
* @category Combinator
*/
export function chainFirstTaskK(f) {
return pipe(f, E.fromTaskK, chainFirstEnvK);
}
/**
* @since 0.11.0
* @category Combinator
*/
export function struct(properties) {
const entries = Object.entries(properties);
const zipAssign = flow(E.zipW, E.map((props) => Object.assign({}, ...props)));
const get = pipe(entries, RA.map(([k, ref]) => pipe(ref.get, E.map((v) => S.make(k, v)))), zipAssign);
const has = pipe(Object.values(properties), RA.map((ref) => ref.has), E.zipW, allBooleans);
const set = (i) => pipe(i, Object.entries, RA.map(([k, v]) => pipe(v, properties[k].set, E.map((v) => S.make(k, v)))), zipAssign);
const remove = pipe(entries, RA.map(([k, ref]) => pipe(ref.remove, EO.map((v) => S.make(k, v)))), E.zipW, E.map(flow(O.traverseReadonlyArrayWithIndex((_, a) => a), O.map((xs) => Object.assign({}, ...xs)))));
const values = pipe(RS.combineAll(...pipe(entries, RA.map(([k, ref]) => pipe(ref.values, RSO.map((v) => S.make(k, v)))))), RS.map(flow(O.traverseReadonlyArrayWithIndex((_, a) => a), O.map((xs) => Object.assign({}, ...xs)))));
return {
get,
has,
set,
update: (f) => pipe(get, E.chainW(f), E.chainW(set)),
remove,
values,
};
}
//# sourceMappingURL=Ref.js.map