Skip to content

Commit 6269a80

Browse files
mikearnaldieffect-bot
authored andcommitted
Add Layer.updateService mirroring Effect.updateService (#4421)
1 parent e5165b1 commit 6269a80

File tree

3 files changed

+53
-1
lines changed

3 files changed

+53
-1
lines changed

.changeset/polite-tables-cry.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"effect": minor
3+
---
4+
5+
Add Layer.updateService mirroring Effect.updateService

packages/effect/src/Layer.ts

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ import * as Context from "./Context.js"
2424
import type * as Effect from "./Effect.js"
2525
import type * as Exit from "./Exit.js"
2626
import type { FiberRef } from "./FiberRef.js"
27-
import type { LazyArg } from "./Function.js"
27+
import { dual, type LazyArg } from "./Function.js"
2828
import { clockTag } from "./internal/clock.js"
2929
import * as core from "./internal/core.js"
3030
import * as defaultServices from "./internal/defaultServices.js"
@@ -1118,3 +1118,37 @@ export const buildWithMemoMap: {
11181118
scope: Scope.Scope
11191119
): Effect.Effect<Context.Context<ROut>, E, RIn>
11201120
} = internal.buildWithMemoMap
1121+
1122+
/**
1123+
* Updates a service in the context with a new implementation.
1124+
*
1125+
* **Details**
1126+
*
1127+
* This function modifies the existing implementation of a service in the
1128+
* context. It retrieves the current service, applies the provided
1129+
* transformation function `f`, and replaces the old service with the
1130+
* transformed one.
1131+
*
1132+
* **When to Use**
1133+
*
1134+
* This is useful for adapting or extending a service's behavior during the
1135+
* creation of a layer.
1136+
*
1137+
* @since 3.13.0
1138+
* @category utils
1139+
*/
1140+
export const updateService = dual<
1141+
<I, A>(
1142+
tag: Context.Tag<I, A>,
1143+
f: (a: A) => A
1144+
) => <A1, E1, R1>(layer: Layer<A1, E1, R1>) => Layer<A1, E1, I | R1>,
1145+
<A1, E1, R1, I, A>(
1146+
layer: Layer<A1, E1, R1>,
1147+
tag: Context.Tag<I, A>,
1148+
f: (a: A) => A
1149+
) => Layer<A1, E1, I | R1>
1150+
>(3, (layer, tag, f) =>
1151+
provide(
1152+
layer,
1153+
map(context(), (c) => Context.add(c, tag, f(Context.unsafeGet(c, tag))))
1154+
))

packages/effect/test/Layer.test.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -663,6 +663,19 @@ describe("Layer", () => {
663663
strictEqual(result.bar, "bar: 1")
664664
}))
665665

666+
it.effect("Updates service via updateService", () =>
667+
Effect.gen(function*() {
668+
const Foo = Context.GenericTag<"Foo", string>("Foo")
669+
const FooDefault = Layer.succeed(Foo, "Foo")
670+
const Bar = Context.GenericTag<"Bar", string>("Bar")
671+
const BarDefault = Layer.effect(Bar, Foo).pipe(
672+
Layer.updateService(Foo, (x) => `Bar: ${x}`),
673+
Layer.provide(FooDefault)
674+
)
675+
const result = yield* Bar.pipe(Effect.provide(BarDefault))
676+
deepStrictEqual(result, "Bar: Foo")
677+
}))
678+
666679
describe("MemoMap", () => {
667680
it.effect("memoizes layer across builds", () =>
668681
Effect.gen(function*() {

0 commit comments

Comments
 (0)