Skip to main content

README.md

# skuld_repo

<!-- nav:header:start -->
[Repo >](docs/effects/repo.md) | [Umbrella →](https://hexdocs.pm/skuld/architecture.html)
<!-- nav:header:end -->

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

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

## Example: test-first with InMemory

```elixir
# 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

- [Repo](https://hexdocs.pm/skuld_repo/repo.html) — full operation reference
- [Hexagonal Architecture](https://hexdocs.pm/skuld/hexagonal-architecture.html) — Port/Adapter pattern in depth

See the [architecture guide](https://hexdocs.pm/skuld/architecture.html) for how this fits into the Skuld ecosystem.

<!-- nav:footer:start -->

---

[Repo >](docs/effects/repo.md) | [Umbrella →](https://hexdocs.pm/skuld/architecture.html)
<!-- nav:footer:end -->