# `Spark.Dsl.Section`
[🔗](https://github.com/ash-project/spark/blob/v2.7.0/lib/spark/dsl/section.ex#L5)

Declares a DSL section.

A dsl section allows you to organize related configurations. All extensions
configure sections, they cannot add DSL builders to the top level. This
keeps things organized, and concerns separated.

A section may have nested sections, which will be configured the same as other sections.
Getting the options/entities of a section is done by providing a path, so you would
use the nested path to retrieve that configuration. See `Spark.Dsl.Extension.get_entities/2`
and `Spark.Dsl.Extension.get_opt/4`.

A section may have entities, which are constructors that produce instances of structs.
For more on entities, see `Spark.Dsl.Entity`.

A section may also have a `schema`, which you can learn more about in `Spark.Options`. Spark will produce
builders for those options, so that they may be configured. They are retrieved with
`Spark.Dsl.Extension.get_opt/4`.

To create a section that is available at the top level (i.e not  nested inside of its own name), use
`top_level?: true`. Remember, however, that this has no effect on sections nested inside of other sections.

`singleton_entity_keys` specifies a set of entity names (by their `:name` field) that should only
appear at most once within the section. This is validated automatically during compilation.

For a full example, see `Spark.Dsl.Extension`.

# `auto_set_fields`

```elixir
@type auto_set_fields() :: keyword(any())
```

# `describe`

```elixir
@type describe() :: String.t()
```

User provided documentation.

Documentation provided in a `Section`'s `describe` field will be included by `Spark` in any generated documentation that includes the `Section`.

# `docs`

```elixir
@type docs() :: String.t()
```

Internal field. Not set by user.

# `entities`

```elixir
@type entities() :: [Spark.Dsl.Entity.t()]
```

# `examples`

```elixir
@type examples() :: [String.t()]
```

# `imports`

```elixir
@type imports() :: [module()]
```

# `links`

```elixir
@type links() :: nil | keyword([String.t()])
```

# `modules`

```elixir
@type modules() :: [atom()]
```

# `name`

```elixir
@type name() :: atom()
```

# `no_depend_modules`

```elixir
@type no_depend_modules() :: [atom()]
```

# `patchable?`

```elixir
@type patchable?() :: boolean()
```

# `sections`

```elixir
@type sections() :: [t()]
```

# `singleton_entity_keys`

```elixir
@type singleton_entity_keys() :: [atom()]
```

# `snippet`

```elixir
@type snippet() :: String.t()
```

# `t`

```elixir
@type t() :: %Spark.Dsl.Section{
  after_define: term(),
  auto_set_fields: auto_set_fields(),
  deprecations: term(),
  describe: describe(),
  docs: docs(),
  entities: entities(),
  examples: examples(),
  imports: imports(),
  links: links(),
  modules: modules(),
  name: name(),
  no_depend_modules: no_depend_modules(),
  patchable?: patchable?(),
  schema: Spark.Options.schema(),
  sections: sections(),
  singleton_entity_keys: singleton_entity_keys(),
  snippet: snippet(),
  top_level?: top_level?()
}
```

# `top_level?`

```elixir
@type top_level?() :: boolean()
```

Determines whether a section can be declared directly in a module.

When `top_level?: true`, that Section's DSL can be declared outside of a `do` block in a module.

## Example

A `Section` declared with `top_level?: true`:

```elixir
@my_section %Spark.Dsl.Section{
  top_level?: true,
  name: :my_section,
  schema: [my_field: [type: :atom, required: true]]
}
```

Can be declared like this:

```elixir
defmodule MyDslModule do
  my_field :value
end
```

With `top_level?: false`, the DSL section would need to be declared explicitly/:

```elixir
defmodule MyDslModule do
  my_section do
    my_field :value
  end
end
```

---

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