Nestjs+GraphQL搭建服务
后面咱们介绍了GraphQL的概念和基础知识,这篇文章记录下应用Nestjs+GraphQL搭建Node服务。
装置
npm i --save @nestjs/graphql graphql-tools graphql apollo-server-express
注册
// app.module.tsimport { Module } from '@nestjs/common';import { GraphQLModule } from '@nestjs/graphql';import { ConfigModule, ConfigService } from 'nestjs-config';@Module({ imports: [ ConfigModule.load(path.resolve(__dirname, 'config', '**/!(*.d).{ts,js}')), GraphQLModule.forRootAsync({ imports: [ConfigModule], useFactory: (config: ConfigService) => config.get('graphql'), inject: [ConfigService], }) ],})export class ApplicationModule {}// src/config/graphql.tsimport * as path from 'path';export default { autoSchemaFile: path.join(process.cwd(), 'src/schema.gql'), // 最初生成的`Schema 文件,不可批改` installSubscriptionHandlers: true, // 启用订阅};
启动我的项目,并拜访 http://localhost:3000/graphql,咱们便能够看到graphql页面。
编写服务端逻辑
接下来咱们注册一个author模块,目录构造如下:
// author.module.tsimport { Module } from '@nestjs/common';import { AuthorService } from './author.service';import { AuthorResolver } from './author.resolver';@Module({ providers: [ AuthorService, AuthorResolver ]})export class AuthorModule {}
// author.service.ts// 此文件用于写数据库查问等逻辑,咱们着重学习GraphQL的应用,故此处不做相干Demoimport { Injectable } from '@nestjs/common';@Injectable()export class AuthorService { async findOneById() {}}
// author.resolver.tsimport { Args, Mutation, Query, Resolver, Subscription, ResolveField, Parent, Int } from '@nestjs/graphql';import { PubSub } from 'graphql-subscriptions';import { Author } from './models/author.model';import { Post } from './models/post.model';import { AuthorService } from './author.service';// import { GetAuthorArgs } from './dto/get-author.args';const pubSub = new PubSub();@Resolver(() => Author)export class AuthorResolver { constructor( private authorsService: AuthorService ) {} // 依据id查问作者信息 @Query(returns => Author, { name: 'author', description: 'get author info by id', nullable: false }) async getAuthor(@Args('id', { type: () => Int, description: 'author id', nullable: false }) id: number): Promise<any> { // return this.authorsService.findOneById(id); return { id, firstName: 'wu', lastName: 'pat', };}// 应用DTO承受参数// @Query(returns => Author)// async getAuthor(@Args() args: GetAuthorArgs) {// return this.authorsService.findOneById(args);// } // 批改作者信息 @Mutation(returns => Author, { name: 'changeAuthor', description: 'change author info by id', nullable: false }) async changeAuthor( @Args('id') id: number, @Args('firstName') firstName: string, @Args('lastName') lastName: string, ): Promise<any> { // return this.authorsService.findOneById(id); return { id, firstName, lastName, };} // 解析posts字段 @ResolveField() async posts(@Parent() author: Author): Promise<any> { const { id } = author; // return this.postsService.findAll({ authorId: id }); return [{ id: 4, title: 'hello', votes: 2412, }]; } // 新增文章 @Mutation(returns => Post) async addPost() { const newPost = { id: 1, title: '新增文章' }; // 新增胜利后,告诉更新 await pubSub.publish('postAdded', { postAdded: newPost }); return newPost; } // 监听变更 @Subscription(returns => Post, { name: 'postAdded', // filter: (payload, variables) => payload.postAdded.title === variables.title, // 过滤订阅 // resolve(this: AuthorResolver, value) { // 批改payload参数 // return value; // } }) async postAdded(/*@Args('title') title: string*/) { return (await pubSub.asyncIterator('postAdded')); }}
// author.model.tsimport { Field, Int, ObjectType } from '@nestjs/graphql';import { Post } from './post.model';@ObjectType({ description: 'Author model' })export class Author { @Field(type => Int, { description: '作者id' }) id: number; @Field({ nullable: true, description: '作者姓姓氏' }) firstName?: string; @Field({ nullable: true, description: '作者姓名字' }) lastName?: string; // 要申明数组的项(而不是数组自身)是可为空的,请将nullable属性设置'items' // 如果数组及其项都是可空的,则设置nullable为'itemsAndList' @Field(type => [Post], { nullable: 'items', description: '作者发表的文章' }) posts: Post[];}
// posts.model.tsimport { Field, Int, ObjectType } from '@nestjs/graphql';@ObjectType()export class Post { @Field(type => Int) id: number; @Field() title: string; @Field(type => Int, { nullable: true }) votes?: number;}
下面的代码蕴含了查问、变更、订阅类型,此时咱们会发现src上面新增了一个文件schema.gql,这个文件就是主动生成的类型文件:
# ------------------------------------------------------# THIS FILE WAS AUTOMATICALLY GENERATED (DO NOT MODIFY)# ------------------------------------------------------type Post { id: Int! title: String! votes: Int}"""Author model"""type Author { """作者id""" id: Int! """作者姓姓氏""" firstName: String """作者姓名字""" lastName: String """作者发表的文章""" posts: [Post]!}type Query { """get author info by id""" author( """author id""" id: Int! ): Author!}type Mutation { """change author info by id""" changeAuthor(lastName: String!, firstName: String!, id: Float!): Author! addPost: Post!}type Subscription { postAdded: Post!}
执行查问
这时咱们的服务曾经运行起来,能够执行查问了。
# 左下角编写QUERY VARIABLES{ "id": 1}
# Write your query or mutation here# 查问作者信息query author($id: Int!) { alias: author(id: $id) { id, firstName, posts { id, title } }}# 批改作者信息mutation changeAuthor { changeAuthor(id: 3, firstName: "firstName" lastName: "lastName") { id, firstName, lastName }}# 公布文章mutation addPost { post: addPost { id, title }}# 订阅文章新增subscription postAdded{ postAdded { id, title }}// 自省查问query schema{ __schema { types { name } }}
至此,咱们的Nestjs+GraphQL服务便搭建实现,给本人一个????!