| 1 | import { LibsqlClient } from "@effect/sql-libsql" |
| 2 | import { Context, Effect, Layer } from "effect" |
| 3 | import { GenericContainer, type StartedTestContainer } from "testcontainers" |
| 4 | |
| 5 | const waitForServer = async (container: StartedTestContainer) => { |
| 6 | const url = `http://${container.getHost()}:${container.getMappedPort(8080)}` |
| 7 | let error: unknown = undefined |
| 8 | |
| 9 | for (let i = 0; i < 60; i++) { |
| 10 | try { |
| 11 | await fetch(url) |
| 12 | return |
| 13 | } catch (cause) { |
| 14 | error = cause |
| 15 | await new Promise((resolve) => setTimeout(resolve, 250)) |
| 16 | } |
| 17 | } |
| 18 | |
| 19 | throw error |
| 20 | } |
| 21 | |
| 22 | export class LibsqlContainer extends Context.Service< |
| 23 | LibsqlContainer, |
| 24 | StartedTestContainer |
| 25 | >()("test/LibsqlContainer") { |
| 26 | static readonly layer = Layer.effect(this)( |
| 27 | Effect.acquireRelease( |
| 28 | Effect.promise(async () => { |
| 29 | const container = await new GenericContainer("ghcr.io/tursodatabase/libsql-server:main") |
| 30 | .withExposedPorts(8080) |
| 31 | .withEnvironment({ SQLD_NODE: "primary" }) |
| 32 | .withCommand(["sqld", "--no-welcome", "--http-listen-addr", "0.0.0.0:8080"]).start() |
| 33 | |
| 34 | try { |
| 35 | await waitForServer(container) |
| 36 | return container |
| 37 | } catch (error) { |
| 38 | await container.stop() |
| 39 | throw error |
| 40 | } |
| 41 | }), |
| 42 | (container) => Effect.promise(() => container.stop()) |
| 43 | ) |
| 44 | ) |
| 45 | |
| 46 | static layerClient = Layer.unwrap( |
| 47 | Effect.gen(function*() { |
| 48 | const container = yield* LibsqlContainer |
| 49 | return LibsqlClient.layer({ |
| 50 | url: `http://${container.getHost()}:${container.getMappedPort(8080)}` |
| 51 | }) |
| 52 | }) |
| 53 | ).pipe(Layer.provide(this.layer)) |
| 54 | } |