defmodule BridgeEx.Extensions.ExternalResources do
@moduledoc """
Preload a set of resources marking them as "external" and provide the related getter functions.
## Options
* `resources` (required): enumerable of resource names (atoms) and their paths (strings).
Each path is assumed to be relative to the module directory.
## Examples
```elixir
defmodule MyBridge do
use BridgeEx.Extensions.ExternalResources,
resources: [
my_query: "queries/query.graphql",
my_mutation: "mutations/mutation.graphql"
]
# it generates the following code:
@external_resource "\#{__DIR__}/queries/query.graphql"
@external_resource "\#{__DIR__}/mutations/mutation.graphql"
@spec my_query() :: String.t()
def my_query, do: Map.fetch!(external_resources(), :my_query)
@spec my_mutation() :: String.t()
def my_mutation, do: Map.fetch!(external_resources(), :my_mutation)
defp external_resources do
%{
my_query: "contents of query.graphql",
my_mutation: "contents of mutation.graphql"
}
end
end
```
"""
defmacro __using__(resources: resources) do
dir = Path.dirname(__CALLER__.file)
resources = for {name, path} <- resources, do: {name, Path.join(dir, path)}
contents = for {name, path} <- resources, into: %{}, do: {name, File.read!(path)}
getters =
for {name, _path} <- resources do
quote do
@spec unquote(name)() :: String.t()
def unquote(name)(), do: Map.fetch!(external_resources(), unquote(name))
end
end
external_resource_attributes =
for {_name, path} <- resources do
quote do: @external_resource(unquote(path))
end
quote generated: true do
unquote_splicing(external_resource_attributes)
unquote_splicing(getters)
defp external_resources, do: unquote(Macro.escape(contents))
end
end
end