# `DocShell.Config`
[🔗](https://github.com/futhr/doc_shell/blob/v2.0.0/lib/doc_shell/config.ex#L1)

Resolves build settings from per-call options, host config, and defaults.

Three layers, highest precedence first:

  1. options passed to `DocShell.Build.run/1`
  2. the host's `config :doc_shell` application environment
  3. the package defaults below

The defaults are Elixir literals in this module rather than entries in a
`config/config.exs`, because a library's config files are never loaded by the
projects that depend on it — only its own build reads them. Keeping defaults
in code is what makes `DocShell.Build.run()` with no arguments produce a
valid artifact tree in a project that has configured nothing.

## Keys

| Key | Default | Purpose |
| --- | --- | --- |
| `:modules` | `[]` | Modules to document. `mix doc_shell.build` fills this from the application spec. |
| `:collection` | unset | Immutable source descriptor used to emit a site-ready `collection.json`. |
| `:guide_bases` | `["guides"]` | Directories searched recursively for Markdown guides. |
| `:changelog_source` | `DocShell.Generate.Changelog.Sources.MarkdownFile` | Source adapter for changelog/release-note entries; set `nil` or `false` to disable. |
| `:changelog_options` | `[]` | Options passed to the configured changelog source. |
| `:changelog_path` | `"CHANGELOG.md"` | Compatibility shortcut for the default Markdown-file source path. |
| `:livebook_base` | `"notebooks"` | Directory searched recursively for `.livemd` notebooks. |
| `:public_dir` | `"priv/doc_shell/public"` | Where the artifact tree is written. |
| `:private_dir` | `"priv/doc_shell/private"` | Where the private manifest is written. |
| `:open_api_adapter` | unset | Adapter module, or unset for an empty OpenAPI document. |
| `:open_api_options` | `[]` | Extra options merged into the adapter call. |
| `:openapi_spec_path` | unset | Also write the OpenAPI document unenveloped here, for tools that expect a plain spec file. |
| `:domains` | `[]` | Ash domains, for the AshOaskit adapter. |
| `:title` | `"Documentation"` | API title in the OpenAPI `info` block. |
| `:api_version` | `"0.1.0"` | API version in the OpenAPI `info` block. |
| `:security_schemes` | `%{}` | OpenAPI `components.securitySchemes`. |
| `:presentation_source` | `StaticGenerator` | Module producing navigation, search, and content. |
| `:path_builder` | unset | Function from entry to path; overrides `/docs/{kind}/{id}`. |
| `:skip_empty` | `true` | Drop entries with no content from the presentation. |
| `:search_tokens` | `false` | Populate `SearchEntry.tokens`. |
| `:search_members` | `false` | Include module member names, signatures and docs in page search text. |
| `:member_metadata` | ExDoc keys, see `DocShell.Generate.ExDoc` | Member metadata keys kept in `modules.json`; `:all` keeps every key. |
| `:pretty` | `false` | Indent written artifacts for debugging. Artifacts are compact canonical JSON otherwise. |
| `:write` | `true` | Write the artifact tree. `false` returns the data only. |

Every key is optional, including `:open_api_adapter` — with no adapter the
build emits a valid empty OpenAPI 3.1 document rather than failing, so a
project with no API still gets a complete artifact tree.

## One application

DocShell reads `:doc_shell` and nothing else. It will not look under the host
application's own key, infer settings from `Mix.Project`, or reach into
another library's environment. Unknown keys under `:doc_shell` are ignored
rather than passed along, which keeps a typo from silently reaching an
adapter.

# `t`

```elixir
@type t() :: keyword()
```

Fully resolved build configuration.

# `fetch!`

```elixir
@spec fetch!(t(), atom()) :: term()
```

Fetches a value that must be present, raising if it is not.

Reserved for keys with a package default, where absence means the config was
built by something other than `load/1` rather than that the host forgot
something.

# `load`

```elixir
@spec load(keyword()) :: t()
```

Returns the resolved configuration: defaults, then host config, then
`overrides`.

Only recognised keys are read from the application environment.

# `resolve`

```elixir
@spec resolve(term()) :: {:ok, t()} | {:error, term()}
```

Resolves and validates build options, returning the offending key on error.

---

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