# `AshScylla.MixHelpers`
[🔗](https://github.com/ohhi-vn/ash_scylla/blob/main/lib/ash_scylla/mix_helpers.ex#L1)

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.

# `app_name`

```elixir
@spec app_name() :: atom()
```

Returns the application name from Mix config.

# `ash_domain?`

```elixir
@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?`

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

Checks if a resource module uses `AshScylla.DataLayer`.

# `file_to_module`

```elixir
@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`

```elixir
@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`

```elixir
@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`

```elixir
@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`

```elixir
@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`

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

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

# `project_domains`

```elixir
@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`

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

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

# `scan_files_for_resources`

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

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

---

*Consult [api-reference.md](api-reference.md) for complete listing*
