واجهات GraphQL
توليد الكود
توليد الكود
أتمت توليد أنواع 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 الخاص بمشروعك.
تمرين:
- قم بإعداد مولد كود GraphQL مع تكوينات العميل والخادم
- أنشئ عمليات GraphQL في ملفات
.graphql - ولّد أنواع TypeScript وخطافات React وأنواع المحللات
- أنشئ مكون React باستخدام الخطافات المُولَّدة
- نفذ محللات الخادم باستخدام الأنواع المُولَّدة
- أضف codegen إلى خط بناء التطبيق الخاص بك واختبره