mcpField
G
graphql-codegen

graphql-codegen

github.com/claude-dev-suite开发4664 次安装2 天前更新
代码仓库

关于 graphql-codegen

面向 TypeScript 开发者的 GraphQL Code Generator 参考技能,涵盖配置、生成类型及客户端集成。适用于从 GraphQL schema 和操作文档生成类型安全代码的项目。

主要功能

  1. 01CLI 配置与代码生成
  2. 02客户端预设与类型生成
  3. 03TanStack Query 集成
  4. 04片段共置
  5. 05多 schema 配置
  6. 06CI 与监视模式

适用场景

  1. 01从 schema 和操作文档生成 TypeScript 代码
  2. 02为 GraphQL 操作生成客户端查询钩子
  3. 03在开发期间监视文档并重新生成

MCP 相关

提及可通过 `mcp__documentation__fetch_docs` 获取 graphql-codegen 的深入文档。

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/claude-dev-suite/claude-dev-suite --skill graphql-codegen

安装后在 Claude Code 中输入/graphql-codegen确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

quick-ref/
client-preset.md
react-query.md
typed-document-node.md

详细介绍

GraphQL Code Generator 核心知识

深度知识:使用 mcp__documentation__fetch_docs,并将技术设为 graphql-codegen,获取完整文档。

安装

npm install -D @graphql-codegen/cli @graphql-codegen/typescript \
  @graphql-codegen/typescript-operations @graphql-codegen/client-preset

基本配置

// codegen.ts
import type { CodegenConfig } from '@graphql-codegen/cli';

const config: CodegenConfig = {
  schema: 'http://localhost:4000/graphql',
  documents: ['src/**/*.tsx', 'src/**/*.ts'],
  ignoreNoDocuments: true,
  generates: {
    './src/gql/': {
      preset: 'client',
      config: {
        documentMode: 'string',
      },
    },
  },
};

export default config;

运行生成

npx graphql-codegen
npx graphql-codegen --watch  # Watch mode

Client Preset(推荐)

client preset 会生成实现 GraphQL 类型安全所需的一切内容。

// codegen.ts
const config: CodegenConfig = {
  schema: 'http://localhost:4000/graphql',
  documents: ['src/**/*.tsx'],
  generates: {
    './src/gql/': {
      preset: 'client',
      plugins: [],
      presetConfig: {
        gqlTagName: 'gql',
        fragmentMasking: { unmaskFunctionName: 'getFragmentData' },
      },
    },
  },
};
用法
import { gql } from '../gql';
import { useQuery } from '@apollo/client';

const GET_USER = gql(`
  query GetUser($id: ID!) {
    user(id: $id) {
      id
      name
      email
    }
  }
`);

function UserProfile({ id }: { id: string }) {
  const { data, loading } = useQuery(GET_USER, {
    variables: { id },
  });

  if (loading) return <Spinner />;
  // data.user is fully typed
  return <div>{data?.user?.name}</div>;
}

TanStack Query 集成

npm install -D @graphql-codegen/typescript-react-query
// codegen.ts
const config: CodegenConfig = {
  schema: 'http://localhost:4000/graphql',
  documents: ['src/**/*.graphql'],
  generates: {
    './src/gql/index.ts': {
      plugins: [
        'typescript',
        'typescript-operations',
        'typescript-react-query',
      ],
      config: {
        fetcher: {
          func: './fetcher#fetcher',
          isReactHook: false,
        },
        reactQueryVersion: 5,
        addInfiniteQuery: true,
      },
    },
  },
};
Fetcher
// src/gql/fetcher.ts
export const fetcher = <TData, TVariables>(
  query: string,
  variables?: TVariables
): (() => Promise<TData>) => {
  return async () => {
    const response = await fetch('http://localhost:4000/graphql', {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        Authorization: `Bearer ${getToken()}`,
      },
      body: JSON.stringify({ query, variables }),
    });

    const json = await response.json();
    if (json.errors) {
      throw new Error(json.errors[0].message);
    }
    return json.data;
  };
};
生成的 Hooks 用法
import { useGetUserQuery, useCreateUserMutation } from './gql';

function UserProfile({ id }: { id: string }) {
  const { data, isLoading } = useGetUserQuery({ id });
  const createMutation = useCreateUserMutation();

  const handleCreate = () => {
    createMutation.mutate({
      input: { name: 'John', email: '[email protected]' },
    });
  };

  if (isLoading) return <Spinner />;
  return <div>{data?.user?.name}</div>;
}

片段就近放置

// components/UserAvatar.tsx
import { gql, FragmentType, getFragmentData } from '../gql';

export const USER_AVATAR_FRAGMENT = gql(`
  fragment UserAvatar on User {
    id
    name
    avatarUrl
  }
`);

interface Props {
  user: FragmentType<typeof USER_AVATAR_FRAGMENT>;
}

export function UserAvatar({ user }: Props) {
  const data = getFragmentData(USER_AVATAR_FRAGMENT, user);
  return <img src={data.avatarUrl} alt={data.name} />;
}

// Usage in parent query
const GET_USER = gql(`
  query GetUser($id: ID!) {
    user(id: $id) {
      id
      ...UserAvatar
    }
  }
`);

生产就绪

Schema 轮询
// codegen.ts
const config: CodegenConfig = {
  schema: [
    {
      'http://localhost:4000/graphql': {
        headers: {
          Authorization: `Bearer ${process.env.GRAPHQL_TOKEN}`,
        },
      },
    },
  ],
  // ...
};
多个 Schema
const config: CodegenConfig = {
  generates: {
    './src/gql/user-api/': {
      schema: 'http://user-api:4000/graphql',
      documents: ['src/features/user/**/*.tsx'],
      preset: 'client',
    },
    './src/gql/product-api/': {
      schema: 'http://product-api:4001/graphql',
      documents: ['src/features/product/**/*.tsx'],
      preset: 'client',
    },
  },
};
CI/CD 集成
# .github/workflows/codegen.yml
name: GraphQL Codegen

on:
  push:
    paths:
      - 'src/**/*.graphql'
      - 'src/**/*.tsx'

jobs:
  generate:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: npm ci
      - run: npx graphql-codegen
      - name: Check for changes
        run: |
          if [[ -n $(git status --porcelain src/gql) ]]; then
            echo "Generated files changed"
            exit 1
          fi
Package 脚本
{
  "scripts": {
    "codegen": "graphql-codegen",
    "codegen:watch": "graphql-codegen --watch"
  }
}
检查清单
  • 已配置 Schema 来源(URL 或本地)
  • Documents 路径与源文件相匹配
  • 使用 client preset 以获得最佳输出
  • 已配置带身份验证的 Fetcher
  • 采用片段就近放置模式
  • 开发时启用监视模式
  • CI 中验证生成的代码
  • 兼容 TypeScript strict 模式

不适用此技能的情况

  • REST API 类型生成(使用 openapi-codegen 技能)
  • tRPC 类型安全 API(使用 trpc 技能)
  • GraphQL Schema 设计(使用 graphql 技能)
  • 非 TypeScript 项目
  • 无需生成类型的简单 GraphQL 查询

反模式

反模式为什么不好解决方案
将生成的文件提交到 git合并冲突、类型过时添加到 .gitignore,并在 CI 中生成
不使用 client preset配置冗长使用 client preset 进行现代化配置
忽略 Schema 变更运行时类型不匹配开发期间以监视模式运行 codegen
缺少 operationId 或查询名称生成的 hook 名称不佳为所有查询/变更命名
不使用片段代码重复使用片段复用字段
只生成类型缺少运行时验证与 Schema 验证结合使用
将 Schema URL 写死与环境耦合使用环境变量指定 Schema 来源
不对生成器包进行版本固定团队成员生成的输出不一致固定生成器版本

快速故障排查

问题可能原因解决方案
生成失败Schema 或 Documents 无效验证 Schema,检查 GraphQL 语法
生成后出现类型错误Schema/代码不匹配重新生成类型,检查 Schema 变更
缺少类型Documents 路径与文件不匹配检查 Documents glob 模式
操作名称重复多个文件中存在同名查询使用唯一的操作名称
找不到片段Documents 中不包含该片段将片段文件加入 Documents
未生成 Hook未使用 React Query 插件添加 typescript-react-query 插件
"Cannot find module './gql'"未运行生成运行 npm run codegen
生成缓慢Documents 过多优化 glob 模式,使用 ignoreNoDocuments
类型推断不起作用导入路径错误从生成的 gql 文件夹导入

参考文档

评论

支持 Markdown