# GraphQL schema

GraphQL schema is generated by passing all the operations (query/mutation/subscription) functions to `apischema.graphql.graphql_schema`. 

Functions parameters and return types are then processed by *apischema* to generate the `Query`/`Mutation`/`Subscription` types with their resolvers/subscribers, which are then passed to `graphql.GraphQLSchema`.

In fact, `graphql_schema` is just a wrapper around `graphql.GraphQLSchema` (same parameters plus a few extras); it just uses *apischema* abstraction to build `GraphQL` object types directly from your code. 

## Operations metadata

GraphQL operations can be passed to `graphql_schema` either using simple functions or wrapping it into `apischema.graphql.Query`/`apischema.graphql.Mutation`/`apischema.graphql.Subscription`. These wrappers have the same parameters as `apischema.graphql.resolver`: `alias`, `conversions`, `error_handler`, `order` and `schema` (`Subscription` has an [additional parameter](#subscriptions)).

```python
{!operation.py!}
```

## *camelCase*

GraphQL use *camelCase* as a convention for resolvers; *apischema* follows this convention by automatically convert all resolver names (and their parameters) to *camelCase*. `graphql_schema` has an `aliaser` parameter if you want to use another case.

## Type names

Schema types are named the same way they are in generated JSON schema: type name is used by default, and it can be overridden using [`apischema.type_name`](../json_schema.md#customize-ref)

```python
{!graphql_type_name.py!}
```

!!! note
    Type names can be distinguished between JSON schema and GraphQL schema using `type_name` named parameter. Indeed, `type_name("foo")` is equivalent to `type_name(json_schema="foo", graphql="foo")`.

However, in GraphQL schema, unions must be named, so `typing.Union` used should be annotated with `apischema.type_name`. `graphql_schema` also provides a `union_ref` parameter which can be passed as a function to generate a type name from the union argument. Default `union_ref` is `"Or".join` meaning `typing.Union[Foo, Bar]` will result in `union FooOrBar = Foo | Bar`

```python
{!union_type_name.py!}
```

## `Enum` metadata

Contrary to dataclasses, `Enum` doesn't provide a way to set metadata for its members, especially description, but also deprecation reason. They can however be passed using `enum_schemas` parameter of `graphql_schema`. 

```python
{!enum_schemas.py!}
```

## Additional types

*apischema* will only include in the schema the types annotating resolvers. However, it is possible to add other types by using the `types` parameter of `graphql_schema`. This is especially useful to add interface implementations where only interface is used in resolver types. 

```python
{!additional_types.py!}
```

## Subscriptions

Subscriptions are particular operations which must return an `AsyncIterable`; this event generator can come with a dedicated resolver to post-process the event.

### Event generator only

```python
{!subscription.py!}
```

!!! note
    Because there is no post-processing of generated event in a dedicated resolver, `error_handler` cannot be called, but it will still modify the type of the event. 

### Event generator + resolver

A resolver can be added by using the `resolver` parameter of `Subscription`.  In this case, *apischema* will map subscription name, parameters and return type on the resolver instead of the event generator. It allows using the same event generator with several resolvers to create different subscriptions.

The first resolver argument will be the event yielded by the event generator.

```python
{!subscription_resolve.py!}
```

