The two choices here are basically the real options; to change the introspection would require diving into parts of Absinthe that would potentially break compatibility with GraphQL clients.
I have sort of done both directions, although for different reasons. As an example, I have an Invoice
object (we use Relay):
node object(:invoice) do
field :invoice_date, :date
field :sales, :integer
field :margin, :integer, resolve: &InvoiceResolver.margin/3
field :cost, :integer, resolve: &InvoiceResolver.cost/3
field :profit, :integer, resolve: &InvoiceResolver.profit/3
end
In my InvoiceResolver
, I have some /3
resolvers:
defmodule InvoiceResolver do
# various includes and aliases, etc., including `Canada.can?/2`
def margin(%{margin: value} = invoice, _, %{context: %{current_user: current_user}}) do
if can?(current_user, show, {invoice, :margin}) do
{:ok, value}
else
{:ok, nil}
end
end
# &c…
end
This is actually important from my perspective because some employees can see the cost, profit, and margin…but others cannot (and customers definitely cannot).
In a different scenario, I’ve added a second Absinthe schema (plus endpoint and Absinthe.Plug instance). I’ve come up with some ways of sharing some of the definitions between the two schemas and some of the resolvers, but the is is less satisfying to me overall. The reason that I did it this way was that the purpose of the two APIs was different (one is primarily for consumption and customer-centric interaction; the other is primarily for creation and employee-centric interaction). We are thinking of adding a third schema for an administrative API, but I’d need to come up with some better abstractions about managing multiple related schema before I chase this further.