Created
September 25, 2023 07:31
-
-
Save yanisurbis/3198cc6f15e26bd2161edefef74e565b to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// explore layers in more details, https://effect-ts.github.io/io/modules/Layer.ts.html | |
import { Context, Effect, Layer } from 'effect' | |
type A = { | |
a: (x: number) => Effect.Effect<never, never, number> | |
} | |
const A = Context.Tag<A>() | |
type B = { | |
b: (x: number) => Effect.Effect<never, never, number> | |
} | |
const B = Context.Tag<B>() | |
type C = { | |
c: (x: number) => Effect.Effect<never, never, number> | |
} | |
const C = Context.Tag<C>() | |
// --- | |
const LayerC = Layer.effect( | |
C, | |
Effect.gen(function* (_) { | |
const a = yield* _(A) | |
const b = yield* _(B) | |
return { | |
c: x => | |
Effect.gen(function* (_) { | |
const y = yield* _(a.a(x)) | |
return yield* _(b.b(y)) | |
}), | |
} | |
}), | |
) | |
// | |
// | |
// | |
// | |
// standard approach, each layer returns a context with a single service | |
const LayerA = Layer.succeed(A, { a: x => Effect.succeed(x + 1) }) | |
const LayerB = Layer.succeed(B, { b: x => Effect.succeed(x * 2) }) | |
const LiveLayer = LayerC.pipe(Layer.use(Layer.merge(LayerA, LayerB))) | |
// alternative approach, layer returns a context with multiple services | |
// Layer.Layer<never, never, A | B> | |
const LayerAB = Layer.effectContext( | |
Effect.gen(function* (_) { | |
return Context.empty().pipe( | |
Context.add(A, { a: x => Effect.succeed(x + 1) }), | |
Context.add(B, { b: x => Effect.succeed(x * 2) }), | |
) | |
}), | |
) | |
const LiveLayer2 = LayerC.pipe(Layer.use(LayerAB)) | |
// yet another approach, if the dependency between A and B is a simple function | |
// Layer.Layer<A, never, B> | |
const LayerBnew = Layer.function(A, B, a => ({ b: x => a.a(x) })) | |
// Layer.Layer<A, never, A | B>, Layer.service is a way to pass a service from one layer to another | |
const LayerABnew = Layer.merge(Layer.service(A), LayerBnew) | |
// Layer.Layer<never, never, C> | |
const LiveLayer3 = LayerC.pipe(Layer.use(LayerABnew), Layer.use(LayerA)) | |
// | |
// | |
// | |
// | |
// helper fn so the call site is cleaner | |
const runProgram = <R, E, E2, A>( | |
effect: Effect.Effect<R, E, A>, | |
layer: Layer.Layer<never, E2, R>, | |
) => Effect.runPromise(Effect.provideLayer(effect, layer)) | |
// | |
// | |
// | |
// | |
export async function getServerSideProps() { | |
const program = Effect.gen(function* (_) { | |
const c = yield* _(C) | |
return yield* _(c.c(1)) | |
}) | |
return { | |
props: { | |
res: { | |
one: await runProgram(program, LiveLayer), | |
two: await runProgram(program, LiveLayer2), | |
three: await runProgram(program, LiveLayer3), | |
}, | |
}, | |
} | |
} | |
const Intro = ({ res }: any) => { | |
return ( | |
<div> | |
<pre>{JSON.stringify(res, null, 2)}</pre> | |
</div> | |
) | |
} | |
export default Intro |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment