The Grafbase OpenAPI connector can now be used to expose a Federation subgraph on Grafbase!
Apollo Federation is a technology for building GraphQL APIs that combines multiple GraphQL services into a single, unified schema. OpenAPI is a technology for specifying the shape of an HTTP API. Grafbase now lets you combine these two technologies - making it easy to add data from any HTTP API into a federated supergraph.
In the example below we have part of an OpenAPI specification that we want to expose as a subgraph:
openapi: 3.0.0
info:
title: Location Service
version: 1.2
paths:
/locations/{id}:
get:
summary: Returns a specific location
parameters:
- in: path
name: id
required: true
schema:
type: string
responses:
'200':
description: 'A Location'
content:
application/json:
schema:
$ref: '#/components/schemas/Location'
We can connect this API to Grafbase and expose it as a subgraph with the following schema:
import { config, connector, graph } from '@grafbase/sdk'
const g = graph.Standalone({ subgraph: true })
const locations = connector.OpenAPI('locations', {
schema: 'http://example.com/openapi.yaml',
})
g.datasource(locations, { namespace: false })
export default config({
graph: g,
})
When this introspects the OpenAPI schema and generates a type for the User
that type will be annotated as a federation entity:
type Location @key(fields: "id") {
name: String!
id: String!
}
This Grafbase API can now be connected into a Federation supergraph.
But that's not all: Grafbase can also use Federation to return references to another subgraphs entities and augment those entities with additional fields.
For example the following schema & resolver pair could be used to define a reviews subgraph with references to the above subgraph:
import { config, connector, graph } from '@grafbase/sdk'
const g = graph.Standalone({ subgraph: true })
const reviews = connector.OpenAPI('reviews', {
schema: 'http://example.com/reviews-openapi.yaml'
transforms: schema => {
schema.queryNaming('OPERATION_ID')
}
})
g.datasource(reviews, { namespace: false })
g.type('Location', {
id: g.string()
}).key('id', { resolvable: false })
g.extend('Review', {
location: {
returns: g.ref('Location'),
resolver: 'review/location'
}
})
export default config({
graph: g
})
We need to write a simple review/location
resolver that takes the Review
from the parent resolver and converts that into a representation of a Location. The supergraph router can then use that to fetch the associated Location
from the location subgraph.
export default function resolver({ location_id }) {
return { id: location_id }
}
We're just getting started with our Federation subgraph support, so there's a lot still to do. For the OpenAPI support we're planning on improving it's entity detection and allowing you to override and augment the entities that we detect. We'll also be rolling out subgraph support to our other connectors.
We'd love to hear your feedback and ideas, so join us on Discord.