UNPKG

@effect-ts/system

Version:

Effect-TS is a zero dependency set of libraries to write highly productive, purely functional TypeScript at scale.

174 lines (159 loc) 4.81 kB
// ets_tracing: off /** * Copyright 2020 Michael Arnaldi and the Matechs Garage Contributors. */ import * as A from "../Collections/Immutable/Array/index.js" import * as R from "../Collections/Immutable/Dictionary/index.js" import type { Has, Tag } from "../Has/index.js" import { mergeEnvironments } from "../Has/index.js" import type { UnionToIntersection } from "../Utils/index.js" import * as As from "./core.js" /** * Access a record of services with the required Service Entries */ export function accessServicesM<SS extends Record<string, Tag<any>>>(s: SS) { return <R = unknown, E = never, B = unknown>( f: (a: { [k in keyof SS]: [SS[k]] extends [Tag<infer T>] ? T : unknown }) => As.Async<R, E, B> ) => As.accessM( ( r: UnionToIntersection< { [k in keyof SS]: [SS[k]] extends [Tag<infer T>] ? Has<T> : unknown }[keyof SS] > ) => f(R.map_(s, (v) => r[v.key]) as any) ) } export const accessServicesTM = <SS extends Tag<any>[]>(...s: SS) => <S, R = unknown, E = never, B = unknown>( f: ( ...a: { [k in keyof SS]: [SS[k]] extends [Tag<infer T>] ? T : unknown } ) => As.Async<R, E, B> ) => As.accessM( ( r: UnionToIntersection< { [k in keyof SS]: [SS[k]] extends [Tag<infer T>] ? Has<T> : never }[keyof SS & number] > ) => f(...(A.map_(s, (v) => r[v.key]) as any)) ) export function accessServicesT<SS extends Tag<any>[]>(...s: SS) { return <B = unknown>( f: ( ...a: { [k in keyof SS]: [SS[k]] extends [Tag<infer T>] ? T : unknown } ) => B ) => As.access( ( r: UnionToIntersection< { [k in keyof SS]: [SS[k]] extends [Tag<infer T>] ? Has<T> : never }[keyof SS & number] > ) => f(...(A.map_(s, (v) => r[v.key]) as any)) ) } /** * Access a record of services with the required Service Entries */ export function accessServices<SS extends Record<string, Tag<any>>>(s: SS) { return <B>( f: (a: { [k in keyof SS]: [SS[k]] extends [Tag<infer T>] ? T : unknown }) => B ) => As.access( ( r: UnionToIntersection< { [k in keyof SS]: [SS[k]] extends [Tag<infer T>] ? Has<T> : unknown }[keyof SS] > ) => f(R.map_(s, (v) => r[v.key]) as any) ) } /** * Access a service with the required Service Entry */ export function accessServiceM<T>(s: Tag<T>) { return <R, E, B>(f: (a: T) => As.Async<R, E, B>) => As.accessM((r: Has<T>) => f(r[s.key as any])) } /** * Access a service with the required Service Entry */ export function accessService<T>(s: Tag<T>) { return <B>(f: (a: T) => B) => accessServiceM(s)((a) => As.succeed(f(a))) } /** * Access a service with the required Service Entry */ export function service<T>(s: Tag<T>) { return accessServiceM(s)((a) => As.succeed(a)) } /** * Provides the service with the required Service Entry */ export function provideServiceM<T>(_: Tag<T>) { return <R, E>(f: As.Async<R, E, T>) => <R1, E1, A1>(ma: As.Async<R1 & Has<T>, E1, A1>): As.Async<R & R1, E | E1, A1> => As.accessM((r: R & R1) => As.chain_(f, (t) => As.provideAll_(ma, mergeEnvironments(_, r, t))) ) } /** * Provides the service with the required Service Entry */ export function provideService<T>(_: Tag<T>) { return (f: T) => <R1, E1, A1>(ma: As.Async<R1 & Has<T>, E1, A1>): As.Async<R1, E1, A1> => provideServiceM(_)(As.succeed(f))(ma) } /** * Replaces the service with the required Service Entry */ export function replaceServiceM<R, E, T>(_: Tag<T>, f: (_: T) => As.Async<R, E, T>) { return <R1, E1, A1>( ma: As.Async<R1 & Has<T>, E1, A1> ): As.Async<R & R1 & Has<T>, E | E1, A1> => accessServiceM(_)((t) => provideServiceM(_)(f(t))(ma)) } /** * Replaces the service with the required Service Entry */ export function replaceServiceM_<R, E, T, R1, E1, A1>( ma: As.Async<R1 & Has<T>, E1, A1>, _: Tag<T>, f: (_: T) => As.Async<R, E, T> ): As.Async<R & R1 & Has<T>, E | E1, A1> { return accessServiceM(_)((t) => provideServiceM(_)(f(t))(ma)) } /** * Replaces the service with the required Service Entry */ export function replaceService<T>(_: Tag<T>, f: (_: T) => T) { return <R1, E1, A1>( ma: As.Async<R1 & Has<T>, E1, A1> ): As.Async<R1 & Has<T>, E1, A1> => accessServiceM(_)((t) => provideServiceM(_)(As.succeed(f(t)))(ma)) } /** * Replaces the service with the required Service Entry */ export function replaceService_<R1, E1, A1, T>( ma: As.Async<R1 & Has<T>, E1, A1>, _: Tag<T>, f: (_: T) => T ): As.Async<R1 & Has<T>, E1, A1> { return accessServiceM(_)((t) => provideServiceM(_)(As.succeed(f(t)))(ma)) }