// 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>>(s: SS) { return ( f: (a: { [k in keyof SS]: [SS[k]] extends [Tag] ? T : unknown }) => As.Async ) => As.accessM( ( r: UnionToIntersection< { [k in keyof SS]: [SS[k]] extends [Tag] ? Has : unknown }[keyof SS] > ) => f(R.map_(s, (v) => r[v.key]) as any) ) } export const accessServicesTM = []>(...s: SS) => ( f: ( ...a: { [k in keyof SS]: [SS[k]] extends [Tag] ? T : unknown } ) => As.Async ) => As.accessM( ( r: UnionToIntersection< { [k in keyof SS]: [SS[k]] extends [Tag] ? Has : never }[keyof SS & number] > ) => f(...(A.map_(s, (v) => r[v.key]) as any)) ) export function accessServicesT[]>(...s: SS) { return ( f: ( ...a: { [k in keyof SS]: [SS[k]] extends [Tag] ? T : unknown } ) => B ) => As.access( ( r: UnionToIntersection< { [k in keyof SS]: [SS[k]] extends [Tag] ? Has : 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>>(s: SS) { return ( f: (a: { [k in keyof SS]: [SS[k]] extends [Tag] ? T : unknown }) => B ) => As.access( ( r: UnionToIntersection< { [k in keyof SS]: [SS[k]] extends [Tag] ? Has : unknown }[keyof SS] > ) => f(R.map_(s, (v) => r[v.key]) as any) ) } /** * Access a service with the required Service Entry */ export function accessServiceM(s: Tag) { return (f: (a: T) => As.Async) => As.accessM((r: Has) => f(r[s.key as any])) } /** * Access a service with the required Service Entry */ export function accessService(s: Tag) { return (f: (a: T) => B) => accessServiceM(s)((a) => As.succeed(f(a))) } /** * Access a service with the required Service Entry */ export function service(s: Tag) { return accessServiceM(s)((a) => As.succeed(a)) } /** * Provides the service with the required Service Entry */ export function provideServiceM(_: Tag) { return (f: As.Async) => (ma: As.Async, E1, A1>): As.Async => 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(_: Tag) { return (f: T) => (ma: As.Async, E1, A1>): As.Async => provideServiceM(_)(As.succeed(f))(ma) } /** * Replaces the service with the required Service Entry */ export function replaceServiceM(_: Tag, f: (_: T) => As.Async) { return ( ma: As.Async, E1, A1> ): As.Async, E | E1, A1> => accessServiceM(_)((t) => provideServiceM(_)(f(t))(ma)) } /** * Replaces the service with the required Service Entry */ export function replaceServiceM_( ma: As.Async, E1, A1>, _: Tag, f: (_: T) => As.Async ): As.Async, E | E1, A1> { return accessServiceM(_)((t) => provideServiceM(_)(f(t))(ma)) } /** * Replaces the service with the required Service Entry */ export function replaceService(_: Tag, f: (_: T) => T) { return ( ma: As.Async, E1, A1> ): As.Async, E1, A1> => accessServiceM(_)((t) => provideServiceM(_)(As.succeed(f(t)))(ma)) } /** * Replaces the service with the required Service Entry */ export function replaceService_( ma: As.Async, E1, A1>, _: Tag, f: (_: T) => T ): As.Async, E1, A1> { return accessServiceM(_)((t) => provideServiceM(_)(As.succeed(f(t)))(ma)) }