import type * as Array from "effect/Array" import * as Effect from "effect/Effect" import { dual } from "effect/Function" import * as Layer from "effect/Layer" import type * as Scope from "effect/Scope" import type * as Types from "effect/Types" import type * as Context from "./Context.js" import { type EffectGenUtils } from "./utils/gen.js" export * from "effect/Layer" type Make = DependenciesOpt & (MakeEff | MakeGenNo | MakeGen) type MakeEff = { readonly make: Effect.Effect } type MakeGen = { readonly make: () => Generator, S> } type MakeGenNo = { readonly make: () => Generator } type MakeErr = Opts extends { make: () => any } ? EffectGenUtils.Error : never type MakeContext = Opts extends { make: () => any } ? EffectGenUtils.Context : never type DependenciesOpt = { dependencies?: Array.NonEmptyReadonlyArray } type Dependencies = { dependencies: Array.NonEmptyReadonlyArray } // Local replacements for removed Effect.Service.MakeDeps* types type MakeDepsE = Opts extends { dependencies: ReadonlyArray> } ? E : never type MakeDepsOut = Opts extends { dependencies: ReadonlyArray> } ? Out : never type PackedLayers = & Layer.Layer< I, MakeErr | MakeDepsE, Exclude, Scope.Scope | MakeDepsOut> > & { withoutDependencies: Layer.Layer, Exclude, Scope.Scope>> } type PackedOrUnpackedLayer = Opts extends Dependencies ? PackedLayers & {} : Layer.Layer, MakeContext> export const make: { ( tag: Context.Service ): , any, any>>( options: Opts ) => PackedOrUnpackedLayer , any, any>>( tag: Context.Service, options: Opts ): PackedOrUnpackedLayer } = dual(2, (tag, options) => { const effect = options.make[Symbol.toStringTag] === "GeneratorFunction" ? Effect.fnUntraced(options.make)() : options.make const withoutDependencies = Layer.effect(tag, effect) if (options.dependencies) { return Object.assign( withoutDependencies.pipe(Layer.provide(options.dependencies)), { withoutDependencies } ) } else { return withoutDependencies } })