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服务便搭建实现,给本人一个????!