Effect 3.14 has been released! This release includes a number of new features and improvements. Here’s a summary of what’s new:
LayerMap module
A LayerMap
allows you to create a map of Layer’s that can be used to dynamically access resources based on a key.
Here is an example of how you can use a LayerMap
to create a service that provides access to multiple OpenAI completions services.
1 import { Completions } from "@effect/ai"
2 import { OpenAiClient, OpenAiCompletions } from "@effect/ai-openai"
3 import { FetchHttpClient } from "@effect/platform"
4 import { NodeRuntime } from "@effect/platform-node"
5 import { Config, Effect, Layer, LayerMap } from "effect"
6
7 // create the openai client layer
8 const OpenAiLayer = OpenAiClient.layerConfig({
9 apiKey: Config.redacted("OPENAI_API_KEY")
10 }).pipe(Layer.provide(FetchHttpClient.layer))
11
12 // create a service that wraps a LayerMap
13 class AiClients extends LayerMap.Service<AiClients>()("AiClients", {
14 // this LayerMap will provide the ai Completions service
15 provides: Completions.Completions,
16
17 // define the lookup function for the layer map
18 //
19 // The returned Layer will be used to provide the Completions service for the
20 // given model.
21 lookup: (model: OpenAiCompletions.Model) =>
22 OpenAiCompletions.layer({ model }),
23
24 // If a layer is not used for a certain amount of time, it can be removed
25 idleTimeToLive: "5 seconds",
26
27 // Supply the dependencies for the layers in the LayerMap
28 dependencies: [OpenAiLayer]
29 }) {}
30
31 // usage
32 Effect.gen(function* () {
33 // access and use the generic Completions service
34 const ai = yield* Completions.Completions
35 const response = yield* ai.create("Hello, world!")
36 console.log(response.text)
37 }).pipe(
38 // use the AiClients service to provide a variant of the Completions service
39 AiClients.provide("gpt-4o"),
40 // provide the LayerMap service
41 Effect.provide(AiClients.Default),
42 NodeRuntime.runMain
43 )
@effect/rpc refactor
The @effect/rpc
package has undergone a refactor to improve the ergonomics of the API, and to make it more modular.
To read more about the changes, take a look at the README.
Effect.linkSpanCurrent
Effect.linkSpanCurrent allows you to link a span to the current span in the context.
1 import { Effect } from "effect"
2
3 Effect.gen(function* () {
4 const childSpan = yield* Effect.makeSpan("linked")
5 // link the "linked" span to the "parent" span
6 yield* Effect.linkSpanCurrent(childSpan)
7 }).pipe(Effect.withSpan("parent"))
Dual Runtime apis
All of the Runtime.run*
apis from the Runtime
module now have dual signatures.
1 import { Effect, Runtime } from "effect"
2
3 const program = Effect.log("Hello, World!")
4
5 // You can run the effect by passing all arguments
6 Runtime.runFork(Runtime.defaultRuntime, program)
7
8 // Or using partial application
9 Runtime.runFork(Runtime.defaultRuntime)(program)
Option transpose apis
Effect.transposeMapOption
Applies an Effect
on an Option
and transposes the result.
- If the
Option
isNone
, the resultingEffect
will immediately succeed with aNone
value. - If the
Option
isSome
, the effectful operation will be executed on the inner value, and its result wrapped in aSome
.
1 import { Effect, Option, pipe } from "effect"
2
3 // ┌─── Effect<Option<number>, never, never>>
4 // ▼
5 const noneResult = pipe(
6 Option.none(),
7 Effect.transposeMapOption(() => Effect.succeed(42)) // will not be executed
8 )
9 console.log(Effect.runSync(noneResult))
10 // Output: { _id: 'Option', _tag: 'None' }
11
12 // ┌─── Effect<Option<number>, never, never>>
13 // ▼
14 const someSuccessResult = pipe(
15 Option.some(42),
16 Effect.transposeMapOption((value) => Effect.succeed(value * 2))
17 )
18 console.log(Effect.runSync(someSuccessResult))
19 // Output: { _id: 'Option', _tag: 'Some', value: 84 }
Top comments (0)