Arc for Elixir

Arc for Elixir is an opinionated CQRS application framework for Phoenix and Plug on Cratis Chronicle, with model-bound commands and queries, validation, authorization, observable queries and opt-in TypeScript proxies for React.

Hex.pm Hex Docs License: MIT Discord

Source preview. The package is built and tested here, but the API may still change, and nothing is claimed beyond what Limits and gaps says is verified.

Overview

You write a command or a query as a plain module. Arc binds, validates, authorizes and runs it, records the events it returns in Chronicle, and serves it to React, LiveView or any HTTP client.

defmodule Library.Authors.Registration.RegisterAuthor do
  @moduledoc "Registers a new author."

  use Arc.Command

  schema do
    field :id, Library.Authors.AuthorId, key: true, required: true
    field :name, :string, required: true, min_length: 2, max_length: 50
  end

  def handle(%__MODULE__{name: name}, _ctx),
    do: {:append, %Library.Authors.AuthorRegistered{name: name}}
end

Arc for Elixir works with Chronicle only. It is part of the Cratis family of Arc implementations for .NET, Kotlin and Java, Go and TypeScript, and follows the same HTTP contract.

Install

defp deps do
  [
    {:cratis_arc, "~> 0.1"}
  ]
end

Arc needs Elixir 1.18 or later and brings cratis_chronicle with it. Phoenix, Phoenix.HTML and Phoenix LiveView are optional: the LiveView support compiles only when phoenix_live_view is a dependency. CI builds and tests with Elixir 1.19.5 on Erlang/OTP 28.5.

Add import_deps: [:cratis_arc] to .formatter.exs so field :name, :string is not rewritten with parentheses.

Prerequisite: Chronicle running

docker pull cratis/chronicle:latest-development
docker run -d --name chronicle \
  -p 127.0.0.1:35000:35000 \
  -p 127.0.0.1:27017:27017 \
  cratis/chronicle:latest-development

The 127.0.0.1: prefixes keep both ports on your machine: the development kernel accepts well-known credentials and its MongoDB has no authentication.

Getting started

Get started builds an authors feature end to end: events, a command, a query, the HTTP API, a LiveView page and a test.

Documentation

Samples

Sample Shows
Samples/plug The smallest Arc application: Bandit and a Plug router
Samples/phoenix The HTTP contract, LiveView and a React app served from one Phoenix endpoint
Samples/frontend A React app on the generated proxies

Samples/run-tests.sh builds and tests all three.

Contributing

cd Source/arc
mix deps.get
mix format --check-formatted
MIX_ENV=test mix compile --warnings-as-errors
mix test

cd ../..
Samples/run-tests.sh
ContractTests/run.sh

Pull requests need exactly one release label (major, minor, patch or no-release) and a description written as a release note; Build and release explains both. Design decisions are recorded in decisions. Questions and ideas are welcome on Discord; report confirmed bugs as issues.

License

MIT. See LICENSE.