尝试使用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

 

猜你喜欢

转载自www.cnblogs.com/terrylin/p/13164206.html