skuld_repo

View Source

Repo > | Umbrella →

Ecto integration for Skuld — an effectful dispatch facade that makes database calls feel like any other effect, with swappable backends for testing. Write once against the effectful interface; swap InMemory in tests, Ecto in production.

What's included

  • Skuld.Repo — effectful dispatch facade generated by EffectfulFacade. Typed callers for all standard Ecto operations (insert, get, get_by, update, delete, one, all, etc.) with bang variants that auto-Throw on error.
  • Skuld.Repo.Ecto — production handler wrapping a real Ecto Repo. Dispatches operations through the Port effect exactly as your app would, with full Ecto query pipeline.
  • Skuld.Repo.InMemory — closed-world in-memory store. All data must be inserted before queries that depend on it. Fast, deterministic, no database process — ideal for integration tests.
  • Skuld.Repo.OpenInMemory — open-world in-memory store. Similar to InMemory but supports dynamic seeding via callbacks. Useful when test data comes from factories or fixtures.
  • Skuld.Repo.Stub — stateless stub returning canned responses. Use for unit tests where you want exact control over every query result without building up state.
  • Skuld.Effects.Transaction.Ecto — database transaction handler. Wraps computations in real Ecto transactions with env state rollback semantics. Composes with EffectLogger for durable workflows.

Installation

def deps do
  [
    {:skuld_repo, "~> 0.32"}
  ]
end

Example: test-first with InMemory

# Production
comp do
  user <- Repo.insert!(%User{name: "Alice"})
  found <- Repo.get(User, user.id)
  found
end
|> Port.with_handler(%{Repo.Effectful => MyApp.Repo.Ecto})
|> Throw.with_handler()
|> Comp.run!()

# Test — same code, zero setup beyond the handler
comp
|> Port.with_handler(%{Repo.Effectful => Repo.InMemory.new()})
|> Throw.with_handler()
|> Comp.run!()

Further reading

See the architecture guide for how this fits into the Skuld ecosystem.


Repo > | Umbrella →