Nest.jsでGraphQL APIを構築するには?

この記事では、NestJSのクリーンなアーキテクチャと型安全性を利用して、NestJSでGraphQL APIを構築する方法を学びます。

NestJSは、型安全性と厳格なアーキテクチャパターンを提供することで、スケーラブルなエンタープライズグレードのバックエンドアプリケーションの作成を支援するNodeJSフレームワークです。

GraphQLはアプリケーション・プログラミング・インターフェース(API)のためのクエリ言語で、RESTに代わるものとして広く使用されています。その速度と安定性により、クエリに対して要求されたデータを正確に応答することで実現されています。このGraphQL機能は、RESTが抱えるオーバーフェッチとアンダーフェッチの問題を解決します。

開発環境のセットアップ

Nest.js CLIがシステムにグローバルにインストールされていない場合は、以下のコマンドを実行してインストールしてください:

npm i -g @nestjs/cli

Nest.js CLIには、開発プロセスを容易にするための定型コードを生成するためのコマンドがいくつかあります。

次に、以下のコマンドを実行してプロジェクトを作成し、必要なスターター・ファイルを生成する:

nest new graphql-api

次に、以下のコマンドを実行してプロジェクト・ディレクトリにcdする:

cd graphql-api

次に、以下のコマンドを実行して、必要な依存関係をインストールする:

npm i @nestjs/graphql @nestjs/apollo graphql apollo-server-express

上記でインストールされた依存関係は以下の通り:

  • nest/graphql
  • nestjs/apollo
  • graphql
  • apollo-server-express

次に、以下のコマンドを実行し、TypeORMパッケージとsqliteデータベースドライバをインストールします:

npm install @nestjs/typeorm typeorm sqlite3

データベースへの接続、読み込み、書き込みを行うには、上記でインストールしたパッケージが必要です。

Nest.jsでGraphQLを設定する

Nest.jsは、GraphQL APIを作成する方法として、コードファーストとスキーマファーストの2つを提供している。

コードファーストのアプローチでは、TypeScriptのデコレーターとクラスを使用して、対応するGraphQLスキーマを生成する。

スキーマファーストのアプローチでは、GraphQL Schema Definition Language(SDL)ファイルを使用し、Nest.jsはGraphQL Schemaに基づくクラスまたはインターフェイスを使用してTypeScript定義を生成します。

このチュートリアルでは、異なる言語間でのコンテキストの切り替えを避けるために、コード・ファースト・アプローチを使用することを特徴とする。

コードファーストのアプローチを使用するには、アプリケーションのエントリーファイルであるapp.module.tsに移動し、@nestjs/graphqlから GraphQLModuleをインポートします。このように:

import { GraphQLModule } from '@nestjs/graphql';

次に、imports配列でGraphQLModuleの forRootメソッドを呼び出します。このメソッドは引数として設定オブジェクトを取ります。設定オプションは、基礎となるGraphQLドライバを介して渡されます(このチュートリアルでは、Apolloドライバを使用します)。設定オブジェクトのautoSchemaFileプロパティをschema.gqlに設定します。このように:

//app.module.ts
GraphQLModule.forRoot({ autoSchemaFile: 'schema.gql' }),

autoSchemaFileプロパティは、自動生成されたスキーマが保存されるファイルパスです。

データベースへの接続

アプリケーションをデータベースに接続するには、app.module.tsファイルに移動し、@nestjs/typeorm からTypeOrmModule をインポートします。

こんな感じだ:

import { TypeOrmModule } from '@nestjs/typeorm';

次に、以下のコードブロックをimports配列に追加する:

TypeOrmModule.forRoot({
      type: 'sqlite',
      database: ':memory:',
      entities: ['dist/**/*.entity{.ts,.js}'],
      synchronize: true,
    }),

上記のコードブロックは、アプリケーションとSqliteデータベースとの間にデータベース接続を作成し、アプリケーション内のすべてのモジュールでその接続を共有します。

リソースの生成

次に、以下のコマンドを実行して、コードを整理するためのモジュールを作成する:

nest g module blog

上記のコマンドは、アプリケーション用のブログ・モジュールを生成する。

次に、以下のコマンドを実行してサービスを作成する:

nest g service blog

上記のコード・ブロックは、アプリケーションにサービスを生成して登録します。このサービスには、アプリケーションのすべてのビジネスロジックが含まれ、処理されます。

次に、以下のコマンドを実行してリゾルバを作成する:

nest g resolver

上記のコードブロックは、リゾルバを生成してアプリケーションに登録します。リゾルバは、GraphQLクエリーと変異をデータに変換する命令を指定し、スキーマで指定されたデータの形状を同期または非同期で返します。

エンティティの作成

エンティティとは、データベースにデータがどのように格納されるかを指定するフィールドの集まりである。

Entityを作成するには、モジュールフォルダ(blog)に、.entity.tsの規約に従ってEntityファイルを作成します(例:blog.entity.ts)。

エンティティファイルに、typeormから ColumnEntityPrimaryGeneratedColumnをインポートします。このように:

import { Column, Entity, PrimaryGeneratedColumn } from 'typeorm';

Columnデコレータは、アノテーションしたフィールドをデータベースのカラムとして追加します。Entityデコレータは、アノテーションするクラスをエンティティとしてマークします。PrimaryGeneratedColumnデコレータは、 アノテーションしたプロパティをテーブルの一意な識別子としてマークし、 それを自動的に生成します。

次に、Blog というクラスを作成してエクスポートする。そして、このクラスをエンティティとしてマークするために、Entityデコレーターでアノテーションする。このように:

@Entity()
export class Blog {}

このチュートリアルではブログAPIを使用するので、クラスにid、title、body、author、dateプロパティを追加します。そして、idプロパティを除く各プロパティにColumnデコレーターをアノテーションします。idプロパティにPrimaryGeneratedColumnデコレータをアノテーションします。

こんな感じだ:

import { Column, Entity, PrimaryGeneratedColumn } from 'typeorm';

@Entity()
export class Blog {
  @PrimaryGeneratedColumn()
  id: number;

  @Column()
  title: string;

  @Column()
  body: string;

  @Column()
  author: string;

  @Column()
  date: string;
}

オブジェクト・タイプの作成

オブジェクトタイプは、クライアントが対話する必要があるオブジェクトを表すGraphQLスキーマ定義です。例えば、ブログAPIを構築する場合、ブログのスキーマ/エンティティをTypeScriptクラスで定義し、各フィールドに適切なデコレーターをアノテーションする必要があります。

次に、エンティティファイルで、@nestjs/graphqlから Int型とFieldと ObjectTypeデコレータをインポートします。このようにします:

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

Fieldデコレーターは、特定のクラスのプロパティーを GraphQL フィールドとしてマークします。このデコレーターでアノテーションされたプロパティのみがスキーマで定義されます。オプションの戻り値型関数と設定オブジェクトを引数として受け取ります。

Int型は、TypeScriptとGraphQLの型システムの間の潜在的な曖昧さを解消するために必要です。これは、整数または浮動小数点数の値を持つプロパティにのみ必要です。

ObjectTypeデコレーターは、クラスをGraphQL型としてマークします。

次に、BlogクラスをObjectTypeデコレーターでアノテーションし、GraphQLタイプとしてマークします。次のように:

@ObjectType()
export class Blog {}

最後に、型の必須プロパティをクラス内部で指定し、それぞれにFieldデコレーターのアノテーションを付けます。例えば

//blog.entity.ts
import { Field, Int, ObjectType } from '@nestjs/graphql';
import { Column, Entity, PrimaryGeneratedColumn } from 'typeorm';

@Entity()
@ObjectType()
export class Blog {
  @PrimaryGeneratedColumn()
  @Field((type) => Int)
  id: number;

  @Column()
  @Field()
  title: string;

  @Column()
  @Field()
  body: string;

  @Column()
  @Field()
  author: string;

  @Column()
  @Field()
  date: string;
}

完成したオブジェクト・タイプは、上のコード・ブロックのようになるはずだ。

上のコードブロックでは、TypeScriptとGraphQLの型システムのあいまいさを避けるために、数値型のidが明示的に整数として指定されていることに注目してほしい。

最後に、Entityをアプリケーションに注入して、アプリケーションとデータベースの間にアクセスレイヤーを作成します。

これを実現するには、blog.module.tsファイルに移動し、@nestjs/typeorm からTypeOrmModule をインポートし、Blog エンティティをインポートします。

次に、以下のコード・ブロックをモジュール・デコレーターに追加します:

imports: [TypeOrmModule.forFeature([Blog])],

上のコードブロックは、アプリケーションとデータベースの間のアクセスレイヤーとして機能するリポジトリを作成する。

サービスの作成

先に生成したサービスファイルblog.service.tsに移動し、@nestjs/typeormから InjectRepositoryとオブジェクトタイプをインポートします。

こんな感じだ:

import { InjectRepository } from '@nestjs/typeorm';
import { Blog } from './blog.entity';

次に、以下のコードブロックをBlogServiceクラスに追加して、リポジトリをインジェクトします:

constructor(
    @InjectRepository(Blog)
    private blogRepository: Repository<Blog>,
  ) {}

次に、以下のコードブロックをサービスクラスに追加し、データベース内のすべてのブログを検索するロジックを実装します:

async getAll(): Promise<Blog[]> {
    return await this.blogRepository.find();
  }

次に、新しいブログをデータベースに追加するロジックを実装する必要がありますが、その前にInput Typeを作成する必要があります。

入力タイプを作成する

複雑なオブジェクトを受け取る突然変異の入力タイプを作成するには、ブログ・フォルダーに dtosフォルダーを作成してください。次に、dtosフォルダ内に、新しいファイルcreate-blog.input.tsを作成します。

create-blog.input.tsファイルで、FieldデコレーターとInputTypeデコレーターをインポートします。このように:

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

InputTypeデコレーターは、クラスを GraphQL 入力タイプとしてマークします。

次に、BlogInputクラスを作成し、エクスポートする。そして、そのクラスにInputTypeデコレーターをアノテーションする。次のように:

@InputType()
export class BlogInput {}

最後に、必要なブログ・プロパティをすべて追加し、フィールド・デコレーターでアノテーションします。

こんな感じだ:

//create-blog.input.ts
import { Field, InputType } from '@nestjs/graphql';

@InputType()
export class BlogInput {
  @Field()
  id: number;

  @Field()
  title: string;

  @Field()
  body: string;

  @Field()
  author: string;

  @Field()
  date: string;
}

完成した入力タイプは、上のコードブロックのようになるはずだ。

次に、入力タイプをサービスファイルにインポートし、以下のコードブロックをサービスクラスに追加して、データベースにブログを追加するロジックを実装します:

async createBlog(blogInput: BlogInput): Promise<Blog> {
    const newBlog = this.blogRepository.create(blogInput);

    return this.blogRepository.save(newBlog);
  }

入力タイプは、通常のNest.jsデータ転送オブジェクトが適用されるのと同じように、入力データの検証メカニズムとして適用されます。dtosのように、class-validatorパッケージを使用してデータに対して追加の検証を実行することもできます。

リゾルバの作成

先に生成したResolverファイルblog.resolver.tsに移動し、エンティティ、入力タイプ、サービスをインポートします。このように:

import { Blog } from './blog.entity';
import { BlogService } from './blog.service';
import { BlogInput } from './dto/create-blog.input';

次に、以下のコードブロックをリゾルバクラスに追加して、 サービスをリゾルバに注入します:

constructor(private blogService: BlogService) {}

次に、@nestjs/graphqlから ArgsMutationQueryデコレータをインポートします。

こんな感じだ:

import { Args, Mutation, Query } from '@nestjs/graphql';

Argsデコレーターは、基本プラットフォームから arguments オブジェクトを取り出し、すべての引数あるいは指定した引数の値をデコレートしたパラメーターに設定します。

Mutationデコレーターは、ルートを変異として指定します。

Queryデコレータはルートをクエリとして指定します。

次に、以下の関数をResolverデコレーターに渡してオブジェクトの型を指定します:

(of) => Blog

次に、getAllメソッドを解決するために、以下のコードブロックをResolverクラスに追加します。

 @Query((type) => [Blog])
  async getAllBlogs() {
    return this.blogService.getAll();
  }

最後に、以下のコード・ブロックをResolverクラスに追加して、createBlogメソッドを解決します。

 @Mutation((returns) => Blog)
  createBlog(@Args('blogInput') blogInput: BlogInput): Promise<Blog> {
    return this.blogService.createBlog(blogInput);
  }

注意:各デコレーターの戻り値の型関数を必ず指定してください。

完成したResolverクラスは、以下のコード・ブロックのようになるはずです:

@Resolver((of) => Blog)
export class BlogResolver {
  constructor(private blogService: BlogService) {}

  @Query((type) => [Blog])
  async getAllBlogs() {
    return this.blogService.getAll();
  }

  @Mutation((returns) => Blog)
  createBlog(@Args('blogInput') blogInput: BlogInput): Promise<Blog> {
    return this.blogService.createBlog(blogInput);
  }
}

GraphQL Playgroundを使用してAPIをテストする

デフォルトで利用可能なGraphQLプレイグラウンドを使用してアプリケーションをテストするには、以下のコマンドを実行し、http://localhost:3000/graphql。

npm start

次に、下の画像に示すように、クエリーと突然変異をテストできるプレイグラウンドが表示されるはずだ。

GraphQLプレイグラウンド

データベースからすべてのブログを取得するには、以下のクエリを実行します:

query getAll{
  getAllBlogs {
    id,
    title,
    body,
    author,
    date
  }
}

例を下の画像に示す:

データベースにブログを追加するには、以下の変異を実行する:

mutation createBlog {
  createBlog (blogInput: {
    id: 1, 
    title: "GraphQL is great", 
    body: "GraphQL APIs are faster than REST APIs", 
    author: "David Ekete",
    date: "01-02-03"
  }) {
    id,
    title,
    body,
    author,
    date,
  }
}

例を下の画像に示す:

GraphQLプレイグラウンド

Back4appとGraphQL

データ取得制御など、GraphQL には REST よりも多くの利点があるため、Back4app プラットフォームでは、プラットフォーム上で実行される解析アプリケーションに統合された GraphQL API を提供しています。

この統合により、簡単なGraphQLクエリや変異を書くだけで、サーバーのバックエンドの健全性をチェックしたり、データベース上でCRUD(Create、Read、Update、Delete)操作を実行したり、その他多くのことができるようになります。

例えば、GraphQL APIを使用してバックエンドサーバーの健全性を確認するには、以下のクエリーを実行します:

query Health {
  health
}

上のクエリーはこう返す:

{
  "data": {
    "health": true
  }
}

GraphQL 機能を開始するには、Parse ダッシュボードに移動し、アプリを選択してクリックします。アプリの UI で[Core]を選択してクリックし、[API console]を選択してクリックし、[GraphQL console]を選択します。

上記の指示に従うと、GraphQLコンソールが開き、開発で使用したGraphQLプレイグラウンドと同様のクエリやミューテーションを実行することができます。Back4appのGraphQL機能については、Back4appのドキュメントを参照してください。

結論

この記事では、Nest.jsでGraphQL APIを作成し、GraphQL playgroundを使ってAPIをテストする方法を取り上げた。GraphQL APIには、REST APIに比べていくつかの利点があります。

しかし、これらはすべてのアプリケーションに理想的というわけではありません。GraphQLとRESTの長所と短所を考慮した上で、どちらがあなたのアプリケーションに適しているかを選ぶようにしてください。

GraphQLやRESTの選択に関わらず、アプリケーションをデプロイする必要があります。Back4appはオープンソースの技術をベースにしたローコードBaaSで、再利用可能なテンプレートを使って繰り返しの作業をなくし、バックエンドのインフラストラクチャの大部分を管理することで、バックエンド構築のプロセスを簡素化します。

Back4appの特徴には、リアルタイムデータベース、クラウド機能、ネイティブAPIとSDK、完全なユーザー管理システムなどがあります。

このプラットフォームには、料金を支払うことなくプラットフォームを探索できる無料ティアもある。

ハッピービルディング

よくあるご質問

GraphQL とは何ですか?

GraphQL は、2012 年に Facebook によって作成された、API 用のオープンソースのデータ クエリおよび操作言語です。

Nest.JS とは何ですか?

Nest.JS は、効率的でスケーラブルなサーバー側アプリケーションを構築するためのオープンソースの Node.js フレームワークです。

Nest.JS を使用して GraphQL API を作成する方法は?

– Nest.js で GraphQL を構成する
– データベースに接続する
– リソースを生成する
– エンティティを作成する
– オブジェクト タイプを作成する
– サービスを作成する


Leave a reply

Your email address will not be published.