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 layerMakeClient = Layer.unwrap(
30 Effect.gen(function*() {
31 const container = yield* PgContainer
32 return PgClient.layerFrom(PgClient.makeClient({
33 url: Redacted.make(container.getConnectionUri())
34 }))
35 })
36 ).pipe(Layer.provide(this.layer))
37
38 static layerMakeClientUnprepared = Layer.unwrap(
39 Effect.gen(function*() {
40 const container = yield* PgContainer
41 return PgClient.layerFrom(PgClient.makeClient({
42 url: Redacted.make(container.getConnectionUri()),
43 prepare: false
44 }))
45 })
46 ).pipe(Layer.provide(this.layer))
47
48 static layerMakeClientAcquireForStream = Layer.unwrap(
49 Effect.gen(function*() {
50 const container = yield* PgContainer
51 return PgClient.layerFrom(PgClient.makeClient({
52 url: Redacted.make(container.getConnectionUri()),
53 applicationName: "side-default",
54 acquireForStream: true
55 }))
56 })
57 ).pipe(Layer.provide(this.layer))
58
59 static layerClientWithTransforms = Layer.unwrap(
60 Effect.gen(function*() {
61 const container = yield* PgContainer
62 return PgClient.layer({
63 url: Redacted.make(container.getConnectionUri()),
64 transformResultNames: String.snakeToCamel,
65 transformQueryNames: String.camelToSnake
66 })
67 })
68 ).pipe(Layer.provide(this.layer))
69
70 static layerClientForListen = Layer.unwrap(
71 Effect.gen(function*() {
72 const container = yield* PgContainer
73 return PgClient.layer({
74 url: Redacted.make(container.getConnectionUri()),
75 maxConnections: 2,
76 multiplex: true
77 })
78 })
79 ).pipe(Layer.provide(this.layer))
80}