Aurora.Uix.Integration.Crud behaviour (Aurora UIX v0.1.4-rc.1)

Copy Markdown

Behaviour defining unified CRUD operations with polymorphic dispatch.

Provides a consistent interface for CRUD operations across multiple backend implementations (Ash Framework and Context-based Ecto). Acts as both a behaviour specification and a dispatcher that routes operations to the appropriate implementation based on connector type.

Key Features

  • Behaviour contract with 8 callbacks for CRUD operations
  • Polymorphic dispatch to backend-specific implementations
  • Runtime module resolution via application configuration
  • Consistent interface across Ash and Context backends
  • Type-safe connector-based routing

Implementation Resolution

The module uses compile-time configuration to build a map of connector types to implementation modules. Configuration is read from :aurora_uix application:

config :aurora_uix, :crud_integration_modules,
  ash: Aurora.Uix.Integration.Ash.Crud,
  ctx: Aurora.Uix.Integration.Ctx.Crud

At runtime, get_crud_module/1 resolves the appropriate implementation:

  1. Extracts type from %Connector{type: :ash} or %Connector{type: :ctx}
  2. Looks up implementation in @crud_integration_modules map
  3. Delegates operation to resolved module (e.g., AshCrud.list/2)
  4. Raises error if type is nil or not found in configuration

Key Constraints

  • Implementation modules must implement all 8 callbacks
  • Connector type must be configured in application environment
  • Invalid or missing types raise runtime errors
  • Backend implementations are resolved at compile time for performance

Summary

Callbacks

Creates a changeset or form for updating a resource.

Creates a new resource in the database.

Deletes a resource from the database.

Retrieves a single resource by ID.

Lists resources with optional query parameters.

Creates a new resource struct with optional preloading.

Navigates to a specific page in paginated results.

Updates an existing resource in the database.

Functions

Creates a changeset for updating an entity.

Creates a new resource in the database.

Deletes a resource from the database.

Retrieves a single entity by ID using the provided Connector.

Applies a list operation using the provided Connector.

Creates a new entity struct using the provided Connector.

Navigates to a specific page in paginated results.

Updates an existing resource in the database.

Callbacks

change(term, struct, arg3, map)

@callback change(term(), struct(), atom() | binary(), map()) :: struct()

Creates a changeset or form for updating a resource.

Parameters

  • crud_spec (term()) - Backend-specific CRUD specification.
  • entity (struct()) - The resource to create a changeset for.
  • form_name (atom() | binary()) - The name of the underlying form.

  • attrs (map()) - Attributes to apply.

Returns

struct() - A changeset or form structure.

create(term, map)

@callback create(term(), map()) :: tuple()

Creates a new resource in the database.

Parameters

  • crud_spec (term()) - Backend-specific CRUD specification.
  • params (map()) - Parameters for the new resource.

Returns

tuple() - Result tuple, typically {:ok, struct()} or {:error, struct()}.

delete(term, struct)

@callback delete(
  term(),
  struct()
) :: tuple()

Deletes a resource from the database.

Parameters

  • crud_spec (term()) - Backend-specific CRUD specification.
  • entity (struct()) - The resource to delete.

Returns

tuple() - Result tuple, typically {:ok, struct()} or {:error, struct()}.

get(term, term, keyword)

@callback get(term(), term(), keyword()) :: struct() | nil

Retrieves a single resource by ID.

Parameters

  • crud_spec (term()) - Backend-specific CRUD specification.
  • id (term()) - The resource identifier.
  • opts (keyword()) - Additional query options.

Returns

struct() | nil - The retrieved resource or nil if not found.

list(term, keyword)

@callback list(
  term(),
  keyword()
) :: Aurora.Ctx.Pagination.t()

Lists resources with optional query parameters.

Parameters

  • crud_spec (term()) - Backend-specific CRUD specification.
  • opts (keyword()) - Query options passed to the backend implementation.

Returns

Pagination.t() - Pagination structure containing query results and metadata.

new(term, map, keyword)

@callback new(term(), map(), keyword()) :: struct()

Creates a new resource struct with optional preloading.

Parameters

  • crud_spec (term()) - Backend-specific CRUD specification.
  • attrs (map()) - Initial attributes for the new resource.
  • opts (keyword()) - Additional options.

Returns

struct() - A new resource struct.

to_page(term, t, integer)

Navigates to a specific page in paginated results.

Parameters

  • crud_spec (term()) - Backend-specific CRUD specification.
  • pagination (Pagination.t()) - The current pagination structure.
  • page (integer()) - The target page number.

Returns

Pagination.t() - Updated pagination structure with the requested page data.

update(term, struct, map)

@callback update(term(), struct(), map()) :: tuple()

Updates an existing resource in the database.

Parameters

  • crud_spec (term()) - Backend-specific CRUD specification.
  • entity (struct()) - The resource to update.
  • params (map()) - Parameters to update.

Returns

tuple() - Result tuple, typically {:ok, struct()} or {:error, struct()}.

Functions

apply_change_function(connector, entity, form_name, attrs \\ %{})

@spec apply_change_function(
  Aurora.Uix.Integration.Connector.t(),
  struct(),
  atom() | binary(),
  map()
) ::
  struct()

Creates a changeset for updating an entity.

Parameters

  • connector (Connector.t()) - The %Connector{} containing type and crud_spec.
  • entity (struct()) - The entity to create a changeset for.
  • form_name (atom() | binary()) - The name of the underlying form.

  • attrs (map()) - Attributes to apply to the changeset. Defaults to %{}.

Returns

struct() - A changeset structure (e.g., %AshPhoenix.Form{} or %Ecto.Changeset{}).

Examples

iex> connector = %Connector{type: :ash, crud_spec: %CrudSpec{...}}
iex> apply_change_function(connector, %MyApp.User{}, %{name: "John"})
%AshPhoenix.Form{...}

iex> connector = %Connector{type: :ctx, crud_spec: %CrudSpec{...}}
iex> apply_change_function(connector, %MyContext.Item{}, %{status: "active"})
%Ecto.Changeset{...}

apply_create_function(connector, params)

@spec apply_create_function(Aurora.Uix.Integration.Connector.t(), map()) :: tuple()

Creates a new resource in the database.

Parameters

  • connector (Connector.t()) - The %Connector{} containing type and crud_spec.
  • params (map()) - Parameters for the new resource.

Returns

tuple() - Result tuple, typically {:ok, struct()} or {:error, struct()}.

Examples

iex> connector = %Connector{type: :ctx, crud_spec: %CrudSpec{...}}
iex> apply_create_function(connector, %{name: "Alice", email: "alice@example.com"})
{:ok, %MyApp.User{name: "Alice"}}

apply_delete_function(connector, entity)

@spec apply_delete_function(
  Aurora.Uix.Integration.Connector.t(),
  struct()
) :: tuple()

Deletes a resource from the database.

Parameters

  • connector (Connector.t()) - The %Connector{} containing type and crud_spec.
  • entity (struct()) - The resource to delete.

Returns

tuple() - Result tuple, typically {:ok, struct()} or {:error, struct()}.

Examples

iex> connector = %Connector{type: :ash, crud_spec: %CrudSpec{...}}
iex> apply_delete_function(connector, %MyApp.User{id: 1})
{:ok, %MyApp.User{id: 1}}

apply_get_function(connector, id, opts)

@spec apply_get_function(Aurora.Uix.Integration.Connector.t(), term(), keyword()) ::
  struct() | nil

Retrieves a single entity by ID using the provided Connector.

Parameters

  • connector (Connector.t()) - The %Connector{} containing type and crud_spec.
  • id (term()) - The entity identifier.
  • opts (keyword()) - Options:
    • :where (list()) - Additional filter clauses (Ash only).
    • :preload (term()) - Associations to load.

Returns

struct() | nil - The retrieved entity or nil if not found.

Examples

iex> connector = %Connector{type: :ash, crud_spec: %CrudSpec{...}}
iex> apply_get_function(connector, "123", preload: [:posts])
%MyApp.User{id: "123"}

iex> apply_get_function(connector, "missing-id", [])
nil

apply_list_function(connector, opts)

@spec apply_list_function(
  Aurora.Uix.Integration.Connector.t(),
  keyword()
) :: Aurora.Ctx.Pagination.t()

Applies a list operation using the provided Connector.

Parameters

  • connector (Connector.t()) - The %Connector{} containing type and crud_spec.
  • opts (keyword()) - Query options passed to the backend implementation.

Returns

Pagination.t() - %Pagination{} structure containing query results.

Examples

iex> connector = %Connector{type: :ash, crud_spec: %CrudSpec{...}}
iex> apply_list_function(connector, where: [{:status, :eq, "active"}])
%Pagination{entries: [...], pages_count: 1}

iex> connector = %Connector{type: :ctx, crud_spec: %CrudSpec{...}}
iex> apply_list_function(connector, limit: 10)
%Pagination{entries: [...]}

apply_new_function(connector, attrs, opts)

@spec apply_new_function(Aurora.Uix.Integration.Connector.t(), map(), keyword()) ::
  struct()

Creates a new entity struct using the provided Connector.

Parameters

  • connector (Connector.t()) - The %Connector{} containing type and crud_spec.
  • attrs (map()) - Initial attributes for the new entity.
  • opts (keyword()) - Options:
    • :preload (list()) - Associations to load.

Returns

struct() - A new entity struct with the provided attributes.

Examples

iex> connector = %Connector{type: :ash, crud_spec: %CrudSpec{...}}
iex> apply_new_function(connector, %{name: "Jane"}, preload: [:profile])
%MyApp.User{name: "Jane", profile: %MyApp.Profile{}}

iex> connector = %Connector{type: :ctx, crud_spec: %CrudSpec{...}}
iex> apply_new_function(connector, %{title: "New"}, [])
%MyContext.Item{title: "New"}

apply_to_page(connector, pagination, page)

Navigates to a specific page in paginated results.

Parameters

  • connector (Connector.t()) - The %Connector{} containing type and crud_spec.
  • pagination (Pagination.t()) - The current %Pagination{} structure.
  • page (integer()) - The target page number.

Returns

Pagination.t() - Updated %Pagination{} structure with the requested page data.

Examples

iex> connector = %Connector{type: :ash, crud_spec: %CrudSpec{...}}
iex> apply_to_page(connector, %Pagination{page: 1, pages_count: 5}, 2)
%Pagination{page: 2, entries: [...]}

apply_update_function(connector, entity, params)

@spec apply_update_function(Aurora.Uix.Integration.Connector.t(), struct(), map()) ::
  tuple()

Updates an existing resource in the database.

Parameters

  • connector (Connector.t()) - The %Connector{} containing type and crud_spec.
  • entity (struct()) - The resource to update.
  • params (map()) - Parameters to update.

Returns

tuple() - Result tuple, typically {:ok, struct()} or {:error, struct()}.

Examples

iex> connector = %Connector{type: :ash, crud_spec: %CrudSpec{...}}
iex> apply_update_function(connector, %MyApp.User{id: 1}, %{name: "Bob"})
{:ok, %MyApp.User{id: 1, name: "Bob"}}