1import * as Context from "../Context.ts"
2import type { Effect } from "../Effect.ts"
3import { dual } from "../Function.ts"
4import * as Layer from "../Layer.ts"
5import { isEffect } from "./core.ts"
6import * as effect from "./effect.ts"
7
8const provideLayer = <A, E, R, ROut, E2, RIn>(
9 self: Effect<A, E, R>,
10 layer: Layer.Layer<ROut, E2, RIn>,
11 options?: {
12 readonly local?: boolean | undefined
13 } | undefined
14): Effect<A, E | E2, RIn | Exclude<R, ROut>> =>
15 effect.scopedWith((scope) =>
16 effect.flatMap(
17 options?.local
18 ? Layer.buildWithMemoMap(layer, Layer.makeMemoMapUnsafe(), scope)
19 : Layer.buildWithScope(layer, scope),
20 (context) => effect.provideContext(self, context)
21 )
22 )
23
24/** @internal */
25export const provide = dual<
26 {
27 <const Layers extends [Layer.Any, ...Array<Layer.Any>]>(
28 layers: Layers,
29 options?: {
30 readonly local?: boolean | undefined
31 } | undefined
32 ): <A, E, R>(
33 self: Effect<A, E, R>
34 ) => Effect<
35 A,
36 E | Layer.Error<Layers[number]>,
37 | Layer.Services<Layers[number]>
38 | Exclude<R, Layer.Success<Layers[number]>>
39 >
40 <ROut, E2, RIn>(
41 layer: Layer.Layer<ROut, E2, RIn>,
42 options?: {
43 readonly local?: boolean | undefined
44 } | undefined
45 ): <A, E, R>(self: Effect<A, E, R>) => Effect<A, E | E2, RIn | Exclude<R, ROut>>
46 <R2>(context: Context.Context<R2>): <A, E, R>(self: Effect<A, E, R>) => Effect<A, E, Exclude<R, R2>>
47 },
48 {
49 <A, E, R, const Layers extends [Layer.Any, ...Array<Layer.Any>]>(
50 self: Effect<A, E, R>,
51 layers: Layers,
52 options?: {
53 readonly local?: boolean | undefined
54 } | undefined
55 ): Effect<
56 A,
57 E | Layer.Error<Layers[number]>,
58 | Layer.Services<Layers[number]>
59 | Exclude<R, Layer.Success<Layers[number]>>
60 >
61 <A, E, R, ROut, E2, RIn>(
62 self: Effect<A, E, R>,
63 layer: Layer.Layer<ROut, E2, RIn>,
64 options?: {
65 readonly local?: boolean | undefined
66 } | undefined
67 ): Effect<A, E | E2, RIn | Exclude<R, ROut>>
68 <A, E, R, R2>(
69 self: Effect<A, E, R>,
70 context: Context.Context<R2>
71 ): Effect<A, E, Exclude<R, R2>>
72 }
73>(
74 (args) => isEffect(args[0]),
75 <A, E, R, ROut>(
76 self: Effect<A, E, R>,
77 source:
78 | Layer.Layer<ROut, any, any>
79 | Context.Context<ROut>
80 | Array<Layer.Any>,
81 options?: {
82 readonly local?: boolean | undefined
83 } | undefined
84 ): Effect<any, any, Exclude<R, ROut>> =>
85 Context.isContext(source)
86 ? effect.provideContext(self, source)
87 : provideLayer(self, Array.isArray(source) ? Layer.mergeAll(...source as any) : source, options)
88)