5. Sharing types and fields: enums
10m

A single Terrain enum

Let's jump right into the problem with a quick review of our schema's enum types. We talked about the different available terrains in FlyBy: for locations, any one of the five following types is valid!

enum LocationTerrain {
TERRESTRIAL
AERIAL
AQUATIC
GALACTIC
MAGMATIC
}

In contrast, our activities can take place on any of these terrains except one. For business reasons, we can't yet include MAGMATIC activities.

enum ActivityTerrain {
TERRESTRIAL
AERIAL
AQUATIC
GALACTIC
}

The result is two separate enum types, meaning that Location and Activity both have to define their own terrain fields. But because this field name is something our two types have in common, it feels like it would be better suited as part of our Attraction interface!

Because we've upgraded our gateway to use Federation 2, moving terrain into the Attraction interface is now a possibility. We can condense our two enum definitions into one type, Terrain, while maintaining the greater restrictiveness of the activities subgraph. This will also allow us to condense the Activity.terrain and Location.terrain fields into a singular terrain field that will instead live in our Attraction interface.

Diagram displaying how the LocationTerrain and ActivityTerrain types can now be collapsed into one Terrain definition, with all possible options, that will live in the supergraph schema

Let's get started!

In subgraph-activities/activities.graphql:

Updating our terrain fields

subgraph-activities/activities.graphql
enum Terrain {
TERRESTRIAL
AERIAL
AQUATIC
GALACTIC
}
interface Attraction {
id: ID!
"The name of the attraction"
name: String!
"A short description about the attraction"
description: String!
"The attraction's main photo as a URL"
photo: String!
"The minimum age in years for participation on this attraction"
minimumAge: Int!
"The terrain for an attraction"
terrain: Terrain!
}
type Activity implements Attraction @key(fields: "id") {
id: ID!
"The name of the attraction"
name: String!
"A short description about the attraction"
description: String!
"The attraction's main photo as a URL"
photo: String!
"The minimum age in years for participation on this attraction"
minimumAge: Int!
"The terrain for an attraction"
terrain: Terrain!
"The activity's location"
location: Location
}

In subgraph-locations/locations.graphql:

Updating our terrain fields

subgraph-locations/locations.graphql
enum Terrain {
TERRESTRIAL
AERIAL
AQUATIC
GALACTIC
MAGMATIC
}
interface Attraction {
id: ID!
"The name of the attraction"
name: String!
"A short description about the attraction"
description: String!
"The attraction's main photo as a URL"
photo: String!
"The minimum age in years for participation on this attraction"
minimumAge: Int
"The terrain for an attraction"
terrain: Terrain!
}
type Location implements Attraction @key(fields: "id") {
id: ID!
"The name of the location"
name: String!
"A short description about the location"
description: String!
"The location's main photo as a URL"
photo: String!
"The minimum age in years for participation on this attraction"
minimumAge: Int
"The terrain for an attraction"
terrain: Terrain!
}

Let's publish those changes.

Publishing subgraph updates

We'll let you take the lead on checking out those changes! Return to Explorer and run the below query.

query GetLocationAndActivityTerrains {
locations {
name
terrain
}
activities {
name
terrain
}
}

Then, try modifying one of the activity objects inside subgraph-activities/datasources/activities_data.json to return MAGMATIC as a terrain instead.

Task!

Now run the above query again.

You should see that MAGMATIC throws an error when we attempt to return it as the value of terrain for an activity. Our schema is complying with our business rules for both of these types.

With just a few updates, we've managed to colocate the terrain field for both Location and Activity into one logical place: the shared Attraction interface! And in the process, we maintained the restriction around activities and the MAGMATIC terrain type.

Let's make sure we've reverted any changes made to our activities data before moving on.

Task!

Key takeaways

  • Federation 2 allows enum types with the same name to include values in one subgraph definition that are omitted in another.
  • The resulting type contains all possible values, but maintains the rules around which values are valid for each subgraph.
Previous
Next