Context with Response Cache Plugin

28 Mar 2022

import { createServer, GraphQLYogaError } from "@graphql-yoga/node";
import { useResponseCache } from "@envelop/response-cache";

type User = {
  id: string;
  name: string;
  isAdmin: boolean;
};

type Post = {
  id: string;
  title: string;
};

type Message = {
  userId: string;
  body: string;
};

const users: User[] = [
  { id: "1", name: "Jamie", isAdmin: true },
  { id: "2", name: "Laurin", isAdmin: false },
  { id: "3", name: "Uri", isAdmin: false },
];

const posts: Post[] = [{ id: "wtf", title: "Learn GraphQL" }];

const messages: Message[] = [
  { userId: users[0].id, body: "Hello" },
  { userId: users[0].id, body: "How's it going?" },
  { userId: users[1].id, body: "Did you see the last GraphQL WTF episode?" },
  { userId: users[2].id, body: "Did you see GraphQL Yoga 2?" },
];

const server = createServer<{
  user?: User;
}>({
  schema: {
    typeDefs: /* GraphQL */ `
      type Query {
        users: [User]!
        posts: [Post]!
        messages: [Message!]!
      }

      type Mutation {
        updateUser(id: ID!, name: String!): User
      }

      type User {
        id: ID!
        name: String!
        isAdmin: Boolean!
      }

      type Post {
        id: ID!
        title: String!
      }

      type Message {
        user: User!
        body: String!
      }
    `,
    resolvers: {
      Query: {
        users: () => users,
        posts: () => posts,
        messages: (_, __, context) => {
          if (!context.user) {
            throw new GraphQLYogaError("User not authenticated");
          }

          return messages
            .filter((m) => m.userId === context.user?.id)
            .map(({ userId, ...message }) => ({
              user: users.find((user) => user.id === userId),
              ...message,
            }));
        },
      },
      Mutation: {
        updateUser: (_, { id, name }) => {
          const user = users.find((user) => user.id === id);

          if (!user) {
            throw new GraphQLYogaError("User not found");
          }

          user.name = name;
          return user;
        },
      },
    },
  },
  context: ({ request }) => {
    const userId = request.headers.get("authorization") ?? null;
    const user = users.find((user) => user.id === userId);

    return {
      user,
    };
  },
  plugins: [
    useResponseCache({
      session: (context) => String(context.user?.id),
      enabled: (context) => !context.user?.isAdmin,
      includeExtensionMetadata: true,
    }),
  ],
});

server.start();