DSL entry point. use Caravela.Domain in a module to declare a domain:
defmodule MyApp.Domains.Library do
use Caravela.Domain
entity :authors do
field :name, :string, required: true
field :bio, :text
end
entity :books do
field :title, :string, required: true, min_length: 3
field :isbn, :string, format: ~r/^\d{13}$/
end
relation :authors, :books, type: :has_many
on_create :books, fn changeset, _context ->
Ecto.Changeset.validate_required(changeset, [:title])
end
can_create :books, fn context ->
context.current_user.role in [:admin, :editor]
end
endAfter compilation the module exposes __caravela_domain__/0, returning
the validated Caravela.Schema.Domain IR, plus __caravela_hook__/4
and __caravela_permission__ clauses for every declared hook and
permission.
Summary
Functions
Authorize creation of an entity. Receives only the context and must
return a boolean.
Authorize deletion of an entity. Same shape as can_update/2.
Filter a read query by authorization context. Must return an
Ecto.Query.
Authorize updating an entity. Receives the loaded entity and the
context. Must return a boolean.
Declare an entity (a table/schema) with a do block of fields.
Declare a field inside an entity block.
Declare a create-time hook for an entity. The hook receives the
Ecto.Changeset and the caller's context map, and must return an
Ecto.Changeset.
Declare a delete-time hook. The hook receives the loaded entity and
the context, and must return :ok or {:error, reason}.
Declare an update-time hook. Same shape as on_create/2.
Declare a relation between two entities.
Declare the API version for this domain. Must match ~r/^v\d+$/.
Functions
Authorize creation of an entity. Receives only the context and must
return a boolean.
can_create :books, fn context ->
context.current_user.role in [:admin, :editor]
end
Authorize deletion of an entity. Same shape as can_update/2.
Filter a read query by authorization context. Must return an
Ecto.Query.
can_read :books, fn query, context ->
case context.current_user.role do
:admin -> query
_ -> where(query, [b], b.published == true)
end
end
Authorize updating an entity. Receives the loaded entity and the
context. Must return a boolean.
can_update :books, fn book, context ->
context.current_user.role == :admin or book.author_id == context.current_user.author_id
end
Declare an entity (a table/schema) with a do block of fields.
entity :books do
field :title, :string, required: true
end
Declare a field inside an entity block.
field :title, :string, required: true, min_length: 3
Declare a create-time hook for an entity. The hook receives the
Ecto.Changeset and the caller's context map, and must return an
Ecto.Changeset.
on_create :books, fn changeset, _context ->
Ecto.Changeset.validate_required(changeset, [:title])
end
Declare a delete-time hook. The hook receives the loaded entity and
the context, and must return :ok or {:error, reason}.
on_delete :authors, fn author, _context ->
if author.published?, do: {:error, :has_published_books}, else: :ok
end
Declare an update-time hook. Same shape as on_create/2.
on_update :books, fn changeset, _context ->
changeset
end
Declare a relation between two entities.
relation :authors, :books, type: :has_many
relation :books, :publishers, type: :belongs_to
Declare the API version for this domain. Must match ~r/^v\d+$/.
version "v1"When set, all generated modules are namespaced under the version
(MyApp.Library.V1.Book) and controller routes are prefixed with
/api/v1/.