graphql-dev
Write GraphQL queries, mutations, and subscriptions — fragments, code generation, TypedDocumentNode, variables, error handling, and client setup. Use when writing GraphQL code for Saleor.
Works with
---
name: graphql-dev
description: Write GraphQL queries, mutations, and subscriptions — fragments, code generation, TypedDocumentNode, variables, error handling, and client setup. Use when writing GraphQL code for Saleor.
license: MIT
---
# GraphQL Development for Saleor
## Before writing code
**Fetch live docs**:
1. Web-search `site:docs.saleor.io api-reference` for the current Saleor GraphQL schema and API reference
2. Web-search `site:the-guild.dev graphql-codegen` for GraphQL Code Generator configuration and plugins
3. Web-search `site:graphql.org learn` for GraphQL specification fundamentals
4. Web-search `saleor GraphQL TypedDocumentNode urql` for typed client patterns
5. Fetch `https://docs.saleor.io/docs/developer/api-conventions` for Saleor-specific GraphQL conventions
## GraphQL Fundamentals
| Operation | Purpose | Saleor Example |
|-----------|---------|----------------|
| **Query** | Read data | Fetch products, orders, categories |
| **Mutation** | Write data | Create checkout, update product, complete order |
| **Subscription** | Real-time events | Webhook subscription payloads |
### Saleor API Characteristics
- GraphQL is the **only** API — there are no REST endpoints
- All operations are accessed at a single `/graphql/` endpoint
- Mutations return both the result object and an `errors` array
- Queries support filtering, sorting, and cursor-based pagination
- Channel context is set via the `channel` argument or HTTP header
## Fragments for Reuse
| Fragment Use Case | Benefit |
|-------------------|---------|
| **Product fields** | Reuse across product list, detail, and search queries |
| **Address fields** | Share between checkout, order, and customer queries |
| **Money fields** | Consistent currency/amount selection |
| **Error fields** | Uniform error handling across mutations |
| **Image fields** | Consistent image URL and alt text selection |
- Name fragments as `{TypeName}Fragment` (e.g., `ProductFragment`, `AddressFragment`)
- Keep fragments focused on a single concern
- Co-locate fragments with the components that use them
## Variables and Input Types
| Concept | Description | Example |
|---------|-------------|---------|
| **Variable** | Dynamic value passed to operation | `$id: ID!`, `$channel: String!` |
| **Input type** | Structured input for mutations | `ProductCreateInput`, `CheckoutCreateInput` |
| **Required** | Non-null variable | `$id: ID!` (with `!`) |
| **Optional** | Nullable variable | `$filter: ProductFilterInput` |
| **Default** | Variable with default value | `$first: Int = 10` |
- Always use variables instead of string interpolation for dynamic values
- Pass channel as a variable for multi-channel operations
## GraphQL Code Generation
| Package | Purpose |
|---------|---------|
| `@graphql-codegen/cli` | Code generation CLI |
| `@graphql-codegen/typescript` | Generate TypeScript types from schema |
| `@graphql-codegen/typescript-operations` | Generate types for operations |
| `@graphql-codegen/typed-document-node` | Generate TypedDocumentNode objects |
### Configuration (codegen.ts)
| Setting | Value | Description |
|---------|-------|-------------|
| `schema` | Saleor GraphQL endpoint URL | Source of truth for types |
| `documents` | `"src/**/*.graphql"` or `"src/**/*.ts"` | Location of operations |
| `generates` | Output file paths | Where to write generated code |
| `plugins` | Array of codegen plugins | Which code to generate |
- Run `graphql-codegen` after schema changes or when adding new operations
- Commit generated files to version control for CI consistency
## TypedDocumentNode Pattern
| Aspect | Benefit |
|--------|---------|
| **Query result** | Fully typed response data |
| **Variables** | Type-checked at compile time |
| **Fragments** | Types flow through fragment composition |
| **IDE support** | Autocomplete for fields and variables |
| **Refactoring** | Rename detection across operations |
- Generated by `@graphql-codegen/typed-document-node`
- Works with urql, Apollo Client, and other GraphQL clients
- Catches schema mismatches at compile time, not runtime
## Error Handling
| Error Type | Location | Cause |
|-----------|----------|-------|
| **GraphQL errors** | `response.data.mutation.errors[]` | Validation, permission, business logic |
| **Network errors** | Caught by client | Connection failure, timeout, 5xx |
| **Schema errors** | Build-time (codegen) | Operation doesn't match schema |
### Saleor Mutation Error Structure
| Field | Type | Description |
|-------|------|-------------|
| `field` | `String` | Which input field caused the error |
| `message` | `String` | Human-readable error message |
| `code` | `Enum` | Machine-readable error code |
- Always check `data.mutation.errors` after every mutation
- Map error codes to user-friendly messages in the storefront
## Client Libraries
| Client | Package | SSR Support | Caching | Best For |
|--------|---------|-------------|---------|----------|
| **urql** | `@urql/core`, `@urql/next` | Yes (via `@urql/next`) | Document cache, Graphcache | Saleor recommended |
| **Apollo Client** | `@apollo/client` | Yes | Normalized cache | Complex caching needs |
| **graphql-request** | `graphql-request` | N/A (no cache) | None | Simple scripts, server-side |
| **gql** (Python) | `gql` | N/A | None | Python scripts and tests |
- Include `Authorization: Bearer <token>` header for authenticated operations
- Include `saleor-channel: <slug>` header for channel-scoped queries
- For SSR: ensure proper request deduplication and cache hydration
## Operation Naming Conventions
| Convention | Example | Benefit |
|-----------|---------|---------|
| **Prefix with verb** | `GetProducts`, `CreateCheckout` | Clear intent |
| **Suffix queries** | `ProductListQuery`, `OrderDetailQuery` | Distinguish from mutations |
| **Suffix mutations** | `CheckoutCreateMutation` | Distinguish from queries |
| **Unique names** | No duplicates across codebase | Required by codegen |
## Pagination Patterns
Saleor uses Relay-style cursor-based pagination:
| Parameter | Type | Description |
|-----------|------|-------------|
| `first` | `Int` | Number of items from the start |
| `after` | `String` | Cursor after which to fetch |
| `last` | `Int` | Number of items from the end |
| `before` | `String` | Cursor before which to fetch |
### Response Structure
| Field | Path | Description |
|-------|------|-------------|
| **edges** | `connection.edges[]` | Array of edge objects |
| **node** | `edge.node` | The actual entity |
| **cursor** | `edge.cursor` | Opaque cursor string |
| **pageInfo.hasNextPage** | `connection.pageInfo` | More items forward |
| **totalCount** | `connection.totalCount` | Total items matching filter |
- Use `first` + `after` for forward pagination (most common)
- Avoid using `totalCount` for large datasets (can be slow)
## Introspection and Schema Downloading
| Method | Tool | Use Case |
|--------|------|----------|
| **Introspection query** | Built-in GraphQL client | Development exploration |
| **GraphQL Playground** | `/graphql/` in browser | Interactive schema browser |
| **Schema download** | `graphql-codegen` | CI/CD and type generation |
| **SDL export** | `rover graph introspect <url>` | Save schema as `.graphql` file |
## Testing GraphQL Operations
| Test Type | Tool | What to Test |
|-----------|------|-------------|
| **Unit** | Vitest, Jest | Operation result parsing, error mapping |
| **Integration** | Saleor test instance | Full round-trip query/mutation |
| **Type check** | `tsc --noEmit` | Generated types match operations |
| **Linting** | `@graphql-eslint/eslint-plugin` | Operation naming, fragment usage |
## Best Practices
- Use GraphQL code generation with TypedDocumentNode for end-to-end type safety
- Define reusable fragments for common field selections
- Always use variables for dynamic values — never concatenate strings
- Check `data.mutation.errors` after every mutation call
- Name every operation uniquely with descriptive PascalCase names
- Use cursor-based pagination with `first`/`after` for list queries
- Include the `saleor-channel` header for channel-scoped operations
- Keep operations minimal — request only the fields you need
- Run `graphql-codegen` in CI to catch schema mismatches
Fetch the GraphQL documentation for current Saleor schema, code generation setup, and client library configuration before implementing.More 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 时使用。

