autoSchmaFile 지정: path or memorytypePaths 지정: SDL files pathts-node generate-typings : TS 클래스 생성 가능@ObjectType@ObjectType({description: 'Author Model'})
export class Author {
@Field(type => Int)
id: number;
@Field({nullable: true})
firstName?: string;
@Field({nullable: true)}
lastName?: string;
@Field(tpye => [Post])
posts: Post[];
}
@Fieldnumber → Int or Floatnullablenullable: ‘items’nullable: ‘itemsAndList’descriptiondeprecationReasonSDL: Schema Definition Language
type Author {
id: Int!
firstName: String
lastName: String
posts: [Post]
}
@Resolver@ResolveField 가 포함될 때마다 필요@Resolver(of => Author)
export class AuthorsResolver {
constructor(
private authorsService: AuthorsService,
private postsService: PostsService,
) {}
@Query(returns => Author)
async author(@Args('id', { type: () => Int }) id: number) {
return this.authorsService.findOneById(id);
}
@ResolveField()
async posts(@Parent() author: Author) {
const { id } = author;
return this.postsService.findAll({ authorId: id });
}
@Mutation(returns => Post)
async upvotePost(@Args({ name: 'postId', type: () => Int }) postId: number) {
return this.postsService.upvoteById({ id: postId });
}
@Subscription(returns => Comment)
commentAdded() {
return pubSub.asyncIterator('commentAdded');
}
}
// SDL schema
type Query {
author(id: Int!): Author
}
type Mutation {
upvotePost(postId: Int!): Post
}
type Subscription {
commentAdded(): Comment!
}
@Query
get, find 와 같은 네이밍 지양name: 쿼리 유형이름 별도 설정 가능@Query({ name: ‘author’ })descriptiondeprecationReasonnullable@Mutation
@InputType 입력 유형 선언@InputType()
export class UpvotePostInput {
@Field()
postId: number;
}
@Mutation(returns => Post)
async upvotePost(
@Args('upvotePostData') upvotePostData: UpvotePostInput,
) {}@Subscription
installSubscriptionHandlers: truePubsub 인스턴스화Pubsub provider 정의 및 생성자를 통한 삽입Pubsub#asyncIterator : 이벤트에 대한 구독 처리triggerNamefilter: 특정 이벤트 필터링@Subscription(returns => Comment, {
filter: (payload, variables) =>
payload.commentAdded.title === variables.title,
})
commentAdded(@Args('title') title: string) {
return pubSub.asyncIterator('commentAdded');
}Pubsub#publish: 이벤트 게시
- 매개변수: triggerName, eventPayload
- 이벤트 페이로드 모양이 구독에서 반환되는 값의 모양과 일치해야 함
- 클라이언트 측 업데이트를 트리거하기 위해 뮤테이션내에서 자주 사용
@Mutation(returns => Post)
async addComment(
@Args('postId', { type: () => Int }) postId: number,
@Args('comment', { type: () => Comment }) comment: CommentInput,
) {
const newComment = this.commentsService.addComment({ id: postId, comment });
pubSub.publish('commentAdded', { commentAdded: newComment });
return newComment;
}
resolve: 게시된 이벤트 페이로드 변경
@Args
@Args() args: GetAuthorArgs
// get-author.args.ts
@ArgsType()
class GetAuthorArgs {
@Field({ nullable: true })
firstName?: string;
@Field({ defaultValue: '' })
@MinLength(3)
lastName: string;
}type: TS 유형에서 예상되는 GraphQL 유형이 없는 경우 명시적 전달@Args('id', { type: () => Int }) id: number)defaultValuedescriptiondeprecationReasonnullable@ResolveField
@Parent 부모 객체 정의 필요ID
Int
Float
GraphQLISODateTime
GraphQLTimestamp
@Scalar
사용자 지정 스칼라
provider로 등록 필요
@Scalar('Date', (type) => Date)
export class DateScalar implements CustomScalar<number, Date> {
description = 'Date custom scalar type';
parseValue(value: number): Date {
return new Date(value); // value from the client
}
serialize(value: Date): number {
return value.getTime(); // value sent to the client
}
parseLiteral(ast: ValueNode): Date {
if (ast.kind === Kind.INT) {
return new Date(ast.value);
}
return null;
}
}
@include(if: Boolean)@skip(if: Boolean)@deprecated(reason: String)SchemaDirectiveVisitor 클래스를 확장하는 클래스 선언export class UpperCaseDirective extends SchemaDirectiveVisitor {
visitFieldDefinition(field: GraphQLField<any, any>) {
const { resolve = defaultFieldResolver } = field;
field.resolve = async function(...args) {
const result = await resolve.apply(this, args);
if (typeof result === 'string') {
return result.toUpperCase();
}
return result;
};
}
}GraphQLModule.forRoot({
// ...
schemaDirectives: {
upper: UpperCaseDirective,
},
});@Directive('@deprecated(reason: "This query will be removed in the next version")')
@Query(returns => Author, { name: 'author' })
async getAuthor(@Args({ name: 'id', type: () => Int }) id: number) {
return this.authorsService.findOneById(id);
}directive @upper on FIELD_DEFINITION
type Post {
id: Int!
title: String! @upper
votes: Int
}@InterfaceType() 으로 정의@InterfaceType()
export abstract class Character {
@Field(type => ID)
id: string;
@Field()
name: string;
}
// 인터페이스 구현
@ObjectType({
implements: () => [Character],
})
export class Human implements Character {
id: string;
name: string;
}