Fix provide
Lint / lint (push) Successful in 12s

This commit is contained in:
Julien Valverdé
2026-05-18 20:28:51 +02:00
parent 7fa5f54f88
commit 4a0a53ae3b
2 changed files with 38 additions and 53 deletions
+4 -4
View File
@@ -1,5 +1,5 @@
import { describe, expect, test } from "bun:test" import { describe, expect, test } from "bun:test"
import { Chunk, Context, Effect, Layer, Option, SubscriptionRef } from "effect" import { Chunk, Context, Effect, Option, SubscriptionRef } from "effect"
import * as Lens from "./Lens.js" import * as Lens from "./Lens.js"
@@ -56,18 +56,18 @@ describe("Lens", () => {
expect(result[1]).toEqual(Option.some(50)) // 100 / 2 expect(result[1]).toEqual(Option.some(50)) // 100 / 2
}) })
test("provide supplies a service to get and modify", async () => { test("provideContext supplies a service to get and modify", async () => {
const result = await Effect.runPromise( const result = await Effect.runPromise(
Effect.flatMap( Effect.flatMap(
SubscriptionRef.make(10), SubscriptionRef.make(10),
parent => { parent => {
const lens = Lens.provide( const lens = Lens.provideContext(
Lens.mapEffect( Lens.mapEffect(
Lens.fromSubscriptionRef(parent), Lens.fromSubscriptionRef(parent),
n => Effect.map(Offset, ({ value }) => n + value), n => Effect.map(Offset, ({ value }) => n + value),
(_n, next) => Effect.map(Offset, ({ value }) => next - value), (_n, next) => Effect.map(Offset, ({ value }) => next - value),
), ),
Layer.succeed(Offset, { value: 5 }), Context.make(Offset, { value: 5 }),
) )
return Effect.flatMap( return Effect.flatMap(
+33 -48
View File
@@ -1,4 +1,4 @@
import { Array, Chunk, type Context, Effect, Function, identity, type Layer, type ManagedRuntime, Option, Pipeable, Predicate, Readable, type Runtime, Stream, type SubscriptionRef, type SynchronizedRef } from "effect" import { Array, Chunk, type Context, Effect, Function, identity, type ManagedRuntime, Option, Pipeable, Predicate, Readable, type Runtime, Stream, type SubscriptionRef, type SynchronizedRef } from "effect"
import type { NoSuchElementException } from "effect/Cause" import type { NoSuchElementException } from "effect/Cause"
import * as Subscribable from "./Subscribable.js" import * as Subscribable from "./Subscribable.js"
@@ -269,54 +269,41 @@ export const mapStream: {
get modify() { return self.modify }, get modify() { return self.modify },
})) }))
/** /**
* Provides the requirements of a `Lens`, removing them from both the read and write environments. * Provides a `Context` to a `Lens`, removing it from both the read and write environments.
*
* Accepts the same provider forms as `Effect.provide`: one or more `Layer`s, a `Context`,
* a `Runtime`, or a `ManagedRuntime`.
*
* Layer providers may add their construction errors to both the read and write error channels.
*/ */
export const provide: { export const provideContext: {
<const Layers extends readonly [Layer.Layer.Any, ...Array<Layer.Layer.Any>]>( <A, ER, EW, RR, RW, R2>(
layers: Layers, self: Lens<A, ER, EW, RR, RW>,
): <A, ER, EW, RR, RW>(self: Lens<A, ER, EW, RR, RW>) => Lens< context: Context.Context<R2>,
A, ): Lens<A, ER, EW, Exclude<RR, R2>, Exclude<RW, R2>>
ER | { [k in keyof Layers]: Layer.Layer.Error<Layers[k]> }[number],
EW | { [k in keyof Layers]: Layer.Layer.Error<Layers[k]> }[number],
{ [k in keyof Layers]: Layer.Layer.Context<Layers[k]> }[number] | Exclude<RR, { [k in keyof Layers]: Layer.Layer.Success<Layers[k]> }[number]>,
{ [k in keyof Layers]: Layer.Layer.Context<Layers[k]> }[number] | Exclude<RW, { [k in keyof Layers]: Layer.Layer.Success<Layers[k]> }[number]>
>
<ROut, E2, RIn>(
layer: Layer.Layer<ROut, E2, RIn>,
): <A, ER, EW, RR, RW>(self: Lens<A, ER, EW, RR, RW>) => Lens<A, ER | E2, EW | E2, RIn | Exclude<RR, ROut>, RIn | Exclude<RW, ROut>>
<R2>( <R2>(
context: Context.Context<R2>, context: Context.Context<R2>,
): <A, ER, EW, RR, RW>(self: Lens<A, ER, EW, RR, RW>) => Lens<A, ER, EW, Exclude<RR, R2>, Exclude<RW, R2>> ): <A, ER, EW, RR, RW>(self: Lens<A, ER, EW, RR, RW>) => Lens<A, ER, EW, Exclude<RR, R2>, Exclude<RW, R2>>
} = Function.dual(2, <A, ER, EW, RR, RW, R2>(
self: Lens<A, ER, EW, RR, RW>,
context: Context.Context<R2>,
): Lens<A, ER, EW, Exclude<RR, R2>, Exclude<RW, R2>> => make({
get get() { return Effect.provide(self.get, context) },
get changes() { return Stream.provideSomeContext(self.changes, context) },
modify: <B, E1 = never, R1 = never>(
f: (a: A) => Effect.Effect<readonly [B, A], E1, R1>
) => Effect.provide(self.modify(f), context),
}))
/**
* Provides a `Runtime` or `ManagedRuntime` to a `Lens`, removing it from both the read and write environments.
*
* `ManagedRuntime` may add its construction errors to both the read and write error channels.
*/
export const provideRuntime: {
<R2>( <R2>(
runtime: Runtime.Runtime<R2>, runtime: Runtime.Runtime<R2>,
): <A, ER, EW, RR, RW>(self: Lens<A, ER, EW, RR, RW>) => Lens<A, ER, EW, Exclude<RR, R2>, Exclude<RW, R2>> ): <A, ER, EW, RR, RW>(self: Lens<A, ER, EW, RR, RW>) => Lens<A, ER, EW, Exclude<RR, R2>, Exclude<RW, R2>>
<E2, R2>( <E2, R2>(
managedRuntime: ManagedRuntime.ManagedRuntime<R2, E2>, managedRuntime: ManagedRuntime.ManagedRuntime<R2, E2>,
): <A, ER, EW, RR, RW>(self: Lens<A, ER, EW, RR, RW>) => Lens<A, ER | E2, EW | E2, Exclude<RR, R2>, Exclude<RW, R2>> ): <A, ER, EW, RR, RW>(self: Lens<A, ER, EW, RR, RW>) => Lens<A, ER | E2, EW | E2, Exclude<RR, R2>, Exclude<RW, R2>>
<A, ER, EW, RR, RW, const Layers extends readonly [Layer.Layer.Any, ...Array<Layer.Layer.Any>]>(
self: Lens<A, ER, EW, RR, RW>,
layers: Layers,
): Lens<
A,
ER | { [k in keyof Layers]: Layer.Layer.Error<Layers[k]> }[number],
EW | { [k in keyof Layers]: Layer.Layer.Error<Layers[k]> }[number],
{ [k in keyof Layers]: Layer.Layer.Context<Layers[k]> }[number] | Exclude<RR, { [k in keyof Layers]: Layer.Layer.Success<Layers[k]> }[number]>,
{ [k in keyof Layers]: Layer.Layer.Context<Layers[k]> }[number] | Exclude<RW, { [k in keyof Layers]: Layer.Layer.Success<Layers[k]> }[number]>
>
<A, ER, EW, RR, RW, ROut, E2, RIn>(
self: Lens<A, ER, EW, RR, RW>,
layer: Layer.Layer<ROut, E2, RIn>,
): Lens<A, ER | E2, EW | E2, RIn | Exclude<RR, ROut>, RIn | Exclude<RW, ROut>>
<A, ER, EW, RR, RW, R2>(
self: Lens<A, ER, EW, RR, RW>,
context: Context.Context<R2>,
): Lens<A, ER, EW, Exclude<RR, R2>, Exclude<RW, R2>>
<A, ER, EW, RR, RW, R2>( <A, ER, EW, RR, RW, R2>(
self: Lens<A, ER, EW, RR, RW>, self: Lens<A, ER, EW, RR, RW>,
runtime: Runtime.Runtime<R2>, runtime: Runtime.Runtime<R2>,
@@ -325,22 +312,20 @@ export const provide: {
self: Lens<A, ER, EW, RR, RW>, self: Lens<A, ER, EW, RR, RW>,
runtime: ManagedRuntime.ManagedRuntime<R2, E2>, runtime: ManagedRuntime.ManagedRuntime<R2, E2>,
): Lens<A, ER | E2, EW | E2, Exclude<RR, R2>, Exclude<RW, R2>> ): Lens<A, ER | E2, EW | E2, Exclude<RR, R2>, Exclude<RW, R2>>
} = Function.dual(2, <A, ER, EW, RR, RW, ROut, E2, RIn>( } = Function.dual(2, <A, ER, EW, RR, RW, E2, R2>(
self: Lens<A, ER, EW, RR, RW>, self: Lens<A, ER, EW, RR, RW>,
layer: Layer.Layer<ROut, E2, RIn>, runtime: Runtime.Runtime<R2>,
): Lens<A, ER | E2, EW | E2, RIn | Exclude<RR, ROut>, RIn | Exclude<RW, ROut>> => make({ ) => make<A, ER | E2, EW | E2, Exclude<RR, R2>, Exclude<RW, R2>>({
get get() { return Effect.provide(self.get, layer) }, get get() { return Effect.provide(self.get, runtime) },
get changes() { get changes() {
return Stream.unwrapScoped( return Stream.unwrap(Effect.map(
Effect.map( Effect.provide(Effect.context<RR>(), runtime),
Effect.provide(Effect.context<RR>(), layer),
context => Stream.provideContext(self.changes, context), context => Stream.provideContext(self.changes, context),
), ))
)
}, },
modify: <B, E1 = never, R1 = never>( modify: <B, E1 = never, R1 = never>(
f: (a: A) => Effect.Effect<readonly [B, A], E1, R1> f: (a: A) => Effect.Effect<readonly [B, A], E1, R1>
) => Effect.provide(self.modify(f), layer), ) => Effect.provide(self.modify(f), runtime),
})) }))
/** /**