SelectoMix

⚠️ Alpha Quality Software

selecto_mix is under active development. Expect breaking changes, behavior changes, incomplete features, and potentially major bugs.

Mix tasks and tooling for automatic Selecto configuration generation from Ecto schemas.

SelectoMix provides utilities to automatically generate Selecto domain configurations from your existing Ecto schemas, preserving user customizations across regenerations and supporting incremental updates when schemas change.

Livebooks, Tutorials, and Demo

Features

Installation

Add selecto_mix to your list of dependencies in mix.exs:

def deps do
  [
    {:selecto_mix, "~> 0.4.0"},
    {:selecto, "~> 0.4.0"},
    {:selecto_db_postgresql, "~> 0.4.0"},
    {:postgrex, ">= 0.0.0"},
    {:ecto, "~> 3.10"}
  ]
end

mix selecto.install now ensures the PostgreSQL driver dependency is present for the default PostgreSQL adapter path.

Then run the installer (recommended for most projects):

mix igniter.install selecto_mix
cd assets && npm install
mix assets.build

Development mode (use your fork/source owner for vendor clones):

mix selecto.install --development-mode --source your-github-user

Release Status (0.4.x)

Quick Start

  1. Generate domains for all schemas:

    mix selecto.gen.domain --all
  2. Generate domain for a specific schema:

    mix selecto.gen.domain Blog.Post
  3. Use the generated domain in your application:

    # In your context or controller
    alias MyApp.SelectoDomains.PostDomain
    
    # Get all posts
    {:ok, {posts, columns, aliases}} = PostDomain.all(MyApp.Repo)
    
    # Find a specific post
    {:ok, {post, aliases}} = PostDomain.find(MyApp.Repo, 123)
    
    # Search with filters
    {:ok, {posts, columns, aliases}} = PostDomain.search(MyApp.Repo, %{
      "status" => "published",
      "category" => "tech"
    })

Generated Files

For each Ecto schema, SelectoMix generates:

Domain Configuration (*_domain.ex)

Complete Selecto domain configuration with:

Usage Examples

Updato API Scaffolding

Scaffold an Updato API endpoint and control panel directly from SelectoMix:

mix selecto.gen.api orders --domain MyApp.OrdersDomain

The legacy alias remains available:

mix selecto.gen.updato_api orders --domain MyApp.OrdersDomain

Basic Domain Generation

# Generate domain for User schema
mix selecto.gen.domain MyApp.User

# Generate with associations included
mix selecto.gen.domain MyApp.User --include-associations

# Generate for multiple schemas
mix selecto.gen.domain MyApp.User MyApp.Post MyApp.Comment

Advanced Options

# Generate all schemas with custom output directory
mix selecto.gen.domain --all --output lib/my_app/domains

# Force regeneration (overwrites customizations)
mix selecto.gen.domain MyApp.User --force

# Dry run to see what would be generated
mix selecto.gen.domain --all --dry-run

# Exclude certain schemas
mix selecto.gen.domain --all --exclude User,InternalSchema

Configuration

Configure SelectoMix in your config/config.exs:

config :selecto_mix,
  output_dir: "lib/my_app/selecto_domains",
  default_associations: true,
  preserve_customizations: true,
  app_name: "MyApp"

Customization Preservation

SelectoMix intelligently preserves user customizations when regenerating files:

defmodule MyApp.SelectoDomains.UserDomain do
  def domain do
    %{
      source: %{
        fields: [:id, :name, :email, :custom_field], # CUSTOM: added custom_field
        # ... rest of configuration
      },
      
      filters: %{
        "status" => %{
          "name" => "Status",
          "type" => "select",
          "options" => ["active", "inactive"] # CUSTOM: added options
        }
      }
    }
  end
end

Fields, filters, and joins marked with # CUSTOM comments are preserved during regeneration.

Rerun After Schema Changes

When your Ecto schemas change, simply rerun the generation:

mix selecto.gen.domain MyApp.User

SelectoMix will:

Integration with Phoenix

Generated domains work seamlessly with Phoenix applications:

# In a Phoenix controller
defmodule MyAppWeb.PostController do
  use MyAppWeb, :controller
  
  alias MyApp.SelectoDomains.PostDomain
  
  def index(conn, params) do
    case PostDomain.search(MyApp.Repo, params) do
      {:ok, {posts, columns, aliases}} ->
        render(conn, "index.html", posts: posts, columns: columns)
    end
  end
end
# In a LiveView
defmodule MyAppWeb.PostLive.Index do
  use MyAppWeb, :live_view
  
  alias MyApp.SelectoDomains.PostDomain
  
  def handle_event("search", %{"q" => query}, socket) do
    {:ok, {posts, _columns, _aliases}} = PostDomain.search(MyApp.Repo, %{"title" => query})
    {:noreply, assign(socket, posts: posts)}
  end
end

Available Mix Tasks

Property Testing

Run the SelectoMix property suite:

mix test test/selecto_mix_property_test.exs

Contributing

  1. Fork the repository
  2. Create your feature branch (git checkout -b feature/amazing-feature)
  3. Add tests for your changes
  4. Ensure all tests pass (mix test)
  5. Commit your changes (git commit -am 'Add amazing feature')
  6. Push to the branch (git push origin feature/amazing-feature)
  7. Create a Pull Request

License

This project is licensed under the MIT License - see the LICENSE file for details.