import type { UnionToIntersection } from "@principia/prelude/Utils"; import { identity } from "../../Function"; import type { Has, Tag } from "../../Has"; import * as M from "../Managed"; import type { Task } from "../Task"; import * as T from "../Task/combinators/service"; import * as L from "./core"; export const fromConstructor = (tag: Tag) => ( constructor: (...services: Services) => S ) => ( ...tags: { [k in keyof Services]: Tag } ): L.Layer }[keyof Services & number]>, never, Has> => L.fromTask(tag)(T.asksServicesT(...tags)((...services: any[]) => constructor(...(services as any))) as any) as any; export const fromTaskConstructor = (tag: Tag) => ( constructor: (...services: Services) => Task ) => ( ...tags: { [k in keyof Services]: Tag } ): L.Layer }[keyof Services & number]> & R, E, Has> => L.fromTask(tag)(T.asksServicesTM(...tags)((...services: any[]) => constructor(...(services as any))) as any) as any; export const fromManagedConstructor = (tag: Tag) => ( constructor: (...services: Services) => M.Managed ) => ( ...tags: { [k in keyof Services]: Tag } ): L.Layer }[keyof Services & number]> & R, E, Has> => L.fromManaged(tag)( M.chain_( M.fromTask(T.asksServicesT(...tags)((...services: any[]) => constructor(...(services as any)))), identity ) ); export const bracketConstructor = (tag: Tag) => ( constructor: (...services: Services) => S2 ) => (...tags: { [k in keyof Services]: Tag }) => ( open: (s: S2) => Task, release: (s: S2) => Task ): L.Layer< UnionToIntersection<{ [k in keyof Services]: Has }[keyof Services & number]> & R & R2, E, Has > => L.prepare(tag)(T.asksServicesT(...tags)((...services: any[]) => constructor(...(services as any))) as any) .open(open as any) .release(release as any) as any; export const bracketTaskConstructor = (tag: Tag) => ( constructor: (...services: Services) => Task ) => (...tags: { [k in keyof Services]: Tag }) => ( open: (s: S2) => Task, release: (s: S2) => Task ): L.Layer< UnionToIntersection<{ [k in keyof Services]: Has }[keyof Services & number]> & R & R2 & R0, E | E0, Has > => L.prepare(tag)(T.asksServicesTM(...tags)((...services: any[]) => constructor(...(services as any))) as any) .open(open as any) .release(release as any) as any; export const restrict = []>(...ts: Tags) => ( layer: L.Layer< R, E, UnionToIntersection< { [k in keyof Tags]: [Tags[k]] extends [Tag] ? Has : never; }[number] > > ): L.Layer< R, E, UnionToIntersection< { [k in keyof Tags]: [Tags[k]] extends [Tag] ? Has : never; }[number] > > => L.andTo_( layer, L.fromRawTask( T.asksServicesT(...ts)((...servises) => servises.map((s, i) => ({ [ts[i].key]: s } as any)).reduce((x, y) => ({ ...x, ...y })) ) ) ) as any;