AshScylla.MixHelpers (AshScylla v1.7.1)

Copy Markdown View Source

Shared helper functions for AshScylla Mix tasks.

Provides resource/repo discovery, CLI option handling, and file scanning used by ash_scylla.gen, ash_scylla.migrate, ash_scylla.new_template, ash_scylla.setup, and ash_scylla.gen.repo.

Discovery

Resources are discovered by:

  1. Reading :ash_domains app env config
  2. Calling Ash.Domain.Info.resources/1 on each domain
  3. Filtering to modules using AshScylla.DataLayer
  4. Falling back to scanning lib/**/*.ex files

Umbrella Support

project_apps/0 returns the current app plus all umbrella children, enabling resource discovery in umbrella projects.

Summary

Functions

Adds child application paths to the code path.

Returns the application name from Mix config.

Checks if a module is a valid Ash domain.

Checks if a resource module uses AshScylla.DataLayer.

Converts a file path to a module name.

Finds all AshScylla resources via domain config, with file-scan fallback.

Finds and returns the default repo module from AshScylla resources.

Converts a string CLI option value to a module atom, if present.

Returns the glob pattern used to discover generated migration files.

Returns the list of app atoms to scan: the current app + umbrella children.

Discovers Ash domains from the project's app configuration.

Returns the list of lib/ directories to scan (current app + umbrella children).

Scans all .ex files in project lib/ directories for AshScylla resources.

Functions

add_child_app_paths()

Adds child application paths to the code path.

This ensures that dependencies (child apps) are available when running migrations or other tasks that need access to compiled modules.

app_name()

@spec app_name() :: atom()

Returns the application name from Mix config.

ash_domain?(module)

@spec ash_domain?(module()) :: boolean()

Checks if a module is a valid Ash domain.

Verifies the module is compiled and exports domain?/0 (added by use Ash.Domain), which distinguishes domains from plain modules.

ash_scylla_resource?(resource)

@spec ash_scylla_resource?(module()) :: boolean()

Checks if a resource module uses AshScylla.DataLayer.

file_to_module(file)

@spec file_to_module(String.t()) :: atom() | nil

Converts a file path to a module name.

Examples

iex> AshScylla.MixHelpers.file_to_module("lib/my_app/resources/user.ex")
:"Elixir.MyApp.Resources.User"

find_all_resources()

@spec find_all_resources() :: [module()]

Finds all AshScylla resources via domain config, with file-scan fallback.

  1. Reads configured domains from app env
  2. Gets each domain's resources via Ash.Domain.Info.resources/1
  3. Filters to AshScylla resources
  4. Falls back to scanning lib/**/*.ex files if no domains configured

find_default_repo()

@spec find_default_repo() :: module()

Finds and returns the default repo module from AshScylla resources.

Extracts the repo from each resource's DSL config and returns the first one.

maybe_atomize(opts, key)

@spec maybe_atomize(
  keyword(),
  atom()
) :: keyword()

Converts a string CLI option value to a module atom, if present.

Uses Module.concat/1 to produce a proper module reference (e.g. "MyApp.User" becomes MyApp.User, not :"MyApp.User").

migration_glob(base_path)

@spec migration_glob(String.t()) :: String.t()

Returns the glob pattern used to discover generated migration files.

Migration files are written as .exs (matching Ecto's convention for non-compiled migration files). Keeping this in one place means the writer (AshScylla.MigrationGenerator) and every reader (AshScylla.SchemaLoader, Mix.Tasks.AshScylla.Migrate, ...) agree on the extension.

Examples

iex> AshScylla.MixHelpers.migration_glob("priv/repo/migrations")
"priv/repo/migrations/**/*.exs"

project_apps()

@spec project_apps() :: [atom()]

Returns the list of app atoms to scan: the current app + umbrella children.

project_domains()

@spec project_domains() :: [module()]

Discovers Ash domains from the project's app configuration.

Checks each app for :ash_domains config, ensures modules are compiled, and validates they are actual Ash domains (Spark DSL modules).

project_lib_paths()

@spec project_lib_paths() :: [String.t()]

Returns the list of lib/ directories to scan (current app + umbrella children).

scan_files_for_resources()

@spec scan_files_for_resources() :: [module()]

Scans all .ex files in project lib/ directories for AshScylla resources.