1import { PgClient } from "@effect/sql-pg"
2import { PostgreSqlContainer } from "@testcontainers/postgresql"
3import { Context, Data, Effect, Layer, Redacted, String } from "effect"
4
5export class ContainerError extends Data.TaggedError("ContainerError")<{
6 cause: unknown
7}> {}
8
9export class PgContainer extends Context.Service<PgContainer>()("test/PgContainer", {
10 make: Effect.acquireRelease(
11 Effect.tryPromise({
12 try: () => new PostgreSqlContainer("postgres:alpine").start(),
13 catch: (cause) => new ContainerError({ cause })
14 }),
15 (container) => Effect.promise(() => container.stop())
16 )
17}) {
18 static readonly layer = Layer.effect(this)(this.make)
19
20 static layerClient = Layer.unwrap(
21 Effect.gen(function*() {
22 const container = yield* PgContainer
23 return PgClient.layer({
24 url: Redacted.make(container.getConnectionUri())
25 })
26 })
27 ).pipe(Layer.provide(this.layer))
28
29 static layerClientWithTransforms = Layer.unwrap(
30 Effect.gen(function*() {
31 const container = yield* PgContainer
32 return PgClient.layer({
33 url: Redacted.make(container.getConnectionUri()),
34 transformResultNames: String.snakeToCamel,
35 transformQueryNames: String.camelToSnake
36 })
37 })
38 ).pipe(Layer.provide(this.layer))
39}