Claude Code Plugins

Community-maintained marketplace

Feedback

graphql-schema-generator

@Dexploarer/claudius-skills
1
0

Generates GraphQL schemas with type definitions, resolvers, queries, mutations, and subscriptions. Use when building GraphQL APIs.

Install Skill

1Download skill
2Enable skills in Claude

Open claude.ai/settings/capabilities and find the "Skills" section

3Upload to Claude

Click "Upload skill" and select the downloaded ZIP file

Note: Please verify skill by going through its instructions before using it.

SKILL.md

name graphql-schema-generator
description Generates GraphQL schemas with type definitions, resolvers, queries, mutations, and subscriptions. Use when building GraphQL APIs.

GraphQL Schema Generator Skill

Expert at creating GraphQL schemas with proper types, resolvers, and best practices.

When to Activate

  • "create GraphQL schema for [entity]"
  • "generate GraphQL API"
  • "build GraphQL types and resolvers"

Complete GraphQL Structure

// schema/user.schema.ts
import { gql } from 'apollo-server-express';

export const userTypeDefs = gql`
  type User {
    id: ID!
    email: String!
    name: String!
    role: UserRole!
    posts: [Post!]!
    createdAt: DateTime!
    updatedAt: DateTime!
  }

  enum UserRole {
    USER
    ADMIN
    MODERATOR
  }

  input CreateUserInput {
    email: String!
    name: String!
    password: String!
    role: UserRole = USER
  }

  input UpdateUserInput {
    email: String
    name: String
    password: String
    role: UserRole
  }

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

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

  type Query {
    user(id: ID!): User
    users(
      first: Int = 10
      after: String
      search: String
    ): UserConnection!
    me: User
  }

  type Mutation {
    createUser(input: CreateUserInput!): User!
    updateUser(id: ID!, input: UpdateUserInput!): User!
    deleteUser(id: ID!): Boolean!
  }

  type Subscription {
    userCreated: User!
    userUpdated(id: ID!): User!
  }
`;

// resolvers/user.resolvers.ts
import { UserInputError, AuthenticationError } from 'apollo-server-express';
import { UserService } from '../services/user.service';
import { pubsub } from '../pubsub';

const USER_CREATED = 'USER_CREATED';
const USER_UPDATED = 'USER_UPDATED';

export const userResolvers = {
  Query: {
    user: async (_parent, { id }, { services, user }) => {
      if (!user) {
        throw new AuthenticationError('Not authenticated');
      }

      return await services.user.findById(id);
    },

    users: async (_parent, { first, after, search }, { services, user }) => {
      if (!user) {
        throw new AuthenticationError('Not authenticated');
      }

      const result = await services.user.findAll({
        first,
        after,
        search,
      });

      return {
        edges: result.users.map(user => ({
          node: user,
          cursor: Buffer.from(user.id.toString()).toString('base64'),
        })),
        pageInfo: {
          hasNextPage: result.hasNextPage,
          endCursor: result.endCursor,
        },
        totalCount: result.totalCount,
      };
    },

    me: async (_parent, _args, { user }) => {
      if (!user) {
        throw new AuthenticationError('Not authenticated');
      }

      return user;
    },
  },

  Mutation: {
    createUser: async (_parent, { input }, { services }) => {
      const user = await services.user.create(input);

      // Publish subscription event
      pubsub.publish(USER_CREATED, { userCreated: user });

      return user;
    },

    updateUser: async (_parent, { id, input }, { services, user }) => {
      if (!user) {
        throw new AuthenticationError('Not authenticated');
      }

      if (user.id !== id && user.role !== 'ADMIN') {
        throw new AuthenticationError('Not authorized');
      }

      const updatedUser = await services.user.update(id, input);

      if (!updatedUser) {
        throw new UserInputError('User not found');
      }

      // Publish subscription event
      pubsub.publish(USER_UPDATED, {
        userUpdated: updatedUser,
        id,
      });

      return updatedUser;
    },

    deleteUser: async (_parent, { id }, { services, user }) => {
      if (!user || user.role !== 'ADMIN') {
        throw new AuthenticationError('Admin access required');
      }

      const success = await services.user.delete(id);

      if (!success) {
        throw new UserInputError('User not found');
      }

      return true;
    },
  },

  Subscription: {
    userCreated: {
      subscribe: () => pubsub.asyncIterator([USER_CREATED]),
    },

    userUpdated: {
      subscribe: withFilter(
        () => pubsub.asyncIterator([USER_UPDATED]),
        (payload, variables) => {
          return payload.id === variables.id;
        }
      ),
    },
  },

  User: {
    // Field resolver for nested data
    posts: async (parent, _args, { services }) => {
      return await services.post.findByAuthorId(parent.id);
    },
  },
};

DataLoader Pattern

// dataloaders/user.dataloader.ts
import DataLoader from 'dataloader';
import { UserService } from '../services/user.service';

export function createUserLoader(userService: UserService) {
  return new DataLoader(async (ids: readonly string[]) => {
    const users = await userService.findByIds([...ids]);

    const userMap = new Map(users.map(user => [user.id, user]));

    return ids.map(id => userMap.get(id) || null);
  });
}

// Use in context
export const createContext = ({ req }) => {
  const userService = new UserService();

  return {
    user: req.user,
    services: {
      user: userService,
    },
    loaders: {
      user: createUserLoader(userService),
    },
  };
};

Best Practices

  • Use clear, descriptive type names
  • Implement pagination (Connection pattern)
  • Add input validation
  • Use enums for fixed values
  • Implement authentication/authorization
  • Use DataLoaders to prevent N+1 queries
  • Add proper error handling
  • Document schema with descriptions
  • Version your API
  • Use subscriptions for real-time data
  • Implement field-level resolvers
  • Cache responses when appropriate

Output Checklist

  • ✅ Type definitions created
  • ✅ Resolvers implemented
  • ✅ Queries/Mutations/Subscriptions
  • ✅ DataLoaders setup
  • ✅ Authentication added
  • ✅ Error handling
  • 📝 Usage examples