TypeGraphql 官方文档示例练习:
import {
ObjectType,
Field,
ID,
Int,
Resolver,
Query,
Args,
ArgsType,
InputType,
Mutation,
Arg,
FieldResolver,
Root
} from 'type-graphql'
import { Min, Max } from 'class-validator'
// 定义类型和字段
@ObjectType({ description: 'test' })
class Recipe {
@Field(() => ID, { nullable: true })
id?: string
@Field()
title: string
@Field({ nullable: true })
description?: string
@Field()
ratings?: number[]
@Field()
averageRating?: number
}
// 定义 Mutation 用到的参数类型
@InputType()
class AddRecipeInput implements Partial<Recipe> {
@Field()
title: string
@Field({ nullable: true })
description?: string
}
// 定义一个 Query 用到的参数类型
@ArgsType()
class GetRecipesArgs {
// 使用defaultValue,TypeGraphql会设置默认值并使该字段可为空
@Field(() => Int, { defaultValue: 0 })
@Min(0)
skip: number
@Field(() => Int)
@Min(1)
@Max(50)
take = 25 // 属性初始化,和 defaultValue 的效果一样
@Field({ nullable: true })
title?: string
// 可以在 args 中自定义辅助方法
get startIndex(): number {
return this.skip
}
get endIndex(): number {
return this.skip + this.take
}
}
// 创建一个解析器
@Resolver()
class RecipeResolver {
// 使用依赖注入,将服务器/存储库/数据存储在resolver类的内部,保证每个应用都由唯一的实例
private recipesCollection: Recipe[] = []
// 创建一个 Query
@Query(() => [Recipe])
async recipes(
@Args()
{ title, startIndex, endIndex }: GetRecipesArgs
): Promise<Recipe[]> {
let recipes = this.recipesCollection
if (title) {
recipes = recipes.filter((recipe) => recipe.title === title)
}
return recipes.slice(startIndex, endIndex)
}
// 创建一个 Mutation
@Mutation()
addRecipe(
@Arg('data')
newRecipeData: AddRecipeInput
// @Ctx()
// ctx: Context
): Recipe[] {
this.recipesCollection.push(newRecipeData)
return this.recipesCollection
}
// 创建一个字段解析器
@FieldResolver()
averageRating(
@Root()
recipe: Recipe
) {
const ratingsSum =
recipe?.ratings?.reduce((prev, next) => prev + next, 0) || 0
return recipe?.ratings?.length ? ratingsSum / recipe.ratings.length : null
}
}