Skip to content
This repository has been archived by the owner on Jul 16, 2024. It is now read-only.

Commit

Permalink
consolidate provide* apis for Layer/Context/Runtime (#674)
Browse files Browse the repository at this point in the history
  • Loading branch information
tim-smart committed Sep 25, 2023
1 parent 794f757 commit 5ad5367
Show file tree
Hide file tree
Showing 19 changed files with 140 additions and 208 deletions.
5 changes: 5 additions & 0 deletions .changeset/cyan-vans-camp.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@effect/io": minor
---

consolidate provide\* apis for Layer/Context/Runtime
89 changes: 13 additions & 76 deletions docs/modules/Effect.ts.md
Original file line number Diff line number Diff line change
Expand Up @@ -89,13 +89,9 @@ Added in v1.0.0
- [contextWith](#contextwith)
- [contextWithEffect](#contextwitheffect)
- [mapInputContext](#mapinputcontext)
- [provideContext](#providecontext)
- [provideLayer](#providelayer)
- [provide](#provide)
- [provideService](#provideservice)
- [provideServiceEffect](#provideserviceeffect)
- [provideSomeContext](#providesomecontext)
- [provideSomeLayer](#providesomelayer)
- [provideSomeRuntime](#providesomeruntime)
- [serviceConstants](#serviceconstants)
- [serviceFunction](#servicefunction)
- [serviceFunctionEffect](#servicefunctioneffect)
Expand Down Expand Up @@ -1571,32 +1567,23 @@ export declare const mapInputContext: {
Added in v1.0.0
## provideContext
## provide
Provides the effect with its required context, which eliminates its
dependency on `R`.
**Signature**
```ts
export declare const provideContext: {
<R>(context: Context.Context<R>): <E, A>(self: Effect<R, E, A>) => Effect<never, E, A>
<R, E, A>(self: Effect<R, E, A>, context: Context.Context<R>): Effect<never, E, A>
}
```
Added in v1.0.0
## provideLayer
Provides a layer to the effect, which translates it to another level.
Splits the context into two parts, providing one part using the
specified layer/context/runtime and leaving the remainder `R0`.
**Signature**
```ts
export declare const provideLayer: {
<R0, E2, R>(layer: Layer.Layer<R0, E2, R>): <E, A>(self: Effect<R, E, A>) => Effect<R0, E2 | E, A>
<R, E, A, R0, E2>(self: Effect<R, E, A>, layer: Layer.Layer<R0, E2, R>): Effect<R0, E | E2, A>
export declare const provide: {
<R2, E2, A2>(layer: Layer.Layer<R2, E2, A2>): <R, E, A>(
self: Effect<R, E, A>
) => Effect<R2 | Exclude<R, A2>, E2 | E, A>
<R2>(context: Context.Context<R2>): <R, E, A>(self: Effect<R, E, A>) => Effect<Exclude<R, R2>, E, A>
<R2>(runtime: Runtime.Runtime<R2>): <R, E, A>(self: Effect<R, E, A>) => Effect<Exclude<R, R2>, E, A>
<R, E, A, R2, E2, A2>(self: Effect<R, E, A>, layer: Layer.Layer<R2, E2, A2>): Effect<R2 | Exclude<R, A2>, E | E2, A>
<R, E, A, R2>(self: Effect<R, E, A>, context: Context.Context<R2>): Effect<Exclude<R, R2>, E, A>
<R, E, A, R2>(self: Effect<R, E, A>, runtime: Runtime.Runtime<R2>): Effect<Exclude<R, R2>, E, A>
}
```
Expand Down Expand Up @@ -1646,56 +1633,6 @@ export declare const provideServiceEffect: {
Added in v1.0.0
## provideSomeContext
Splits the context into two parts, providing one part using the
specified layer and leaving the remainder `R0`.
**Signature**
```ts
export declare const provideSomeContext: {
<R>(context: Context.Context<R>): <R1, E, A>(self: Effect<R1, E, A>) => Effect<Exclude<R1, R>, E, A>
<R, R1, E, A>(self: Effect<R1, E, A>, context: Context.Context<R>): Effect<Exclude<R1, R>, E, A>
}
```
Added in v1.0.0
## provideSomeLayer
Splits the context into two parts, providing one part using the
specified layer and leaving the remainder `R0`.
**Signature**
```ts
export declare const provideSomeLayer: {
<R2, E2, A2>(layer: Layer.Layer<R2, E2, A2>): <R, E, A>(
self: Effect<R, E, A>
) => Effect<R2 | Exclude<R, A2>, E2 | E, A>
<R, E, A, R2, E2, A2>(self: Effect<R, E, A>, layer: Layer.Layer<R2, E2, A2>): Effect<R2 | Exclude<R, A2>, E | E2, A>
}
```
Added in v1.0.0
## provideSomeRuntime
Splits the context into two parts, providing one part using the
specified runtime and leaving the remainder `R0`.
**Signature**
```ts
export declare const provideSomeRuntime: {
<R>(context: Runtime.Runtime<R>): <R1, E, A>(self: Effect<R1, E, A>) => Effect<Exclude<R1, R>, E, A>
<R, R1, E, A>(self: Effect<R1, E, A>, context: Runtime.Runtime<R>): Effect<Exclude<R1, R>, E, A>
}
```
Added in v1.0.0
## serviceConstants
**Signature**
Expand Down
2 changes: 1 addition & 1 deletion examples/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ export const program = Effect.gen(function*($) {

pipe(
program,
Effect.provideSomeLayer(HttpServerLive),
Effect.provide(HttpServerLive),
Effect.catchAllCause(Effect.logError),
Effect.runFork
)
2 changes: 1 addition & 1 deletion examples/deep.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ const program = pipe(
}),
Effect.flatMap((chunk) => Effect.sync(() => console.log(Array.from(chunk)))),
Effect.tapErrorCause(Effect.logError),
Effect.provideLayer(Logger.minimumLogLevel(Level.Debug))
Effect.provide(Logger.minimumLogLevel(Level.Debug))
)

Effect.runFork(program)
2 changes: 1 addition & 1 deletion examples/example.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ const L = Layer.effect(
})
)

const main = Effect.provideSomeLayer(L)(Effect.flatMap(N, (n) => Effect.logDebug(`n: ${n}`)))
const main = Effect.provide(L)(Effect.flatMap(N, (n) => Effect.logDebug(`n: ${n}`)))

Effect.runSync(
Logger.withMinimumLogLevel(LogLevel.Debug)(main)
Expand Down
2 changes: 1 addition & 1 deletion examples/log.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ const program2 = Logger.withMinimumLogLevel(LogLevel.Info)(

const main = pipe(
Effect.all([program1, program2], { discard: true }),
Effect.provideSomeLayer(Logger.minimumLogLevel(LogLevel.Info))
Effect.provide(Logger.minimumLogLevel(LogLevel.Info))
)

Effect.runFork(main)
2 changes: 1 addition & 1 deletion examples/logMeta.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ const program = Effect.gen(function*($) {

const main = pipe(
program,
Effect.provideSomeLayer(Logger.replace(Logger.defaultLogger, customLogger))
Effect.provide(Logger.replace(Logger.defaultLogger, customLogger))
)

Effect.runFork(main)
94 changes: 14 additions & 80 deletions src/Effect.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import type * as Either from "@effect/data/Either"
import type * as Equal from "@effect/data/Equal"
import type { Equivalence } from "@effect/data/Equivalence"
import type { LazyArg } from "@effect/data/Function"
import { dual, identity } from "@effect/data/Function"
import { identity } from "@effect/data/Function"
import type * as HashMap from "@effect/data/HashMap"
import type * as HashSet from "@effect/data/HashSet"
import type { TypeLambda } from "@effect/data/HKT"
Expand All @@ -30,7 +30,7 @@ import type * as Fiber from "@effect/io/Fiber"
import type * as FiberId from "@effect/io/FiberId"
import type * as FiberRef from "@effect/io/FiberRef"
import type * as FiberRefs from "@effect/io/FiberRefs"
import * as FiberRefsPatch from "@effect/io/FiberRefsPatch"
import type * as FiberRefsPatch from "@effect/io/FiberRefsPatch"
import { clockTag } from "@effect/io/internal/clock"
import * as core from "@effect/io/internal/core"
import * as defaultServices from "@effect/io/internal/defaultServices"
Expand All @@ -53,7 +53,7 @@ import type * as Request from "@effect/io/Request"
import type { RequestBlock } from "@effect/io/RequestBlock"
import type { RequestResolver } from "@effect/io/RequestResolver"
import type * as Runtime from "@effect/io/Runtime"
import * as RuntimeFlags from "@effect/io/RuntimeFlags"
import type * as RuntimeFlags from "@effect/io/RuntimeFlags"
import type * as RuntimeFlagsPatch from "@effect/io/RuntimeFlagsPatch"
import type * as Schedule from "@effect/io/Schedule"
import * as Scheduler from "@effect/io/Scheduler"
Expand Down Expand Up @@ -3044,72 +3044,23 @@ export const mapInputContext: {
<R0, R, E, A>(self: Effect<R, E, A>, f: (context: Context.Context<R0>) => Context.Context<R>): Effect<R0, E, A>
} = core.mapInputContext

/**
* Provides the effect with its required context, which eliminates its
* dependency on `R`.
*
* @since 1.0.0
* @category context
*/
export const provideContext: {
<R>(context: Context.Context<R>): <E, A>(self: Effect<R, E, A>) => Effect<never, E, A>
<R, E, A>(self: Effect<R, E, A>, context: Context.Context<R>): Effect<never, E, A>
} = core.provideContext

/**
* Splits the context into two parts, providing one part using the
* specified layer and leaving the remainder `R0`.
*
* @since 1.0.0
* @category context
*/
export const provideSomeContext: {
<R>(context: Context.Context<R>): <R1, E, A>(self: Effect<R1, E, A>) => Effect<Exclude<R1, R>, E, A>
<R, R1, E, A>(self: Effect<R1, E, A>, context: Context.Context<R>): Effect<Exclude<R1, R>, E, A>
} = core.provideSomeContext

/**
* Splits the context into two parts, providing one part using the
* specified runtime and leaving the remainder `R0`.
*
* @since 1.0.0
* @category context
*/
export const provideSomeRuntime: {
<R>(context: Runtime.Runtime<R>): <R1, E, A>(self: Effect<R1, E, A>) => Effect<Exclude<R1, R>, E, A>
<R, R1, E, A>(self: Effect<R1, E, A>, context: Runtime.Runtime<R>): Effect<Exclude<R1, R>, E, A>
} = dual<
<R>(context: Runtime.Runtime<R>) => <R1, E, A>(self: Effect<R1, E, A>) => Effect<Exclude<R1, R>, E, A>,
<R, R1, E, A>(self: Effect<R1, E, A>, context: Runtime.Runtime<R>) => Effect<Exclude<R1, R>, E, A>
>(2, (self, runtime) => {
const patchFlags = RuntimeFlags.diff(_runtime.defaultRuntime.runtimeFlags, runtime.runtimeFlags)
const inversePatchFlags = RuntimeFlags.diff(runtime.runtimeFlags, _runtime.defaultRuntime.runtimeFlags)
const patchRefs = FiberRefsPatch.diff(_runtime.defaultRuntime.fiberRefs, runtime.fiberRefs)
const inversePatchRefs = FiberRefsPatch.diff(runtime.fiberRefs, _runtime.defaultRuntime.fiberRefs)
return acquireUseRelease(
core.flatMap(
patchRuntimeFlags(patchFlags),
() => patchFiberRefs(patchRefs)
),
() => provideSomeContext(self, runtime.context),
() =>
core.flatMap(
patchRuntimeFlags(inversePatchFlags),
() => patchFiberRefs(inversePatchRefs)
)
)
})

/**
* Provides a layer to the effect, which translates it to another level.
* specified layer/context/runtime and leaving the remainder `R0`.
*
* @since 1.0.0
* @category context
*/
export const provideLayer: {
<R0, E2, R>(layer: Layer.Layer<R0, E2, R>): <E, A>(self: Effect<R, E, A>) => Effect<R0, E2 | E, A>
<R, E, A, R0, E2>(self: Effect<R, E, A>, layer: Layer.Layer<R0, E2, R>): Effect<R0, E | E2, A>
} = layer.provideLayer
export const provide: {
<R2, E2, A2>(
layer: Layer.Layer<R2, E2, A2>
): <R, E, A>(self: Effect<R, E, A>) => Effect<R2 | Exclude<R, A2>, E2 | E, A>
<R2>(context: Context.Context<R2>): <R, E, A>(self: Effect<R, E, A>) => Effect<Exclude<R, R2>, E, A>
<R2>(runtime: Runtime.Runtime<R2>): <R, E, A>(self: Effect<R, E, A>) => Effect<Exclude<R, R2>, E, A>
<R, E, A, R2, E2, A2>(self: Effect<R, E, A>, layer: Layer.Layer<R2, E2, A2>): Effect<R2 | Exclude<R, A2>, E | E2, A>
<R, E, A, R2>(self: Effect<R, E, A>, context: Context.Context<R2>): Effect<Exclude<R, R2>, E, A>
<R, E, A, R2>(self: Effect<R, E, A>, runtime: Runtime.Runtime<R2>): Effect<Exclude<R, R2>, E, A>
} = layer.effect_provide

/**
* Provides the effect with the single service it requires. If the effect
Expand Down Expand Up @@ -3149,23 +3100,6 @@ export const provideServiceEffect: {
): Effect<R1 | Exclude<R, Context.Tag.Identifier<T>>, E | E1, A>
} = effect.provideServiceEffect

/**
* Splits the context into two parts, providing one part using the
* specified layer and leaving the remainder `R0`.
*
* @since 1.0.0
* @category context
*/
export const provideSomeLayer: {
<R2, E2, A2>(
layer: Layer.Layer<R2, E2, A2>
): <R, E, A>(self: Effect<R, E, A>) => Effect<R2 | Exclude<R, A2>, E2 | E, A>
<R, E, A, R2, E2, A2>(
self: Effect<R, E, A>,
layer: Layer.Layer<R2, E2, A2>
): Effect<R2 | Exclude<R, A2>, E | E2, A>
} = layer.provideSomeLayer

/**
* @since 1.0.0
* @category context
Expand Down
74 changes: 65 additions & 9 deletions src/internal/layer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import * as Clock from "@effect/io/Clock"
import type * as Effect from "@effect/io/Effect"
import type * as Exit from "@effect/io/Exit"
import type { FiberRef } from "@effect/io/FiberRef"
import type * as FiberRefsPatch from "@effect/io/FiberRefsPatch"
import * as FiberRefsPatch from "@effect/io/FiberRefsPatch"
import * as core from "@effect/io/internal/core"
import * as effect from "@effect/io/internal/effect"
import * as circular from "@effect/io/internal/effect/circular"
Expand All @@ -17,6 +17,7 @@ import * as EffectOpCodes from "@effect/io/internal/opCodes/effect"
import * as OpCodes from "@effect/io/internal/opCodes/layer"
import * as ref from "@effect/io/internal/ref"
import * as runtime from "@effect/io/internal/runtime"
import * as runtimeFlags from "@effect/io/internal/runtimeFlags"
import * as synchronized from "@effect/io/internal/synchronizedRef"
import type * as Layer from "@effect/io/Layer"
import type * as Runtime from "@effect/io/Runtime"
Expand Down Expand Up @@ -1115,12 +1116,67 @@ export const provideLayer = dual<
))

/** @internal */
export const provideSomeLayer: {
<R2, E2, A2>(
layer: Layer.Layer<R2, E2, A2>
): <R, E, A>(self: Effect.Effect<R, E, A>) => Effect.Effect<R2 | Exclude<R, A2>, E | E2, A>
<R, E, A, R2, E2, A2>(
export const provideSomeRuntime: {
<R>(context: Runtime.Runtime<R>): <R1, E, A>(self: Effect.Effect<R1, E, A>) => Effect.Effect<Exclude<R1, R>, E, A>
<R, R1, E, A>(self: Effect.Effect<R1, E, A>, context: Runtime.Runtime<R>): Effect.Effect<Exclude<R1, R>, E, A>
} = dual<
<R>(context: Runtime.Runtime<R>) => <R1, E, A>(self: Effect.Effect<R1, E, A>) => Effect.Effect<Exclude<R1, R>, E, A>,
<R, R1, E, A>(self: Effect.Effect<R1, E, A>, context: Runtime.Runtime<R>) => Effect.Effect<Exclude<R1, R>, E, A>
>(2, (self, rt) => {
const patchFlags = runtimeFlags.diff(runtime.defaultRuntime.runtimeFlags, rt.runtimeFlags)
const inversePatchFlags = runtimeFlags.diff(rt.runtimeFlags, runtime.defaultRuntime.runtimeFlags)
const patchRefs = FiberRefsPatch.diff(runtime.defaultRuntime.fiberRefs, rt.fiberRefs)
const inversePatchRefs = FiberRefsPatch.diff(rt.fiberRefs, runtime.defaultRuntime.fiberRefs)
return core.acquireUseRelease(
core.flatMap(
core.updateRuntimeFlags(patchFlags),
() => effect.patchFiberRefs(patchRefs)
),
() => core.provideSomeContext(self, rt.context),
() =>
core.flatMap(
core.updateRuntimeFlags(inversePatchFlags),
() => effect.patchFiberRefs(inversePatchRefs)
)
)
})

/** @internal */
export const effect_provide = dual<
{
<R2, E2, A2>(
layer: Layer.Layer<R2, E2, A2>
): <R, E, A>(self: Effect.Effect<R, E, A>) => Effect.Effect<R2 | Exclude<R, A2>, E | E2, A>
<R2>(
context: Context.Context<R2>
): <R, E, A>(self: Effect.Effect<R, E, A>) => Effect.Effect<Exclude<R, R2>, E, A>
<R2>(
runtime: Runtime.Runtime<R2>
): <R, E, A>(self: Effect.Effect<R, E, A>) => Effect.Effect<Exclude<R, R2>, E, A>
},
{
<R, E, A, R2, E2, A2>(
self: Effect.Effect<R, E, A>,
layer: Layer.Layer<R2, E2, A2>
): Effect.Effect<R2 | Exclude<R, A2>, E | E2, A>
<R, E, A, R2>(
self: Effect.Effect<R, E, A>,
context: Context.Context<R2>
): Effect.Effect<Exclude<R, R2>, E, A>
<R, E, A, R2>(
self: Effect.Effect<R, E, A>,
runtime: Runtime.Runtime<R2>
): Effect.Effect<Exclude<R, R2>, E, A>
}
>(
2,
<R, E, A, R2>(
self: Effect.Effect<R, E, A>,
layer: Layer.Layer<R2, E2, A2>
): Effect.Effect<R2 | Exclude<R, A2>, E | E2, A>
} = dual(2, (self, layer) => provideLayer(self, merge(context(), layer)))
source: Layer.Layer<any, any, R2> | Context.Context<R2> | Runtime.Runtime<R2>
): Effect.Effect<Exclude<R, R2>, any, any> =>
isLayer(source)
? provideLayer(self as any, merge(context(), source as Layer.Layer<any, any, R2>))
: Context.isContext(source)
? core.provideSomeContext(self, source)
: provideSomeRuntime(self, source as Runtime.Runtime<R2>)
)
Loading

0 comments on commit 5ad5367

Please sign in to comment.