| 1 | import { PgClient } from "@effect/sql-pg" |
| 2 | import { PostgreSqlContainer } from "@testcontainers/postgresql" |
| 3 | import { Context, Data, Effect, Layer, Redacted, String } from "effect" |
| 4 | |
| 5 | export class ContainerError extends Data.TaggedError("ContainerError")<{ |
| 6 | cause: unknown |
| 7 | }> {} |
| 8 | |
| 9 | export 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 | } |