スキル一覧に戻る
Dexploarer

graphql-schema-generator

by Dexploarer

4🍴 2📅 2026年1月15日
GitHubで見るManusで実行

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

スコア

総合スコア

50/100

リポジトリの品質指標に基づく評価

SKILL.md

SKILL.mdファイルが含まれている

+20
LICENSE

ライセンスが設定されている

0/10
説明文

100文字以上の説明がある

0/10
人気

GitHub Stars 100以上

0/15
最近の活動

3ヶ月以内に更新がある

0/10
フォーク

10回以上フォークされている

0/5
Issue管理

オープンIssueが50未満

+5
言語

プログラミング言語が設定されている

+5
タグ

1つ以上のタグが設定されている

0/5

レビュー

💬

レビュー機能は近日公開予定です