zoukankan      html  css  js  c++  java
  • 尝试使用Nestjs搭建GraphQL服务

    参考文档官网文档尝试遇到问题:

    1、返回null的问题可以通过nullable: true解决

    2、返回的数据跟schema 中定义的预期 types类型不一致,主要是由于之前在result.interceptor.ts中自定义返回数据格式导致,做下区分就可以了。

    app.module.ts

    import { Module } from '@nestjs/common';
    import { GraphQLModule } from '@nestjs/graphql';
    import { SuppliesModule } from '../supplies/supplies.module';
    
    const GQLModule = GraphQLModule.forRootAsync({
        useFactory: () => ({
            debug: true,
            playground: true,
            installSubscriptionHandlers: true,
            autoSchemaFile: 'schema.gql',
            tracing: true,
            include: [SuppliesModule],
        }),
    });
    
    @Module({
      imports: [
        GQLModule,
      ],
    })
    export class AppModule {}

    supplies.resolver.ts

    import { NotFoundException } from '@nestjs/common';
    import { Args, Mutation, Query, Resolver, Subscription } from '@nestjs/graphql';
    import { PubSub } from 'apollo-server-express';
    import { NewSupplieInput } from '../dto/supplie.input';
    import { SupplieArgs } from '../dto/supplie.args';
    import { Supplie } from '../models/supplie.model';
    import { SuppliesService } from '../service/supplies.service';
    
    const pubSub = new PubSub();
    
    @Resolver((of) => Supplie)
    export class SuppliesResolver {
        constructor(private readonly suppliesService: SuppliesService) {}
    
        // @UseGuards(GqlAuthGuard)
        @Query((returns) => String)
        hello(): string {
            return 'Hello World!';
        }
    
        // 查询单个
        @Query((returns) => Supplie, { name: 'supplie', nullable: true })
        async supplie(@Args('id') id: string): Promise<Supplie> {
            const supplie = await this.suppliesService.findOneById(id);
            if (!supplie) {
                throw new NotFoundException(id);
            }
            return supplie;
        }
    
        // 查询所有
        @Query((returns) => [Supplie])
        async suppliesAll(@Args() supplieArgs: SupplieArgs): Promise<Supplie[]> {
            return this.suppliesService.findAll(supplieArgs);
        }
    
        // 添加
        @Mutation((returns) => Supplie)
        async addSupplie(@Args('newSupplieData') newSupplieData: NewSupplieInput): Promise<Supplie> {
            const supplie = await this.suppliesService.create(newSupplieData);
            pubSub.publish('suplieAdded', { suplieAdded: supplie });
            return supplie;
        }
    
        // 删除
        @Mutation((returns) => Boolean)
        async removeSupplie(@Args('id') id: string) {
            return this.suppliesService.remove(id);
        }
    
        @Subscription((returns) => Supplie)
        suplieAdded() {
            return pubSub.asyncIterator('suplieAdded');
        }
    }

    supplies.service.ts

    import { Injectable } from '@nestjs/common';
    import { NewSupplieInput } from '../dto/supplie.input';
    import { SupplieArgs } from '../dto/supplie.args';
    import { Supplie } from '../models/supplie.model';
    
    @Injectable()
    export class SuppliesService {
        private readonly supplies: Supplie[] = [{ id: 1, firstName: 'Cat', lastName: '5' }];
    
        async create(data: NewSupplieInput): Promise<Supplie> {
            return {} as any;
        }
    
        async findOneById(id: string): Promise<Supplie> {
            // return this.supplies.find((supplie) => supplie.id === id);
            return this.supplies[0];
        }
    
        async findAll(supplieArgs: SupplieArgs): Promise<Supplie[]> {
            const result = [
                { id: 100, firstName: 'ddd', lastName: 'ddf' },
                { id: 11, firstName: 'ddd', lastName: 'ddf' },
            ];
            return result;
        }
    
        async remove(id: string): Promise<boolean> {
            return true;
        }
    }

    supplies.module.ts

    import { Module } from '@nestjs/common';
    import { SuppliesResolver } from './resolver/supplies.resolver';
    import { SuppliesService } from './service/supplies.service';
    
    @Module({
        providers: [SuppliesResolver, SuppliesService],
    })
    export class SuppliesModule {}

    supplie.model.ts

    import { Field, Int, ObjectType } from '@nestjs/graphql';
    
    @ObjectType()
    export class Supplie {
        @Field((type) => Int)
        id?: number;
    
        @Field({ nullable: true })
        firstName: string;
    
        @Field({ nullable: true })
        lastName: string;
    }

    supplie.args.ts

    import { ArgsType, Field, Int } from '@nestjs/graphql';
    import { Max, Min } from 'class-validator';
    
    @ArgsType()
    export class SupplieArgs {
        @Field((type) => Int)
        @Min(0)
        skip: number = 0;
    
        @Field((type) => Int)
        @Min(1)
        @Max(50)
        take: number = 25;
    }

    supplie.input.ts

    import { Field, InputType } from '@nestjs/graphql';
    import { IsOptional, Length, MaxLength } from 'class-validator';
    
    @InputType()
    export class NewSupplieInput {
        @Field()
        @MaxLength(30)
        name: string;
    
        @Field({ nullable: true })
        @IsOptional()
        @Length(30, 255)
        firstName?: string;
    
        @Field((type) => String)
        lastName: string;
    }

    result.interceptor.ts

    import { Injectable, NestInterceptor, ExecutionContext, CallHandler } from '@nestjs/common';
    import { Observable, from } from 'rxjs';
    import { map } from 'rxjs/operators';
    import { GqlContextType } from '@nestjs/graphql';
    export interface Response<T> {
        data: T;
    }
    
    @Injectable()
    export class ResultInterceptor<T> implements NestInterceptor<T, Response<T>> {
        intercept(context: ExecutionContext, next: CallHandler): Observable<Response<T>> {
          
            // HTTP (REST) Context
            if (context.getType() === 'http') {
                return next.handle().pipe(
                    map((rawData) => ({
                        code: (rawData && rawData.code) || 100000,
                        msg: (rawData && rawData.msg) || 'success',
                        currTime: new Date(),
                        data: rawData ? (!rawData.code && !rawData.msg ? rawData : rawData.data || undefined) : undefined,
                    }))
                );
            }
            // GraphQL Context
            else if (context.getType<GqlContextType>() === 'graphql') {
                eturn next.handle();
            }
            return next.handle();
        }
    }

    二、在 Vue 组件中的用法

    <template>
      <div>{{ hello }}</div>
    </template>
    
    <script>
    import gql from 'graphql-tag'
    
    export default {
      apollo: {
        // 简单的查询,将更新 'hello' 这个 vue 属性
        hello: gql`query {
          hello
        }`,
      },
    }
    </script>
    
    query {
      supplie(id: "1") {
        firstName,
        lastName,
        id
      }
      hello
    }
    
    query SuppliesAll($pageIndex: Int!) {
     suppliesAll(skip: $pageIndex) {
        id,
        lastName
     }
    }
    

    Query Variables

    {
    "pageIndex": 1
    }

      

    参考:

    vue Apollo https://vue-apollo.netlify.com/zh-cn/guide/apollo

    NestJS GraphQL https://docs.nestjs.com/graphql/resolvers

    GraphQL快速入门 https://segmentfault.com/a/1190000017851838 

    VUE与GQLhttps://www.cnblogs.com/lhxsoft/p/11904388.html

     

  • 相关阅读:
    -_-#【缓存】Content-Type 错误
    ♫【事件】事件处理程序
    -_-#【Node】Express 400 Error: ENOENT, open
    【JS】定位
    【JS】壹零零壹
    洛谷—— P1018 乘积最大
    洛谷—— P1017 进制转换
    洛谷——P1011 车站
    洛谷——P2241 统计方形(数据加强版)
    洛谷——P1548 棋盘问题
  • 原文地址:https://www.cnblogs.com/terrylin/p/13164206.html
Copyright © 2011-2022 走看看