defmodule OrgGarden.Config do @moduledoc """ Centralized configuration access with validation. Provides a unified interface for accessing configuration values, with support for defaults and required value validation. ## Usage OrgGarden.Config.get(:http_port) #=> 8080 OrgGarden.Config.get!(:quartz_path) #=> "/path/to/quartz" or raises if not set OrgGarden.Config.pipeline_opts() #=> %{zotero_url: "...", bibtex_file: nil, citation_mode: :warn} """ @doc """ Get a configuration value with an optional default. """ def get(key, default \\ nil) do Application.get_env(:org_garden, key, default) end @doc """ Get a required configuration value. Raises if not set. """ def get!(key) do case Application.get_env(:org_garden, key) do nil -> raise ArgumentError, "Missing required configuration: #{key}" value -> value end end @doc """ Build pipeline options map for transforms. """ def pipeline_opts do %{ zotero_url: get(:zotero_url, "http://localhost:23119"), bibtex_file: get(:bibtex_file), citation_mode: get(:citation_mode, :warn) } end @doc """ Validate that all required configuration is present. Returns :ok or {:error, reasons}. """ def validate do errors = [] |> validate_quartz_path() |> validate_citation_mode() case errors do [] -> :ok errors -> {:error, errors} end end @doc """ Validate configuration and raise on errors. """ def validate! do case validate() do :ok -> :ok {:error, errors} -> raise "Configuration errors: #{inspect(errors)}" end end # Private validation helpers defp validate_quartz_path(errors) do case get(:quartz_path) do nil -> errors path -> cli_path = Path.join(path, "quartz/bootstrap-cli.mjs") if File.exists?(cli_path) do errors else [{:quartz_path, "bootstrap-cli.mjs not found at #{cli_path}"} | errors] end end end defp validate_citation_mode(errors) do case get(:citation_mode) do mode when mode in [:silent, :warn, :strict] -> errors other -> [{:citation_mode, "Invalid citation mode: #{inspect(other)}"} | errors] end end end