iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 9
0
Modern Web

NestJs 讀書筆記系列 第 9

NestJs - GraphQL 內部結構說明 (上篇)

  • 分享至 

  • xImage
  •  

GraphQL 內部結構說明 (上篇)

目標:

  1. 了解 GraphQL Code first 模式,成功在 Playground 發送 API

上一個篇章我們岔出去說了一下 MongoDB,現在我們再回到 GrpahQL

有寫過 ApolloGraphQL 的讀者應該對於下面幾個名詞不陌生
它們有著密不可分的關係,所以我把它們放在一起說

Resolver Schema Queries
根據 Schema 的需求來實作 定義資料結構,客戶端可以讀取和寫入資料類型 包含 query 及 mutation,提供客戶端查詢以及更改資料的介面

NestJs 提供兩種方式建置 Schema

Code first Schema first
透過 TypeScript classes 和 TypeScript decorators 生成 SDL,再透過 @nestjs/graphql 讀取定義好的 metadata ,自動生成 GraphQL Schema 這方式可能是較為熟悉的方式,跟過去在定義 Schema 一樣,最後再需要的地方補上一些 decorators
以上是兩個粗略的比較,接下來會以範例來說明,讓讀者能夠更明白兩者的差異

讀者可以開兩個專案,將其分開架構才不會過於混亂
之前 GraphQL 的範例是以 Schema first 編寫

Code first

AppModule

首先使用 decorators 和 TypeScript classes 生成 GraphQL Schema,並指定路徑寫入

import { Module } from '@nestjs/common';
import { GraphQLModule } from '@nestjs/graphql';
import { AuthorsModule } from './authors/authors.module';
import { join } from 'path';

@Module({
  imports: [
    GraphQLModule.forRoot({
      // 將編譯過後的 Schema 寫入 src/schema.gql
      autoSchemaFile: join(process.cwd(), 'src/schema.gql')
    }),
    AuthorsModule
  ]
  
})
export class AppModule {}

Model

接著定義 Schema ,建立 author.model.ts,使用 TypeScript classes 和 TypeScript decorators 的 annotate ,標記屬性在欄位上。
在編譯時會根據 metadata 的屬性轉成相對的格式,我相信沒做過的人大概看不懂這是什麼意思,我們由範例來解說!

定義資料格式,包括:欄位名稱,類別,型態...

// 目錄: src/authors/models/author.model.ts

import { Field, ObjectType, ID } from '@nestjs/graphql';

@ObjectType()
export class Author {
  @Field(type => ID)
  id: string;

  @Field({ nullable: true })
  firstName?: string;

  @Field({ nullable: true })
  lastName?: string;
}

Resolver

在 Resolver 中定義 查詢 author 方法,能傳入參數 id,為了指定此方法是 查詢 ,必須在名稱上面加上 @Query() decorator,最後 decorator 會基於方法名稱產生 Schema

// 目錄:src/authors/authors.resolver.ts

import { Resolver, Query, ID, Args } from "@nestjs/graphql";

import { Author } from './models/author.model';

@Resolver(of => Author)
export class AuthorsResolver {
  constructor(
  ) {}

  @Query(returns => Author)
  async author(@Args('id', { type: () => ID }) id: string) {}
}

Module

將剛剛完成的 Resolver import 到 authors.module

// 目錄:src/authors/authors.module.ts
import { Module } from '@nestjs/common';
import { AuthorsResolver } from './authors.resolver';
@Module({
    providers: [AuthorsResolver]
})
export class AuthorsModule {}

Schema

接著先啟動服務,就能看到 src 目錄下生成了 schema.gql,這就是透過 TypeScript decorator 編譯完成的結果!

# ------------------------------------------------------
# THIS FILE WAS AUTOMATICALLY GENERATED (DO NOT MODIFY)
# ------------------------------------------------------

type Author {
  id: ID!
  firstName: String
  lastName: String
}

type Query {
  author(id: ID!): Author!
}

打開 http://localhost:3000/graphql ,查詢 author ,就會回傳失敗!!
因為 author 並沒有回傳任何物件,所以必須先回去 AuthorsResolver 補上要回傳的資訊,記得要符合我們定義的 author.model 格式。

async findOneById(id: String): Promise<Author> {
    return {
        id: '1',
        lastName: "lastName",
        firstName: "firstName"
    };
}

最後完成的結果 /images/emoticon/emoticon12.gif

下一篇章我們會說明 Schema first 是如何建構的~


上一篇
在 NestJs 如何使用 MongoDB
下一篇
NestJs - GraphQL 內部結構說明 (下篇)
系列文
NestJs 讀書筆記31
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言