소스 정보
- 저장소
- microwind/ai-skills
- 최근 소스 활동
- 2026년 3월 26일 14:58
- 감지된 SKILL.md 언어
- 중국어
- 스타
- 68
- 포크
- 17
설치 방법
기본적으로 소스를 먼저 확인하는 Prompt가 선택됩니다. 직접 명령으로 전환하거나 로컬 사본을 다운로드할 수도 있습니다.
소스 파일 검토
설치 여부를 결정하기 전에 SKILL.md와 SkillsMP에 표시된 보조 파일을 읽어 보세요.
메뉴
기본적으로 소스를 먼저 확인하는 Prompt가 선택됩니다. 직접 명령으로 전환하거나 로컬 사본을 다운로드할 수도 있습니다.
설치 여부를 결정하기 전에 SKILL.md와 SkillsMP에 표시된 보조 파일을 읽어 보세요.
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
직접 명령은 검토 Prompt를 거치지 않습니다. 실행하기 전에 소스를 확인하세요.
npx skills add https://github.com/microwind/ai-skills --skill graphql-api명령은 한 줄로 유지됩니다. 복사하기 전에 가로로 스크롤해 전체 내용을 확인하세요.
로컬 사본을 원하시나요? SkillsMP에서 현재 제공할 수 있는 파일을 다운로드하세요.
SOC 직업 분류 기준
SKILL.md 표시 중
| name | GraphQL API开发 |
| description | 当开发GraphQL API时,分析查询策略,优化API性能,解决数据获取问题。验证GraphQL架构,设计查询模式,和最佳实践。 |
| license | MIT |
GraphQL是一种现代化的API查询语言,提供了比REST更灵活的数据获取方式。不当的GraphQL设计会导致性能问题、安全漏洞和复杂性增加。需要建立完善的GraphQL开发规范。
核心原则: 好的GraphQL设计应该高效、安全、易于维护。坏的GraphQL设计会导致N+1查询问题、性能下降和安全风险。
始终:
触发短语:
问题:
查询列表时,每个项目都触发额外的数据库查询
后果:
- 数据库压力大
- 响应时间长
- 性能线性下降
- 服务器资源浪费
解决方案:
- 数据加载器(DataLoader)
- 批量查询优化
- 预加载关联数据
- 查询合并策略
问题:
客户端发送过于复杂的嵌套查询
后果:
- 服务器性能下降
- 内存占用过高
- 响应超时
- 拒绝服务攻击风险
解决方案:
- 查询深度限制
- 复杂度分析
- 查询超时设置
- 白名单字段限制
问题:
Schema设计过于复杂或不一致
后果:
- 开发困难
- 维护成本高
- 客户端困惑
- 版本管理困难
解决方案:
- 简化Schema设计
- 统一命名规范
- 模块化设计
- 版本控制策略
# 用户类型
type User {
id: ID!
username: String!
email: String!
profile: Profile
posts: [Post!]!
createdAt: DateTime!
}
# 用户资料类型
type Profile {
id: ID!
firstName: String!
lastName: String!
avatar: String
bio: String
}
# 文章类型
type Post {
id: ID!
title: String!
content: String!
author: User!
comments Comment
String
DateTime
user ID User
users Int, Int User
post ID Post
posts Int, Int Post
search String SearchResult
createUser CreateUserInput User
updateUser ID, UpdateUserInput User
createPost CreatePostInput Post
deletePost ID Boolean
Post
userUpdated ID User
CreateUserInput
String
String
String
ProfileInput
ProfileInput
String
String
String
String
SearchResult User Post Comment
UserRole
ADMIN
MODERATOR
USER
DateTime
Upload
# 可评论接口
interface Commentable {
id: ID!
comments: [Comment!]!
}
# 实现接口
type Post implements Commentable {
id: ID!
title: String!
content: String!
comments: [Comment!]!
}
type Video implements Commentable {
id: ID!
title: String!
url: String!
duration: Int!
comments: [Comment!]!
}
import graphene
from graphene_django import DjangoObjectType
from django.contrib.auth.models import User
from datetime import datetime
import promise
class ProfileType(graphene.ObjectType):
id = graphene.ID()
first_name = graphene.String()
last_name = graphene.String()
avatar = graphene.String()
bio = graphene.String()
class UserType(DjangoObjectType):
profile = graphene.Field(ProfileType)
posts = graphene.List('PostType')
class Meta:
model = User
fields = ('id', 'username', 'email', 'date_joined')
def resolve_profile(self, info):
if hasattr(self, 'profile'):
return self.profile
return None
def resolve_posts(self, info):
# 使用DataLoader解决N+1问题
return info.context.loaders.post_loader.load(self.id)
class PostType(graphene.ObjectType):
id = graphene.ID()
title = graphene.String()
content = graphene.String()
author = graphene.Field(UserType)
comments = graphene.()
tags = graphene.(graphene.String)
created_at = graphene.DateTime()
():
info.context.loaders.user_loader.load(.author_id)
():
info.context.loaders.comment_loader.load(.)
(graphene.ObjectType):
user = graphene.Field(UserType, =graphene.ID(required=))
users = graphene.(UserType, limit=graphene.Int(), offset=graphene.Int())
post = graphene.Field(PostType, =graphene.ID(required=))
posts = graphene.(PostType, limit=graphene.Int(), offset=graphene.Int())
():
info.context.loaders.user_loader.load(())
():
queryset = User.objects.()
offset:
queryset = queryset[offset:]
limit:
queryset = queryset[:limit]
queryset
():
info.context.loaders.post_loader.load(())
():
queryset = Post.objects.()
offset:
queryset = queryset[offset:]
limit:
queryset = queryset[:limit]
queryset
(graphene.Mutation):
user = graphene.Field(UserType)
success = graphene.Boolean()
errors = graphene.(graphene.String)
:
username = graphene.String(required=)
email = graphene.String(required=)
password = graphene.String(required=)
first_name = graphene.String()
last_name = graphene.String()
():
:
user = User.objects.create_user(
username=username,
email=email,
password=password
)
first_name last_name:
Profile.objects.create(
user=user,
first_name=first_name,
last_name=last_name
)
CreateUser(user=user, success=, errors=[])
Exception e:
CreateUser(user=, success=, errors=[(e)])
(graphene.ObjectType):
create_user = CreateUser.Field()
promise Promise
promise.dataloader DataLoader
():
():
users = User.objects.(id__in=keys)
user_dict = {user.: user user users}
Promise.resolve([user_dict.get(key) key keys])
():
():
posts = Post.objects.(author_id__in=keys)
posts_dict = {}
post posts:
posts_dict.setdefault(post.author_id, []).append(post)
Promise.resolve([posts_dict.get(key, []) key keys])
graphql.validation.rules QueryComplexityRule
graphql GraphQLSchema, validate
:
():
.max_complexity = max_complexity
():
complexity =
():
complexity
(node, ):
selection node.selection_set.selections:
complexity +=
calculate_complexity(selection)
:
graphql
ast = graphql.parse(query)
calculate_complexity(ast)
Exception:
complexity <= .max_complexity
django.views.decorators.csrf csrf_exempt
django.http JsonResponse
json
():
request.method == :
JsonResponse({: })
request.method == :
:
data = json.loads(request.body)
query = data.get()
variables = data.get(, {})
complexity_limiter = QueryComplexityLimiter(max_complexity=)
complexity_limiter.analyze_query(query, schema):
JsonResponse({
: [{: }]
}, status=)
loaders = {
: UserLoader(),
: PostLoader(),
: CommentLoader()
}
context = {: loaders}
result = schema.execute(query, variables=variables, context=context)
JsonResponse({
: result.data,
: [(error) error result.errors] result.errors
})
Exception e:
JsonResponse({
: [{: (e)}]
}, status=)
schema = graphene.Schema(query=Query, mutation=Mutation)
import { ApolloClient, InMemoryCache, gql, createHttpLink } from '@apollo/client';
import { setContext } from '@apollo/client/link/context';
// HTTP链接
const httpLink = createHttpLink({
uri: 'http://localhost:8000/graphql/',
});
// 认证链接
const authLink = setContext((_, { headers }) => {
const token = localStorage.getItem('authToken');
return {
headers: {
...headers,
authorization: token ? `Bearer ${token}` : '',
}
}
});
// Apollo客户端
const client = new ApolloClient({
link: authLink.concat(httpLink),
cache: new InMemoryCache(),
defaultOptions: {
watchQuery: {
errorPolicy: 'all',
},
query: {
errorPolicy: 'all',
},
},
});
// GraphQL查询
const GET_USER = gql`
query GetUser(: ID
user )
id
username
email
profile
firstName
lastName
avatar
posts
id
title
content
createdAt
`;
= gql`;
= gql`;
= () => {
{
response = client.({
: ,
: { id },
});
response..;
} (error) {
.(, error);
error;
}
};
= () => {
{
response = client.({
: ,
variables,
});
response..;
} (error) {
.(, error);
error;
}
};
= () => {
{
response = client.({
: ,
: { input },
});
response..;
} (error) {
.(, error);
error;
}
};
{ useQuery, useMutation } ;
= () => {
{ loading, error, data } = (, {
: { id },
: !id,
});
{
: data?.,
loading,
error,
};
};
= () => {
[createUserMutation, { loading, error }] = (, {
: {
cache.({
: {
: [...existing, createUser]
}
});
},
});
= () => {
result = ({
: { input },
});
result..;
};
{
createUser,
loading,
error,
};
};
= () => {
[page, setPage] = ();
[users, setUsers] = ([]);
{ loading, error, data, fetchMore } = (, {
: {
: pageSize,
: page * pageSize,
},
});
( {
(data?.) {
(page === ) {
(data.);
} {
( [...prev, ...data.]);
}
}
}, [data, page]);
= () => {
(!loading && data?.?. === pageSize) {
( prev + );
}
};
{
users,
loading,
error,
loadMore,
: data?.?. === pageSize,
};
};