ネストを使用して、GraphSQL APIを構築する方法


私に従って、トピックや改善についてのご提案を取るに満足

There are many ways to build a GraphQL API. Looking at JavaScript you might be using the raw grapql library, the graphql-express library or why not the one from apollo. There is another really great way and that is Nest.js that nicely integrates with GraphQL


この記事では、

  • グラフィカルに説明する.私たちはあなたの主要な構造を理解するために十分に説明します.

  • 最初の巣を作成します.JP + Graphqlプロジェクトと完全なcrudのように見えるものを見てください

  • ベストプラクティスは、我々が巣の完全な力を活用するために何をすることができるかについて見ましょう

  • ラフグラフの基礎
    以下の記事のGraphSQLの基礎を説明しました.


  • この記事はGraphSQLに完全なプライマーを追加した場合にはとても長いことでしょう.したがって、スキーマとリゾルバ関数からなるGraphSQL APIを示すことで満足しましょう.

    クリエイトユアファーストHello GraphQL 巣で.js
    では、GraphSQLがどのように動作するかについての基本的な理解があります.次の手順を実行します.

  • ネストプロジェクト

  • GraphSQLを使用するプロジェクトを準備します

  • スキーマとリゾルバを書く

  • ええ、巣を足場にします.JSプロジェクト
    新しいプロジェクトを足場にするには、次のように入力します.
    nest new hello-world
    
    置換できますhello-world プロジェクトの名前を指定します.これは、次のステップのために必要なファイルを与えます.

    ワイヤアップグラフ
    作成したプロジェクトでGraphqlを使用するには、次の手順を実行する必要があります.
  • 必要な依存関係をインストールする
  • 設定GraphQLModule
  • 注意してください.
    npm i --save @nestjs/graphql apollo-server-express graphql
    
    上記はネストのために必要なGraphSQL結合を与えます@nestjs/graphql とグラフ作成のためのアポロライブラリapollo-server-express .
    次は何かを設定する必要がありますGraphQLModule 図書館から得たもの@nestjs/graphql . これを設定する方法はたくさんありますが、この時点でスキーマファイルを見つける場所です.したがって、我々は変更されますapp.module.ts 以下のようになります.
    // app.module.ts
    
    import { Module } from '@nestjs/common';
    import { GraphQLModule } from '@nestjs/graphql';
    import { AppResolver } from './app.resolver';
    // import { join } from 'path';
    
    @Module({
      imports: [
        GraphQLModule.forRoot({
          debug: false,
          playground: true,
          typePaths: ['./**/*.graphql']
        }),
      ],
      providers: [ AppResolver ]
    })
    export class AppModule { }
    
    詳しく見ましょうGraphQLModule.forRoot() 呼び出し.今、我々はここで我々は設定を参照してくださいplayground である.これは私たちのクエリをもたらすためのグラフィカルな方法を与えます.また、私たちは、私たちがtypePaths そして、そのように見える配列を与える['./**/*.graphql'] . さて、これは.graphql . この構文の理由は、実際にいくつかのファイルのスキーマ定義を広げることができます.

    スキーマとリゾルバを書く
    次のステップは、上記のパターンにマッチするファイルを作成することですapp.graphql 次のコンテンツを提供します.
    // app.graphql
    
    type Cat {
      id: Int
      name: String
      age: Int
    }
    
    type Query {
      getCats: [Cat]
      cat(id: ID!): Cat
    }
    
    さて、これは私たちをきれいに設定しますが、リゾルバ関数はどうですか?さて、頭に戻るapp.module.ts そして、特定の行にズームproviders: [ AppResolver ] . これは私たちの配線アップですAppResolver それは我々のResolverクラスとして機能します.詳しく見ましょうAppResolver :
    // app.resolver.ts
    
    import { Args, Mutation, Query, Resolver, Subscription } from '@nestjs/graphql';
    import { ParseIntPipe } from '@nestjs/common';
    
    
    @Resolver('Cat')
    export class AppResolver {
      cats = [{
        id: 1,
        name: 'Mjau',
        age: 17
      }]
    
      @Query()
      getCats() {
        console.log('getCats');
        return this.cats;
      }
    
      @Query('cat')
      async findOneById(
        @Args('id', ParseIntPipe)
        id: number,
      ): Promise<any> {
        return this.cats.find(c => c.id === id);
      }
    
    }
    
    ご覧の通りクラスを作りますAppResolver しかし、また、いくつかの面白い装飾機が付属しています.説明しましょう
  • @Resolver , このDecoratorは、GraphSQLに、このクラスがTypeCat .
  • Query() , これは、これによって装飾されているメソッドは、Query スキーマで.我々が見ることができるように、我々には方法がありますgetCats() しかし、我々がマッチを命名するつもりでないケースでは、我々はARGQuery それはどのような部分が一致すると言う.この方法でわかるようにfindOneById() 我々はそれを飾るQuery('cat') これは単に任意のクエリを解決することを意味cat
  • @Args , このデコレータは、任意の入力パラメータを掘るためにヘルパーデコレータとして使用されます

  • スピンのために取る
    まず最初に、必要なライブラリを最初に入力してください.
    npm install
    
    すべての必要な依存関係をインストールします.一旦この仕上がりが始まるならば、我々は出発する準備ができていなければなりません.
    次の型はAPIを試すことができます.
    npm start
    
    次のようになります.

    次のステップは、私たちのブラウザに移動することですhttp://localhost:3000/graphql . 次のように表示されます.

    としては、上記の2つの異なるクエリを定義して画像を参照してくださいoneCat and allCats そして、それぞれのクエリ定義を見ることができます.と呼ばれてoneCat あなたはどのように呼び出すことがわかります{ cat(id: 1){ name } } つまり、Resolverを呼び出しますcat パラメータ付きid と値1 フィールドを選択name 結果では、Cat . 他のクエリallCats 単純呼び出し{ getCats } このメソッドはAppResolver クラス

    加算加算器
    これまでのところ、我々は完全に動作するGraphSQL APIをクエリに動作しますが、我々はmutatorの一部を欠落している、我々は猫を追加し、それを更新したり、削除をサポートする場合はどうですか?そのためには、次の手順を実行する必要があります.
  • 我々のスキーマにmutator操作を加えてください
  • 必要なレゾルバメソッドをAppResolver クラス
  • テストする

  • スキーマの更新
    を、スキーマにいくつかのmutatorsを追加する必要がありますapp.graphql 以下のようになります.
    type Cat {
      id: Int
      name: String
      age: Int
    }
    
    input CatInput {
      name: String
      age: Int,
      id: Int
    }
    
    type Mutation {
      createCat(cat: CatInput): String,
      updateCat(cat: CatInput): String,
      deleteCat(id: ID!): String
    }
    
    type Query {
      getCats: [Cat]
      cat(id: ID!): Cat
    }
    
    上記のように我々は追加しましたMutation and CatInput
    リゾルバを追加する
    を、今私たちに戻る必要がありますAppResolver クラスを確認し、次のように確認します.
    // app.resolver.ts
    
    import { Args, Mutation, Query, Resolver, Subscription } from '@nestjs/graphql';
    import { ParseIntPipe } from '@nestjs/common';
    
    
    
    @Resolver('Cat')
    export class AppResolver {
      cats = [{
        id: 1,
        name: 'Cat1',
        age: 17
      }]
    
      @Mutation()
      createCat(
        @Args('cat')
        cat: any
      ): Promise<string> {
        this.cats = [...this.cats, {...cat, id: this.cats.length + 1}];
        return Promise.resolve('cat created');
      }
    
      @Mutation()
      updateCat(
        @Args('cat')
        cat: any
      ): Promise<string> {
        this.cats = this.cats.map(c => {
          if(c.id === cat.id) {
            return {...cat}
          }
          return c;
        });
        return Promise.resolve('cat updated');
      }
    
      @Mutation()
      deleteCat(
        @Args('id', ParseIntPipe)
        id: number
      ) : Promise<any> {
        this.cats = this.cats.filter(c => c.id !== id);
        return Promise.resolve('cat removed');
      }
    
    
      @Query()
      getCats() {
        console.log('getCats');
        return this.cats;
      }
    
      @Query('cat')
      async findOneById(
        @Args('id', ParseIntPipe)
        id: number,
      ): Promise<any> {
        return this.cats.find(c => c.id === id);
      }
    
    }
    
    追加の方法はdeleteCat() , updateCat() and createCat() .

    追加機能
    私たちはこの時点で完全に機能するAPIを持っています.実際には、ブラウザのウィンドウを確認し、完全なCRUDをテストすることができます.

    ベストプラクティスによって何を意味するのか?さて、以下のようにAPIを使いやすくすることができます.

  • 今、我々は多くの種類を定義しているapp.graphql ファイルが、これらの型を抽出し、それらをResolverクラス

  • 私たちのAPIを分割する必要はありません1つの巨大なスキーマファイルを確実にこれを分割することができますし、ネストのすべてのファイルを

  • DTOSを飾ることによってAPIを定義してください、APIを定義する第2の方法があります

  • 型を追加
    私は、我々のスキーマから型を抽出して、Resolverクラスでそれらを使用することができると言いました.それは素晴らしいが、私はあなたが疑問に思っていると思いますか?
    さて、最初に頭にする必要がありますapp.module.ts とプロパティdefinitions そして二つのことを言いなさい.最初に生成された型のファイル名を指定し、2番目に出力形式を指定します.後者には二つの選択肢がある.class or interface . ファイルは次のようになります.
    @Module({
      imports: [
        GraphQLModule.forRoot({
          debug: false,
          playground: true,
          typePaths: ['./**/*.graphql'],
          definitions: {
            path: join(process.cwd(), 'src/graphql.ts'),
            outputAs: 'class',
          }
        }),
      ],
      providers: [ AppResolver ]
    })
    export class AppModule { }
    
    あなたがAPIを始めるならばnpm start then src/graphql.ts が作成されます.
    //graphql.ts
    
    
    /** ------------------------------------------------------
     * THIS FILE WAS AUTOMATICALLY GENERATED (DO NOT MODIFY)
     * -------------------------------------------------------
     */
    
    /* tslint:disable */
    export class CatInput {
        name?: string;
        age?: number;
        id?: number;
    }
    
    export class Cat {
        id?: number;
        name?: string;
        age?: number;
    }
    
    export abstract class IMutation {
        abstract createCat(cat?: CatInput): string | Promise<string>;
    
        abstract updateCat(cat?: CatInput): string | Promise<string>;
    
        abstract deleteCat(id: string): string | Promise<string>;
    }
    
    export abstract class IQuery {
        abstract getCats(): Cat[] | Promise<Cat[]>;
    
        abstract cat(id: string): Cat | Promise<Cat>;
    }
    
    
    我々のためのテイクアウトは、タイプですCat and CatInput 我々が我々を作るために使うことができる我々AppResolver クラスAより安全なタイプ.あなたapp.resolver.ts ファイルは次のようになります.
    // app.resolver.ts
    
    import { Args, Mutation, Query, Resolver, Subscription } from '@nestjs/graphql';
    import { ParseIntPipe } from '@nestjs/common';
    import { Cat, CatInput } from './graphql';
    
    
    
    @Resolver('Cat')
    export class AppResolver {
      cats:Array<Cat> = [{
        id: 1,
        name: 'Cat1',
        age: 17
      }]
    
      @Mutation()
      createCat(
        @Args('cat')
        cat: CatInput
      ): Promise<string> {
        this.cats = [...this.cats, {...cat, id: this.cats.length + 1}];
        return Promise.resolve('cat created');
      }
    
      @Mutation()
      updateCat(
        @Args('cat')
        cat: CatInput
      ): Promise<string> {
        this.cats = this.cats.map(c => {
          if(c.id === cat.id) {
            return {...cat}
          }
          return c;
        });
        return Promise.resolve('cat updated');
      }
    
      @Mutation()
      deleteCat(
        @Args('id', ParseIntPipe)
        id: number
      ) : Promise<any> {
        this.cats = this.cats.filter(c => c.id !== id);
        return Promise.resolve('cat removed');
      }
    
      @Query()
      getCats(): Array<Cat> {
        return this.cats;
      }
    
      @Query('cat')
      async findOneById(
        @Args('id', ParseIntPipe)
        id: number,
      ): Promise<Cat> {
        return this.cats.find(c => c.id === id);
      }
    
    }
    
    上の注意点は、どのように内部配列cats 現在型Cat とメソッドcreateCat() and updateCat() 今のタイプの入力CatInput . 更なる方法getCats() 配列を返すCat そして最後に方法findOneById() タイプの約束を返すCat .

    スキーマ定義を分割する
    今、我々は簡単に物事が設定されているため、これを行うことができると述べた.これは*と呼ばれる別のファイルを作成するだけで簡単です.グラフ.それで、私はいつそれをするべきですか?よく、あなたのAPIで別のトピックを持っているときに分割を行う意味があります.あなたが犬を加えていると言いましょうdogs.graphql また、犬のための別のリゾルバークラスです.
    この記事のポイントはどのように開始することができますどのように徐々に新しいタイプと新しいリゾルバを追加し続ける必要が表示されます.あなたがそれが役に立つと思います.

    第二の物事の定義
    スキーマを定義する2番目の方法は、この記事のスコープの外にあります.しかし、これがどのように行われるかを見てくださいrepo そして読むhere 見出し「コードファースト」の下で

    概要
    今、私たちは新しいプロジェクトを生成し、スキーマを定義することを学び、スキーマから型を生成するためのレゾルバです.我々は本当に自分自身を誇りにする必要があります.