SuperAPI AI Directory

graphql

Coding & development

View repository

Updated 10-15 22:14

About this skill

GraphQL Development

Design efficient GraphQL APIs.

When to Use

  • Creating GraphQL schemas
  • Resolver implementation
  • N+1 query problems
  • Federation/stitching
  • Performance optimization

Schema Design

type Query {
  user(id: ID!): User
  users(filter: UserFilter, limit: Int = 10): UserConnection!
}

type Mutation { createUser(input: CreateUserInput!): CreateUserPayload! updateUser(id: ID!, input: UpdateUserInput!): UpdateUserPayload! }

type User { id: ID! email: String! name: String! posts(first: Int, after: String): PostConnection! createdAt: DateTime! }

input CreateUserInput { email: String! name: String! }

type CreateUserPayload { user: User errors: [Error!] }

type UserConnection { edges: [UserEdge!]! pageInfo: PageInfo! totalCount: Int! }

type UserEdge { node: User! cursor: String! }

type PageInfo { hasNextPage: Boolean! endCursor: String }


## Resolvers

```javascript
const resolvers = {
  Query: {
    user: (_, { id }, { dataSources }) => dataSources.users.getById(id),

    users: async (_, { filter, limit }, { dataSources }) => {
      const users = await dataSources.users.find(filter, limit);
      return connectionFromArray(users);
    },
  },

  User: {
    // Field resolver with DataLoader for N+1
    posts: (user, args, { loaders }) => loaders.postsByUser.load(user.id),
  },

  Mutation: {
    createUser: async (_, { input }, { dataSources }) => {
      try {
        const user = await dataSources.users.create(input);
        return { user, errors: null };
      } catch (e) {
        return { user: null, errors: [{ message: e.message }] };
      }
    },
  },
};

DataLoader (N+1 Solution)

const DataLoader = require("dataloader");

const createLoaders = (dataSources) => ({
  userById: new DataLoader(async (ids) => {
    const users = await dataSources.users.getByIds(ids);
    const userMap = new Map(users.map((u) => [u.id, u]));
    return ids.map((id) => userMap.get(id) || null);
  }),

  postsByUser: new DataLoader(async (userIds) => {
    const posts = await dataSources.posts.findByUserIds(userIds);
    const grouped = groupBy(posts, "userId");
    return userIds.map((id) => grouped[id] || []);
  }),
});

Performance Tips

  • Use DataLoader for batching
  • Implement query complexity limits
  • Add depth limiting
  • Cache with Redis/CDN
  • Use persisted queries

Best Practices

  • Nullable by default, explicit ! for required
  • Use input types for mutations
  • Return payload types with errors
  • Implement cursor pagination
  • Version via schema evolution

Examples

Input: "Fix N+1 queries" Action: Implement DataLoader, batch database queries

Input: "Design user management API" Action: Create schema with types, queries, mutations, pagination