واجهات GraphQL

توليد الكود

18 دقيقة الدرس 29 من 35

توليد الكود

أتمت توليد أنواع TypeScript وخطافات React والمحللات من مخطط GraphQL والعمليات الخاصة بك باستخدام GraphQL Code Generator.

مولد كود GraphQL

تثبيت وتكوين مولد كود GraphQL:

# تثبيت التبعيات npm install -D @graphql-codegen/cli \ @graphql-codegen/typescript \ @graphql-codegen/typescript-operations \ @graphql-codegen/typescript-react-apollo # تهيئة التكوين npx graphql-codegen init # أو أنشئ codegen.yml يدوياً
# codegen.yml schema: http://localhost:4000/graphql documents: 'src/**/*.graphql' generates: src/generated/graphql.ts: plugins: - typescript - typescript-operations - typescript-react-apollo config: withHooks: true withComponent: false withHOC: false

توليد أنواع TypeScript

ولّد تعريفات TypeScript آمنة من حيث النوع من المخطط الخاص بك:

# schema.graphql type User { id: ID! name: String! email: String! posts: [Post!]! } type Post { id: ID! title: String! content: String! author: User! } type Query { user(id: ID!): User users: [User!]! } type Mutation { createUser(input: CreateUserInput!): User! } input CreateUserInput { name: String! email: String! }
# تشغيل توليد الكود npm run codegen # الأنواع المُولَّدة في src/generated/graphql.ts export type User = { __typename?: 'User'; id: Scalars['ID']; name: Scalars['String']; email: Scalars['String']; posts: Array<Post>; }; export type Post = { __typename?: 'Post'; id: Scalars['ID']; title: Scalars['String']; content: Scalars['String']; author: User; }; export type CreateUserInput = { name: Scalars['String']; email: Scalars['String']; };
ملاحظة: الأنواع المُولَّدة تتضمن تلقائياً حقول __typename لتحديد نوع GraphQL والتخزين المؤقت.

توليد خطافات React

أنشئ خطافات React آمنة من حيث النوع من عمليات GraphQL الخاصة بك:

# src/graphql/queries.graphql query GetUser($id: ID!) { user(id: $id) { id name email posts { id title } } } query GetUsers { users { id name email } }
# src/graphql/mutations.graphql mutation CreateUser($input: CreateUserInput!) { createUser(input: $input) { id name email } }
// خطافات مُولَّدة في src/generated/graphql.ts export function useGetUserQuery( baseOptions: Apollo.QueryHookOptions<GetUserQuery, GetUserQueryVariables> ) { return Apollo.useQuery<GetUserQuery, GetUserQueryVariables>( GetUserDocument, baseOptions ); } export function useCreateUserMutation( baseOptions?: Apollo.MutationHookOptions< CreateUserMutation, CreateUserMutationVariables > ) { return Apollo.useMutation<CreateUserMutation, CreateUserMutationVariables>( CreateUserDocument, baseOptions ); } // الاستخدام في مكون React import { useGetUserQuery, useCreateUserMutation } from './generated/graphql'; function UserProfile({ userId }: { userId: string }) { const { data, loading, error } = useGetUserQuery({ variables: { id: userId }, }); const [createUser] = useCreateUserMutation(); if (loading) return <div>جاري التحميل...</div>; if (error) return <div>خطأ: {error.message}</div>; return ( <div> <h1>{data?.user?.name}</h1> <p>{data?.user?.email}</p> </div> ); }
نصيحة: استخدم علامة --watch مع codegen لإعادة توليد الأنواع تلقائياً عند تغيير ملفات GraphQL: npm run codegen -- --watch

توليد المحللات

ولّد توقيعات محللات آمنة من حيث النوع للخادم الخاص بك:

# codegen.yml من جانب الخادم schema: ./schema.graphql generates: src/generated/resolvers.ts: plugins: - typescript - typescript-resolvers config: useIndexSignature: true contextType: ./context#Context mappers: User: ./models#UserModel Post: ./models#PostModel
// أنواع المحللات المُولَّدة import { GraphQLResolveInfo } from 'graphql'; import { UserModel, PostModel } from './models'; import { Context } from './context'; export type Resolvers<ContextType = Context> = { Query?: QueryResolvers<ContextType>; Mutation?: MutationResolvers<ContextType>; User?: UserResolvers<ContextType>; Post?: PostResolvers<ContextType>; }; export type QueryResolvers<ContextType = Context> = { user?: Resolver<Maybe<User>, {}, ContextType, RequireFields<QueryUserArgs, 'id'>>; users?: Resolver<Array<User>, {}, ContextType>; }; export type MutationResolvers<ContextType = Context> = { createUser?: Resolver<User, {}, ContextType, RequireFields<MutationCreateUserArgs, 'input'>>; }; // استخدم الأنواع المُولَّدة في المحللات الخاصة بك import { Resolvers } from './generated/resolvers'; export const resolvers: Resolvers = { Query: { user: async (_, { id }, { db }) => { return db.user.findUnique({ where: { id } }); }, users: async (_, __, { db }) => { return db.user.findMany(); }, }, Mutation: { createUser: async (_, { input }, { db }) => { return db.user.create({ data: input }); }, }, };

تكوين Codegen

خيارات تكوين متقدمة لحالات استخدام مختلفة:

# codegen.yml - مثال تكوين كامل schema: http://localhost:4000/graphql documents: - 'src/**/*.graphql' - 'src/**/*.tsx' generates: # أنواع وخطافات من جانب العميل src/generated/client.ts: plugins: - typescript - typescript-operations - typescript-react-apollo config: withHooks: true withComponent: false withHOC: false skipTypename: false enumsAsTypes: true constEnums: true # أنواع محللات من جانب الخادم src/generated/server.ts: plugins: - typescript - typescript-resolvers config: useIndexSignature: true contextType: ../context#Context defaultMapper: Partial<{T}> mappers: User: ../models#UserModel Post: ../models#PostModel # مخطط GraphQL كـ TypeScript src/generated/schema.ts: plugins: - typescript - typescript-graphql-files-modules # نتيجة الفحص الذاتي src/generated/introspection.json: plugins: - introspection hooks: afterAllFileWrite: - prettier --write - eslint --fix

تكامل CI/CD

ادمج توليد الكود في خط بناء التطبيق الخاص بك:

{ "scripts": { "codegen": "graphql-codegen --config codegen.yml", "codegen:watch": "graphql-codegen --config codegen.yml --watch", "prebuild": "npm run codegen", "build": "tsc", "pretest": "npm run codegen", "test": "jest" } }
# .github/workflows/ci.yml name: CI on: [push, pull_request] jobs: test: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - name: Setup Node.js uses: actions/setup-node@v3 with: node-version: '18' - name: Install dependencies run: npm ci - name: Generate GraphQL types run: npm run codegen - name: Run type check run: npm run type-check - name: Run tests run: npm test - name: Build run: npm run build
تحذير: التزم دائماً بالملفات المُولَّدة في التحكم في الإصدار أو أعد توليدها في CI/CD. وثّق اختيارك في ملف README الخاص بمشروعك.
تمرين:
  1. قم بإعداد مولد كود GraphQL مع تكوينات العميل والخادم
  2. أنشئ عمليات GraphQL في ملفات .graphql
  3. ولّد أنواع TypeScript وخطافات React وأنواع المحللات
  4. أنشئ مكون React باستخدام الخطافات المُولَّدة
  5. نفذ محللات الخادم باستخدام الأنواع المُولَّدة
  6. أضف codegen إلى خط بناء التطبيق الخاص بك واختبره