Skip to content

Latest commit

 

History

History
124 lines (105 loc) · 3.04 KB

constructing-types.mdx

File metadata and controls

124 lines (105 loc) · 3.04 KB
title
Constructing Types

import { Tabs } from 'nextra/components';

For many apps, you can define a fixed schema when the application starts, and define it using GraphQL schema language. In some cases, it's useful to construct a schema programmatically. You can do this using the GraphQLSchema constructor.

When you are using the GraphQLSchema constructor to create a schema, instead of defining Query and Mutation types solely using schema language, you create them as separate object types.

For example, let's say we are building a simple API that lets you fetch user data for a few hardcoded users based on an id. Using buildSchema we could write a server with:

<Tabs items={['SDL', 'Code']}> <Tabs.Tab>

const express = require('express');
const { createHandler } = require('graphql-http/lib/use/express');
const { buildSchema } = require('graphql');

const schema = buildSchema(`
type User {
  id: String
  name: String
}

type Query {
  user(id: String): User
}
`);

// Maps id to User object
const fakeDatabase = {
  a: {
    id: 'a',
    name: 'alice',
  },
  b: {
    id: 'b',
    name: 'bob',
  },
};

const root = {
  user({ id }) {
    return fakeDatabase[id];
  },
};

const app = express();
app.all(
  '/graphql',
  createHandler({
    schema: schema,
    rootValue: root,
  }),
);
app.listen(4000);
console.log('Running a GraphQL API server at localhost:4000/graphql');

</Tabs.Tab> <Tabs.Tab>

const express = require('express');
const { createHandler } = require('graphql-http/lib/use/express');
const graphql = require('graphql');

// Maps id to User object
const fakeDatabase = {
  a: {
    id: 'a',
    name: 'alice',
  },
  b: {
    id: 'b',
    name: 'bob',
  },
};

// Define the User type
const userType = new graphql.GraphQLObjectType({
  name: 'User',
  fields: {
    id: { type: graphql.GraphQLString },
    name: { type: graphql.GraphQLString },
  },
});

// Define the Query type with inline resolver
const queryType = new graphql.GraphQLObjectType({
  name: 'Query',
  fields: {
    user: {
      type: userType,
      // `args` describes the arguments that the `user` query accepts
      args: {
        id: { type: graphql.GraphQLString },
      },
      resolve: (_, { id }) => {
        return fakeDatabase[id];
      },
    },
  },
});

const schema = new graphql.GraphQLSchema({ query: queryType });

const app = express();
app.all(
  '/graphql',
  createHandler({
    schema: schema,
  }),
);
app.listen(4000);
console.log('Running a GraphQL API server at localhost:4000/graphql');

</Tabs.Tab>

When we use the GraphQLSchema constructor method of creating the API, the root level resolvers are implemented on the Query and Mutation types rather than on a root object.

This can be particularly useful if you want to create a GraphQL schema automatically from something else, like a database schema. You might have a common format for something like creating and updating database records. This is also useful for implementing features like union types which don't map cleanly to ES6 classes and schema language.