graphql
Design GraphQL schemas, resolvers, and federation. Use for GraphQL API design or performance issues.
Works with
---
name: graphql
description: Design GraphQL schemas, resolvers, and federation. Use for GraphQL API design or performance issues.
license: MIT
---
# GraphQL Development
Design efficient GraphQL APIs.
## When to Use
- Creating GraphQL schemas
- Resolver implementation
- N+1 query problems
- Federation/stitching
- Performance optimization
## Schema Design
```graphql
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)
```javascript
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, paginationMore API Design skills
lark-event
larksuite/cli
Lark/Feishu real-time event listening / subscribing / consuming: stream events as NDJSON via `lark-cli event consume <EventKey>` (covers IM messages/reactions/chat changes, Approval status changes, Task updates, VC meeting started/joined/ended, Minutes generated, Whiteboard updated, etc.). Use for Lark bots, real-time message processing, long-running subscribers, streaming webhook/push handlers. Supports `--max-events` / `--timeout` bounded runs and a stderr ready-marker contract — designed for AI agents running as subprocesses.
lark-contact
larksuite/cli
飞书 / Lark 通讯录:按姓名 / 邮箱解析成 open_id,或按 open_id 反查姓名 / 部门 / 邮箱 / 联系方式 / 个人状态 / 签名,以及按关键词搜索当前用户可见的机器人 / 智能体(agent)。当用户提到一个名字要下一步发消息 / 排日程,或拿到 open_id 想查具体信息时使用。不负责部门树遍历、按部门列员工、组织架构图,这类需求走原生 OpenAPI。
lark-openapi-explorer
larksuite/cli
飞书/Lark 原生 OpenAPI 探索:从官方文档库中挖掘未经 CLI 封装的原生 OpenAPI 接口。当用户的需求无法被现有 lark-* skill 或 lark-cli 已注册命令满足,需要查找并调用原生飞书 OpenAPI 时使用。

