Build a dynamic connector
For use with Netlify Connect only.
The define the data model and specify how to sync data documents outline how to develop connectors that sync data from a source, cache the data in the data layer’s database in Connect, and then serve the data from the cache while it’s available — you can think of these as static connectors.
But, there are some cases where you may need to develop a connector that allows Netlify to access data directly from the source every time. For example, you may need a dynamic connector to support the following scenarios:
- The data source is updated frequently and you need results in close to real time, such as financial data
- You need to access data from a pre-existing API (GraphQL/OpenAPI/REST)
- You need to use a database as a source
To build a dynamic connector, use the proxySchema
method.
You can use connector.proxySchema(fn)
in place of connector.model(fn)
and connector.sync(fn)
to have a dynamic-only connector, or you can include all of these methods and build a connector that supports a data source that is both static and dynamic.
Specify a GraphQL schema with proxySchema
Use the connector.proxySchema()
method to define and build a GraphQL schema using @graphql-tools
modules.
When Netlify generates the GraphQL schema for your data source, the schema that proxySchema
returns will be combined with the schema generated from the connector’s model
method, if one exists. The combining process is also known as schema stitching.
There are two steps:
- Define type definitions using GraphQL SDL
- Define the resolvers
Here is a snippet of an example connector that uses proxySchema
to generate a GraphQL schema:
import { makeExecutableSchema } from "@graphql-tools/schema";import { stitchSchemas } from "@graphql-tools/stitch";import { buildHTTPExecutor } from "@graphql-tools/executor-http";import { schemaFromExecutor, RenameTypes } from "@graphql-tools/wrap";
// Connecting an existing GraphQL APIasync function getRemoteGraphQLSchema({ typePrefix, uri }) { const remoteExecutor = buildHTTPExecutor({ endpoint: uri, });
const schema = { schema: await schemaFromExecutor(remoteExecutor), executor: remoteExecutor, transforms: [new RenameTypes((name) => `${typePrefix}${name}`)], };
return schema;}
// Leverage an existing REST APIasync function getSchemaFromCustomRestAPI({ typePrefix, apiClient,}: { typePrefix: string; apiClient: BreweryApiClient;}) { const typeDefs = ` enum BreweryType { micro large brewpub closed proprietor contract }
type Brewery { id: ID name: String brewery_type: BreweryType address_1: String address_2: String address_3: String city: String state_province: String postal_code: String country: String longitude: String latitude: String phone: String website_url: String state: String street: String }
type Query { breweryFromOrigin(id: ID): Brewery randomBreweryFromOrigin(size: Int): [Brewery] breweriesFromOrigin(by_type: BreweryType, by_ids: [String], by_name: String, by_postal: String, by_city: String): [Brewery] } `;
const resolvers = { Query: { breweryFromOrigin: async (_, { id }) => { return apiClient.breweryById(id); }, randomBreweryFromOrigin: async (_, { size }) => { return apiClient.randomBrewery(size); }, breweriesFromOrigin: async (_, { by_type, by_ids, by_name, by_postal, by_city }) => { return apiClient.getBreweries({ by_type, by_ids, by_name, by_postal, by_city, }); }, }, };
return { transforms: [new RenameTypes((name) => `${typePrefix}Dynamic${name}`)], schema: makeExecutableSchema({ typeDefs, resolvers, }), };}
connector.proxySchema(async ({ typePrefix, state }) => { const swapiSchema = await getRemoteGraphQLSchema({ typePrefix, uri: `https://swapi-graphql.netlify.app/.netlify/functions/index`, });
const brewerySchema = await getSchemaFromCustomRestAPI({ typePrefix, apiClient: state.client, });
return stitchSchemas({ subschemas: [swapiSchema, brewerySchema], });});
This connector uses proxySchema
to combine a schema from an existing GraphQL API and a schema from a custom REST API. The stitchSchemas
function is used to combine the schemas.