Customize
There are many ways to customize GraphQL Explorer. All the strategies involve changing the configuration objects. You can either achieve this by mutating the properties of the initialized configuration object, or by subclassing the ExplorerConfiguration class and overriding the methods, depending on your desired customization. Here are some common customization paths
#
Customize inputsBy default, GraphQL Explorer introspects the gql schema and uses yup and react-widgets to dynamically generate the forms for mutation and query arguments. You can modify the input component or the schema to use for specific types or fields by modifying the Configuration.inputFieldResolvers
field:
const myInputFieldResolver: InputFieldResolver = { check: (type) => type === g.GraphQLString && field.name == 'color', getSchema: () => yup.string().oneOf(['blue', 'red']).trim(), Component: ({ value, onChange }) => ( <div> <CoolColorDropdown value={value} onChange={onChange} /> </div> ),};
configuration.inputFieldResolvers.push(myInputFieldResolver);
check
required A predicate that determines for which field this resolver applies togetSchema
if specified, overrides the default schema for that typeComponent
if specified, overrides the default input component for that type
It's important to know that the order in which the resolvers are added in the resolvers array is important, as the first resolver who passes the check will be used. For example, if you need your resolver to take precedence over the builtin input resolvers, you might want to do the following instead:
configuration.inputFieldResolvers = [myInputFieldResolver, ...configuration.inputFieldResolvers];
#
Cutomize typesGraphQL explorer dynamically creates sensible queries for all types and displays the data in predefined panels. If you wish to change specific behavior for a type, you can add a new TypeResolver
to the Configuration.typeResolvers
field.
const myTypeResolver: TypeResolver = { check: (t) => g.isObjectType(t) && t.name === 'Spaceship', ...,};
configuration.typeResolvers.push(myTypeResolver);
check
required A predicate that determines for which field this resolver applies toSection
the component rendering the valuegetObjectFragment
by default, GraphQL Explorer fetches all the primitive (ie non-object) fields of an object without argument. if you wish to fetch some nested object, or change which fields are fetch, you can set this propertygetListFragment
by default, when GraphQL Explorer needs to fetch a list, it applies some basic heuristic to fetch 3-4 fields with relevant names (like "title", "id", "name"). You can use this method to specify which list fragments to returngetMutations
by default GraphQL Explorer tries to guess which are the list of mutations related to a field. You can explicitly set which mutations you want by setting this fieldgetDefaultArgs
you can specify which default arguments to set when fetching an object of this typegetFormArgs
you can filter out some arguments from appearing in the form if they are set through the default args or by theSection
component
To get a good sense on the flexibility that these hooks provide, you can check out the code for the built-in connectionResolver.
Sometimes, especially when customizing object types, you just want to change a single property, but you would still want to use all the properties from another resolver, for example the object resolver. to achieve that, you can do:
const myTypeResolver: TypeResolver = { ...objectResolver(configuration), check: (t) => g.isObjectType(t) && t.name === 'Spaceship', getListFragments: () => ['id', 'name', 'make'],};
configuration.typeResolvers.push(myTypeResolver);
#
Customizing FieldsSingle fields from the object panel can be customized by adding resolvers to the Configuration.fieldResolvers
field.
const myFieldResolver: FieldResolver = { check: (type, field) => field.name.endsWith('Url'), Component: ({ title, item }) => { return ( <> <b>{title}:</b> <a href={item}>{item}</a> </> ); },}
configuration.fieldResolvers.push(myFieldResolver);