defmodule Tableau.DataExtension do
@moduledoc """
YAML files and Elixir scripts (.exs) in the configured directory will be automatically parsed/executed and made available in an `@data` assign in your templates.
Elixir scripts will be executed and the last expression returned as the data.
## Configuration
- `:enabled` - boolean - Extension is active or not.
- `:dir` - string - Directory to scan for data files. Defaults to `_data`
### Example
```elixir
config :tableau, Tableau.DataExtension,
enabled: true,
dir: "_facts"
```
### YAML
```yaml
# _facts/homies.yaml
- name: Mitch
- name: Jimbo
- name: Bobby
```
```heex
```
### Elixir
```elixir
# _facts/homies.exs
resp = Req.get!("https://example.com/homies")
resp.body["homies"]
```
```heex
```
"""
use Tableau.Extension, key: :data, priority: 200
import Schematic
@impl Tableau.Extension
def config(config) do
unify(
map(%{
optional(:enabled, true) => bool(),
optional(:dir, "_data") => str()
}),
config
)
end
@impl Tableau.Extension
def pre_build(token) do
data =
for file <- Path.wildcard(Path.join(token.extensions.data.config.dir, "**/*.{yml,yaml,exs}")), into: %{} do
case Path.extname(file) do
".exs" ->
key = Path.basename(file, ".exs")
{result, _binding} = Code.eval_file(file)
{key, result}
yaml when yaml in ~w[.yml .yaml] ->
key =
file
|> Path.basename(".yaml")
|> Path.basename(".yml")
{key, YamlElixir.read_from_file!(file)}
end
end
{:ok, Map.put(token, :data, data)}
end
end