defmodule Image.Plug.SourceResolver.Composite do @moduledoc """ Source resolver that dispatches by `Image.Plug.Source.kind` to a configured set of per-kind resolvers. This is the resolver most hosts will use: a single `Image.Plug` configuration handles every URL form the Cloudflare provider can produce (file paths, absolute URLs, hosted asset ids). ### Configuration Each per-kind sub-resolver is configured as a keyword under its kind name. Sub-resolver options are passed through verbatim. * `:file` — keyword list passed to `Image.Plug.SourceResolver.File`. * `:http` — keyword list passed to `Image.Plug.SourceResolver.HTTP`. * `:hosted` — `{module, options}` for the host's hosted-asset resolver. There is no built-in implementation in v0.1; hosts plug their own asset store in here. Example: {Image.Plug.SourceResolver.Composite, file: [root: "priv/static/uploads"], http: [allowed_hosts: ["assets.example.com"]], hosted: {MyApp.AssetResolver, table: :my_assets}} """ @behaviour Image.Plug.SourceResolver alias Image.Plug.{Error, Source} alias Image.Plug.SourceResolver @impl Image.Plug.SourceResolver def load(%Source{kind: kind} = source, options) do case dispatch(kind, options) do {:ok, {module, sub_options}} -> module.load(source, sub_options) {:error, _} = error -> error end end defp dispatch(:path, options) do case Keyword.fetch(options, :file) do {:ok, sub_options} -> {:ok, {SourceResolver.File, sub_options}} :error -> kind_not_configured(:path) end end defp dispatch(:url, options) do case Keyword.fetch(options, :http) do {:ok, sub_options} -> {:ok, {SourceResolver.HTTP, sub_options}} :error -> kind_not_configured(:url) end end defp dispatch(:hosted, options) do case Keyword.fetch(options, :hosted) do {:ok, {module, sub_options}} when is_atom(module) and is_list(sub_options) -> {:ok, {module, sub_options}} {:ok, module} when is_atom(module) -> {:ok, {module, []}} :error -> kind_not_configured(:hosted) end end defp kind_not_configured(kind) do {:error, Error.new(:invalid_option, "no resolver configured for source kind", details: %{kind: kind})} end end