SelectoMix

Alpha software. Generation flows are usable but still evolving.

selecto_mix is the tooling package for setting up Selecto in an Elixir project.

Use it when you want to:

Installation

def deps do
[
{:selecto_mix, ">= 0.4.6 and < 0.6.0"},
{:selecto, ">= 0.4.6 and < 0.6.0"},
{:selecto_db_postgresql, ">= 0.4.4 and < 0.6.0"},
{:postgrex, ">= 0.0.0"},
{:ecto, "~> 3.10"}
]
end

Then run:

mix igniter.install selecto_mix
mix assets.build

For local multi-repo workspace development:

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

Quick Start

Generate a domain from one schema:

mix selecto.gen.domain MyApp.Catalog.Product

Generate domains for all schemas:

mix selecto.gen.domain --all

Generate a domain plus LiveView wiring:

mix selecto.gen.domain MyApp.Catalog.Product --live

Generate a trusted provider module for Studio's host-app artifact registry:

mix selecto.gen.domain MyApp.Catalog.Product --studio-artifacts

The generated provider uses core Selecto.Domain inspection APIs. Register it with config :selecto_studio, :domain_artifacts in the host app when you want SelectoStudioWeb.DomainInspectionController to preload that domain.

The generated router notice includes the LiveView route plus optional SelectoComponents.QueryContract.Plug, SelectoComponents.QueryContract.Guide.Plug, and SelectoComponents.QueryContract.IntentValidator.Plug routes for serving query-contract.json, a compact Markdown query-guide.md, and a non-executing query intent validator.

Generate an Updato API endpoint and control panel:

mix selecto.gen.api products --domain MyApp.SelectoDomains.ProductDomain --schema MyApp.Catalog.Product

Generated Updato control panels can render write fields backed by Selecto choice_sources. To enable option loading and membership validation, assign choice-source resolvers and scope from the LiveView socket or session:

socket
|> assign(
choice_source_domain: MyApp.SelectoDomains.ProductChoiceSources.domain(),
choice_source_options_resolver: &MyApp.SelectoDomains.ProductChoiceSources.resolve_options/1,
choice_source_membership_resolver: &MyApp.SelectoDomains.ProductChoiceSources.resolve_membership/1,
choice_source_value_parser: &MyApp.SelectoDomains.ProductChoiceSources.parse_value/2,
choice_source_scope: %{
actor: socket.assigns.current_scope.user,
tenant: socket.assigns.current_scope.user.account_id,
context: %{surface: :updato_control_panel}
}
)

Keep actor, tenant, and required domain filters server-owned. Browser payloads may provide search text or a selected id, but they should not be trusted for tenant or authorization scope.

For choice sources whose Domain-of-Interest filters are security-sensitive, declare a fail-closed policy in the domain overlay:

defchoice_source(:product_assignees, %{
domain: :employees,
value_field: :id,
label_field: :full_name,
constraint_policy: %{domain_of_interest: :fail_closed}
})

Resolvers should return a closed option/membership result when that policy is present and any trusted filter cannot be enforced.

Core Workflow

Recommended workflow:

  1. Generate the base domain from your Ecto schema.
  2. Keep schema-derived structure in the generated file.
  3. Put custom filters, columns, and named functions in overlays when possible.
  4. Re-run generation when schemas change.

That keeps generated structure and user-authored behavior separate.

Common Tasks

After mix selecto.gen.domain creates a domain, it prints the matching export/check/import/inspect/describe/diagram/docs follow-up commands with suggested priv/selecto/*.normalized.json, priv/selecto/*.inspection.json, and docs/selecto/*.diagram.mmd / docs/selecto/*.md artifact paths.

Export a normalized domain JSON artifact:

mix selecto.domain.export MyApp.SelectoDomains.ProductDomain --output priv/selecto/product.normalized.json

Runtime-only values such as function captures are emitted as explicit placeholder metadata so the artifact remains JSON-safe for tools.

Check an exported artifact without loading the original domain module:

mix selecto.domain.check priv/selecto/product.normalized.json

Preview the current import/readback plan:

mix selecto.domain.import priv/selecto/product.normalized.json --check

The import check includes a generated-domain preview with the target module, target file, reconstructed sections, and runtime placeholders that still need manual handling. It also parses the source preview and checks that the target module and domain/0 are present without executing the code.

Add --source to print the would-be Elixir module source without writing it, or use --format json to include the source preview in the import plan.

Write the generated module only after that preview is fully validated and has no runtime placeholders:

mix selecto.domain.import priv/selecto/product.normalized.json --write --target-file lib/my_app/selecto_domains/product_domain.ex

Existing files are preserved by default; pass --force when you intentionally want to overwrite the target.

Inspect the same artifact for a compact sections/counts/registries summary:

mix selecto.domain.inspect priv/selecto/product.normalized.json

Generate Studio/tooling inspection JSON from the same artifact:

mix selecto.domain.describe priv/selecto/product.normalized.json --output priv/selecto/product.inspection.json

Generate a Mermaid diagram from the inspection artifact:

mix selecto.domain.diagram priv/selecto/product.inspection.json --output docs/selecto/product.diagram.mmd

Generate Markdown docs from the same artifact, including capability usage tables when the domain declares capability references:

mix selecto.domain.docs priv/selecto/product.normalized.json --output docs/selecto/product.md

Diff two artifacts:

mix selecto.domain.diff priv/selecto/old.normalized.json priv/selecto/new.normalized.json

UDF Workflow

Generated domains include a stable functions: %{} section.

Generated overlays include deffunction examples so named function registrations can live outside regenerated files.

Recommended UDF pattern:

  1. generate the domain
  2. keep structural metadata in the generated domain file
  3. add custom deffunction definitions in the overlay
  4. regenerate safely as schemas evolve

Status

Current 0.4.x scope:

Demos And Tutorials