用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
直接命令不会经过审查 Prompt;运行前请先检查来源。
npx skills add https://github.com/MikeTreml/MissionControl --skill graphql命令会保持在同一行。复制前请横向滚动并检查完整内容。
想先保存到本地?可下载 SkillsMP 当前能够提供的文件。
基于 SOC 职业分类
正在显示 SKILL.md
| name | graphql |
| description | GraphQL schema design, resolvers, directives, subscriptions, and best practices for API development. |
| allowed-tools | Read, Write, Edit, Bash, Glob, Grep |
Expert assistance for designing and implementing GraphQL APIs.
Invoke this skill when you need to:
| Parameter | Type | Required | Description |
|---|---|---|---|
| typeName | string | Yes | GraphQL type name |
| operations | array | No | queries, mutations, subscriptions |
| directives | array | No | Custom directives |
# schema.graphql
# Scalars
scalar DateTime
scalar JSON
# Enums
enum Role {
USER
ADMIN
}
enum SortOrder {
ASC
DESC
}
# Types
type User {
id: ID!
name: String!
email: String!
role: Role!
posts: [Post!]!
createdAt: DateTime!
updatedAt: DateTime!
}
type Post {
id: ID!
title: String!
content: String!
published: Boolean!
author: User!
comments: [Comment!]!
createdAt: DateTime!
}
type Comment {
id: ID!
content: String!
author: User!
post: Post!
createdAt: DateTime!
}
# Pagination
type PageInfo {
hasNextPage: Boolean!
hasPreviousPage: Boolean!
startCursor: String
endCursor: String
}
type UserEdge {
node: User!
cursor: String!
}
type UserConnection {
edges: [UserEdge!]!
pageInfo: PageInfo!
totalCount: Int!
}
# Inputs
input CreateUserInput {
name: String!
email: String!
password: String!
role: Role = USER
}
input UpdateUserInput {
name: String
email: String
role: Role
}
input UsersFilterInput {
search: String
role: Role
}
input PaginationInput {
first: Int
after: String
last: Int
before: String
}
# Queries
type Query {
me: User
user(id: ID!): User
users(
filter: UsersFilterInput
pagination: PaginationInput
orderBy: SortOrder
): UserConnection!
post(id: ID!): Post
posts(published: Boolean): [Post!]!
}
# Mutations
type Mutation {
# Auth
login(email: String!, password: String!): AuthPayload!
register(input: CreateUserInput!): AuthPayload!
# Users
updateUser(id: ID!, input: UpdateUserInput!): User!
deleteUser(id: ID!): Boolean!
# Posts
createPost(title: String!, content: String!): Post!
updatePost(id: ID!, title: String, content: String, published: Boolean): Post!
deletePost(id: ID!): Boolean!
}
# Subscriptions
type Subscription {
postCreated: Post!
postUpdated(id: ID!): Post!
commentAdded(postId: ID!): Comment!
}
# Auth
type AuthPayload {
token: String!
user: User!
}
# Directives
directive @auth(requires: Role = USER) on FIELD_DEFINITION
directive @deprecated(reason: String) on FIELD_DEFINITION
// resolvers/index.ts
import { Resolvers } from '../generated/graphql';
import { Context } from '../context';
import { userResolvers } from './user.resolvers';
import { postResolvers } from './post.resolvers';
import { authResolvers } from './auth.resolvers';
export const resolvers: Resolvers<Context> = {
Query: {
...userResolvers.Query,
...postResolvers.Query,
},
Mutation: {
...authResolvers.Mutation,
...userResolvers.Mutation,
...postResolvers.Mutation,
},
Subscription: {
...postResolvers.Subscription,
},
User: userResolvers.User,
Post: postResolvers.Post,
};
// resolvers/user.resolvers.ts
import { GraphQLError } from 'graphql';
import { Context } from '../context';
export const userResolvers = {
Query: {
me: (: , : , { user, prisma }: ) => {
(!user) ();
prisma..({ : { : user. } });
},
: (: , { id }: { : }, { prisma }: ) => {
prisma..({ : { id } });
},
: (
: ,
{ filter, pagination, orderBy }: ,
{ prisma }:
) => {
{ first = , after } = pagination || {};
where = filter?.
? { : { : filter., : } }
: ;
users = prisma..({
where,
: first + ,
: after ? { : after } : ,
: after ? : ,
: { : orderBy || },
});
hasNextPage = users. > first;
edges = users.(, first).( ({
: user,
: user.,
}));
{
edges,
: {
hasNextPage,
: !!after,
: edges[]?.,
: edges[edges. - ]?.,
},
: prisma..({ where }),
};
},
},
: {
: (
: ,
{ id, input }: { : ; : },
{ user, prisma }:
) => {
(!user) ();
(user. !== id && user. !== ) {
();
}
prisma..({
: { id },
: input,
});
},
},
: {
: (: , : , { prisma }: ) => {
prisma..({ : { : parent. } });
},
},
};
// loaders/index.ts
import DataLoader from 'dataloader';
import { PrismaClient, User, Post } from '@prisma/client';
export function createLoaders(prisma: PrismaClient) {
return {
userLoader: new DataLoader<string, User | null>(async (ids) => {
const users = await prisma.user.findMany({
where: { id: { in: ids as string[] } },
});
const userMap = new Map(users.map((u) => [u.id, u]));
return ids.map((id) => userMap.get(id) || null);
}),
postsByAuthorLoader: new DataLoader<string, Post[]>(async (authorIds) => {
posts = prisma..({
: { : { : authorIds [] } },
});
postsByAuthor = <, []>();
posts.( {
authorPosts = postsByAuthor.(post.) || [];
authorPosts.(post);
postsByAuthor.(post., authorPosts);
});
authorIds.( postsByAuthor.(id) || []);
}),
};
}
: {
: loaders..(parent.),
}