Last active
December 2, 2017 15:06
-
-
Save tlux/765835296ef3e547cd0e232a0c1eed47 to your computer and use it in GitHub Desktop.
GraphQL: Using fragments on interfaces or unions with Absinthe and Apollo. The Mix task basically generates a JSON file from your Absinthe schema that contains mappings of interfaces/unions to the particular implemented types. This file can subsequently be read by your custom Apollo client.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Provides an automated solution for the following issue: | |
// http://dev.apollodata.com/react/initialization.html#fragment-matcher | |
import { | |
ApolloClient, | |
createNetworkInterface, | |
IntrospectionFragmentMatcher | |
} from 'apollo-client' | |
import types from './typemap.json' | |
// Use a custom fragment matcher to tell Apollo how interface and union types | |
// used in fragments resolve to implemented types. | |
const fragmentMatcher = new IntrospectionFragmentMatcher({ | |
introspectionQueryResultData: { | |
__schema: { types } | |
} | |
}) | |
// Define a the GraphQL endpoint. | |
const networkInterface = createNetworkInterface({ | |
uri: '/graphql' | |
}) | |
// Build the Apollo client. | |
export default new ApolloClient({ | |
networkInterface, | |
fragmentMatcher | |
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
defmodule Mix.Tasks.Apollo.Gen.Typemap do | |
@moduledoc """ | |
Provides a task to regenerate the fragment-types.json file which provides | |
details about GraphQL interfaces and unions that are used by the Apollo | |
library. | |
""" | |
use Mix.Task | |
alias Absinthe.Schema, as: SchemaUtils | |
alias Absinthe.Type.Interface | |
alias Absinthe.Type.Union | |
# TODO: Replace this with your own Absinthe schema! | |
alias MyApp.Web.Schema | |
@shortdoc "Generates a GraphQL typemap.json file for Apollo" | |
# TODO: Whereever you want your file to be located! | |
@path Path.join(File.cwd!, "./typemap.json") | |
@doc false | |
@spec run([String.t]) :: any | |
def run(_args) do | |
data = for type <- SchemaUtils.types(Schema), | |
type.__struct__ in [Interface, Union] do | |
identifier = type.__reference__.identifier | |
implementations = SchemaUtils.concrete_types(Schema, identifier) | |
kind = case type do | |
%Interface{} -> "INTERFACE" | |
%Union{} -> "UNION" | |
end | |
possible_types = Enum.map(implementations, &%{"name" => &1.name}) | |
%{ | |
"kind" => kind, | |
"name" => type.name, | |
"possibleTypes" => possible_types | |
} | |
end | |
Application.ensure_all_started(:poison) | |
serialized_data = Poison.encode!(data, pretty: true) | |
File.write!(@path, serialized_data) | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Thanks for the hint! I fixed that in the original code.