Resolvers & Execution Model

◕ GraphQLLesson 6Intermediate

A resolver is a function responsible for returning the value of a field in your schema. GraphQL executes resolvers in a tree-like fashion — starting from root query resolvers, then recursively resolving nested fields.

1 Resolver Signature
JavaScript — Resolver Function Arguments
// Every resolver receives 4 arguments:
// resolver(parent, args, context, info)

const resolvers = {
  Query: {
    // parent = root value (null for top-level queries)
    // args   = query arguments { id: "42" }
    // context= shared data (auth user, DB connections, dataloaders)
    // info   = query AST, field selection info
    user: async (parent, args, context, info) => {
      if (!context.currentUser) throw new Error("Not authenticated");
      return context.db.User.findById(args.id);
    },

    users: async (_, { role, limit = 20, offset = 0 }, { db }) => {
      const filter = role ? { role } : {};
      return db.User.find(filter).skip(offset).limit(limit);
    }
  },

  // Field-level resolvers on User type
  User: {
    // parent = the User object returned from the Query resolver
    posts: async (user, _, { db }) => {
      return db.Post.find({ authorId: user.id });
    },
    // Computed field — not stored in DB
    fullName: (user) => user.firstName + " " + user.lastName
  },

  Mutation: {
    createUser: async (_, { input }, { db, bcrypt }) => {
      const hash = await bcrypt.hash(input.password, 12);
      return db.User.create({ ...input, passwordHash: hash });
    }
  }
};
2 The Context Object
JavaScript — Apollo Server Context
const server = new ApolloServer({ typeDefs, resolvers });

await startStandaloneServer(server, {
  context: async ({ req }) => {
    // Build context for EVERY request
    const token = req.headers.authorization?.split(" ")[1];
    let currentUser = null;
    if (token) {
      try {
        const decoded = jwt.verify(token, process.env.JWT_SECRET);
        currentUser = await User.findById(decoded.userId);
      } catch {}
    }
    return {
      currentUser,           // attached user
      db: { User, Post },   // database models
      dataloaders            // batch loaders (Lesson 11)
    };
  }
});
3 Code Challenge
Challenge: Write a full resolver map for a Post type that includes: author (fetched from DB by authorId), commentCount (computed by counting comments), and readingTime (computed as body word count divided by 200, in minutes).