Pothos GraphQL
Searching...

Context object

The GraphQL context object can be used to give every resolver in the schema access to some shared state for the current request. One common use case is to store the current User on the context object.

One important thing to note about Pothos is that every request is assumed to have a new unique context object, so be sure to set up your context objects in a way that they are unique to each request.

First let's define a User class that holds information about a user, and create a SchemaBuilder with a Context type that has a currentUser property.

class User {
  id: string;
  firstName: string;
  username: string;

  constructor(id: string, firstName: string, username: string) {
    this.id = id;
    this.firstName = firstName;
    this.username = username;
  }
}

const builder = new SchemaBuilder<{
  Context: {
    currentUser: User;
  };
}>({});

Next, we will want to add something in our schema that uses the current user:

builder.queryType({
  fields: (t) => ({
    currentUser: t.field({
      type: User,
      resolve: (root, args, context) => context.currentUser,
    }),
  }),
});

builder.objectType(User, {
  fields: (t) => ({
    id: t.exposeID('id', {}),
    firstName: t.exposeString('firstName', {}),
    username: t.exposeString('username', {}),
  }),
});

Finally, we need to actually create our context when a request is created.

const yoga = createYoga({
  schema,
  context: async ({ req }) => ({
    // This part is up to you!
    currentUser: await getUserFromAuthHeader(req.headers.authorization),
  }),
});
const server = createServer(yoga);

server.listen(3000);

Initialize context cache

Several Pothos plugins use the context object to cache data for the current request. Some examples include dataloaders and auth scopes. This caching mechanism works based on the assumption that the same context object is passed to every resolver in a request, and each request has a unique context object. This works for most applications without any additional configuration.

In some rare edge cases, you may have some additional logic added to your application that clones or mutates the context object throughout the execution of a request. To ensure that all plugins work correctly even if the context object is cloned, wrapped, or modified in a way that does not preserve its identity, you can manually initialize the context cache and attach it to the context object:

import { initContextCache } from '@pothos/core';

const server = createYoga({
  schema: builder.toSchema(),
  context: async ({ req }) => ({
    // Adding this will prevent any issues if you server implementation
    // copies or extends the context object before passing it to your resolvers
    ...initContextCache(),

    currentUser: await getUserFromAuthHeader(req.headers.authorization),
  }),
});

const server = createServer(yoga);

server.listen(3000);