[Nest.js]1. 優先パラメータ、CRUD APIの作成


リファレンス
https://wikidocs.net/148195

NestJSはNodeです。jsベースのWeb APIフレームワーク、ExpressまたはFastinyフレームワークに基づく。


データベース接続、ORM、構成、テストなど、Web APIの作成に必要なさまざまな機能を提供します。


NestJSではアクセサリーをよく使います。


開発環境の構築


1. Nest.jsプロジェクトの作成

# @nestjs/cli 설치
sudo npm install -g @nestjs/cli
# NestJS 프로젝트 생성
nest new ${project-name}
プロジェクトは直接作成されません.
https://github.com/nestjs/typescript-starter
ウィリポギトリーを始めにする方法もあります.
(nest newコマンドで生成されたアイテムと比較して、最新のライブラリが含まれています.)

2.必要なモジュールのインストール


目的は簡単なGraphQL CRUD APIを作成するので、必要なライブラリをインストールできます(DBMSはPostgreSQLを使用します)
# typeorm
npm install typeorm
npm install @nestjs/typeorm
# graphql
npm install graphql
npm install graphql-upload
npm install @nestjs/graphql
# jwt
npm install @nestjs/jwt
npm install jsonwebtoken
# apollo-server
npm install apollo-server-express
npm install @nestjs/apollo';
# PostgreSQL
npm install pg
ライブラリのインストールが完了し、サーバの実行を開始します.
# npm
npm run start
# yarn
yarn start
デフォルトでは、NestJSは3000ポート、src/mainで実行されます.ts上で実行されるポートを変更できます.

CRUD APIの作成


1.リソースの作成


NestJSは、nest generateコマンドにより各種テンプレートを生成する機能を提供し、resourceオプションは、CRUD APIの作成に必要な基本テンプレートを作成するために使用される.
# User 관련 CRUD API를 작성하기 nest generate 명령어 사용
nest generate resource "User"

GraphQL APIを作成するため、どのテンプレートを作成するかを選択するコマンドを入力します.GraphQL(code first)を選択します.
(schema-first/code-first差異:https://yechoi.tistory.com/81)
nest generateコマンドで作成できるテンプレート


ユーザー関連のCRUD APIのフォルダ構造の作成が完了しました.
  • dto :
  • entity.ts :
  • module.ts :
  • resolver.ts :
  • service.ts :
  • 2.Entityの定義


    まずgenerateコマンドで作成したuser.entity.TSファイルでUser Entityを定義します.
    user.entity.TSを開くと、次のようなUserクラスが表示されます.@ObjectType DecoratorはGraphQLで使用されるタイプです.
    import { ObjectType, Field, Int } from '@nestjs/graphql';
    
    @ObjectType()
    export class User {
      @Field(() => Int, { description: 'Example field (placeholder)' })
      exampleField: number;
    }
    
    NestJSで生成されたEntityにコンテンツを追加します.
    import { Field, ObjectType } from '@nestjs/graphql';
    
    import {
      Column,
      CreateDateColumn,
      DeleteDateColumn,
      Entity,
      PrimaryGeneratedColumn,
      UpdateDateColumn,
    } from 'typeorm';
    @Entity()
    @ObjectType()
    export class User {
      @PrimaryGeneratedColumn('uuid')
      @Field(() => String)
      id: string;
    
      @Column({ type: 'varchar', length: '255', nullable: true })
      @Field(() => String)
      email: string;
    
      @Column({ type: 'varchar', length: '255' })
      password: string;
    
      @Column({ type: 'varchar', length: '50' })
      @Field(() => String)
      name: string;
    
      @DeleteDateColumn()
      deletdAt: Date;
    
      @CreateDateColumn()
      createdAt: Date;
    
      @UpdateDateColumn()
      updatedAt: Date;
    }
    まず、User EntityをDBのUserテーブルにマッピングするために、@Entityデータレコーダを追加し、必要なプロパティを入力します.@Columnデコーダの属性を使用してタイプOrmを介してDBのColumnにマッピングし、@Filedデコーダの属性を使用してGraphQLのタイプにマッピングする.@Entity@ColumnデータレコーダはType Ormライブラリから提供されるデータレコーダであり、Synchronizeオプションが有効になっている場合、サーバの実行時に自動的に同期されます.

    3.API、DTOの作成


    createUser APIを作成します.
    NestJSはDTOでデータを交換します.
    Entityと同様にgenerateコマンドを使用するとDTOが生成されます.
    この時点で作成したcreate-user DTOでは、パラメータを使用して渡す内容を記述します.
    // user/dto/create-user.input.ts
    import { InputType, Field } from '@nestjs/graphql';
    
    @InputType()
    export class CreateUserInput {
      @Field(() => String, { description: '유저 E-Mail' })
      email: string;
      @Field(() => String, { description: '비밀번호' })
      password: string;
      @Field(() => String, { description: '유저 이름' })
      name: string;
    }
    @InputTypeデータレコーダを使用すると、GraphQL APIでInputとして使用されるオブジェクトを作成できます.
    CreateUserInputが定義されている以上、CreateUserAPIを作成します.
    nest generateコマンドで作成したuser.service.tsにAPIロジックとuserを作成します.resolver.tsでマッピングします.
    (GraphQLでは解析器はコントローラのようです)
    user.resolver.ts
    import ...
    
    @Resolver(() => User)
    export class UserResolver {
      constructor(private readonly userService: UserService) {}
    
      @Mutation(() => User)
      createUser(@Args('createUserInput') createUserInput: CreateUserInput) {
        return this.userService.create(createUserInput);
      }
      
      @Query(() => [User], { name: 'user' })
      findAll() {
        return this.userService.findAll();
      }
      ...
    }
    自動生成された解析器.@Resolverデータレコーダを使用して解析器を作成し、@Query@Mutationデータレコーダを使用してQueryおよびMultiを定義できます.@Query@Mutationデコーダは、各APIの戻りタイプの関数をパラメータとして受信し、name、descriptionなどをオプションとして渡すことができる.
    (オプションとして名前が指定されていない場合、データレコーダを使用するメソッド名はAPIの名前になります.)
  • Query : GET
  • Mutation : PUT, POST, PATCH, DELETE
  • 簡単なCRUD APIを作成することを目的としているため、解析器はそのままサービスのために論理を記述します.
    // user/user.service.ts
    import ...
    
    @Injectable()
    export class UserService {
      constructor(
        @InjectRepository(User)
        private readonly userRepository: Repository<User>,
      ) {}
      ...
      
    }
    TypeORMはRepository設計モードをサポートする.
    各Entityには、@Injectableデータレコーダをサービスクラスで使用することも、@InjectRepositoryデータレコーダをサービスクラスの作成者で使用することも、save()データレコーダを使用して使用するEntityのRepositoryをロードすることもできます.
    // user/user.service.ts
    import ...
    
    @Injectable()
    export class UserService {
      constructor(
        @InjectRepository(User)
        private readonly userRepository: Repository<User>,
      ) {}
      
      async create(createUserInput: CreateUserInput) {
        return await this.userRepository.save({
          ...createUserInput,
        });
      }
      
      ...
      
    }
    DTOを介して渡されたパラメータは、ユーザレポートのsave()メソッドを使用してデータベースに保存されます.
    TypeOrmのレポートは、remove()softRemove()upsert()など、さまざまな方法をサポートしています.複雑なSQLはqueryBuilderで実行できます.
    //モジュール

    サーバーの実行とテスト


    前に作成したEntityがデータベースに反映されているか、APIが正常に動作しているかを確認します.
    /src/app.module.tsファイルを表示すると、プロジェクトの最上位モジュールAppModuleが宣言され、UserModuleがインポートされていることがわかります.
    (generateコマンドで作成したモジュールは自動的にインポートされます.)
    UserModuleで、Apollo-Serverを実行するためのグラフィックQLModuleとType Orm連動用のType OrmModuleを追加します.

    1. GraphQLModule

    @Module({
      imports: [
        UserModule,
        GraphQLModule.forRoot({
          driver: ApolloDriver,
          autoSchemaFile: 'src/common/graphql/schema.gql',
          context: ({ req, res }) => ({ req, res }),
        }),
      ],
    })
    export class AppModule {}
    AutoSchemaFileオプションのパスが指定されている場合、code-first方式で作成されたGraphQLのtypeDefsが自動的に作成されます.

    2. TypeOrmModule

    
    @Module({
      imports: [
        UserModule,
        GraphQLModule.forRoot({
          driver: ApolloDriver,
          autoSchemaFile: 'src/common/graphql/schema.gql',
          context: ({ req, res }) => ({ req, res }),
        }),
        TypeOrmModule.forRoot({
          type: 'postgres',
          port: 5433,
          database: 'gchoi',
          username: 'gchoi',
          password: '1234',
          host: '127.0.0.1',
          entities: [__dirname + '/**/*.entity.*'],
          synchronize: true,
          logging: true,
        }),
      ],
    })
    export class AppModule {}
    APIを接続するDBの接続情報をオブジェクトに渡す.
    Synchronizeオプションが有効になっている場合は、Entityの内容を変更するとDBに反映されます.ログオプションが有効になっている場合は、各SQLのログを表示できます.
    GraphQLModuleとTypeOrmModuleを追加し、サーバを実行して結果を表示します.
    # 실행
    npm run start:dev
    yarn start:dev

    サーバーは正常に動作しています.
    データベースを見ると.

    テーブルが正常に作成されていることを確認します.
    ブラウザでlocalhost:3000/graphqlに接続します.

    GraphQLサーバが正常に動作していることがわかります.
    作成したcreateUser APIを使用してみましょう

    正常に戻る.

    データベースのデータもいいです.
    終わります.
    次の記事では、join、queryBuilder、accessToken、refreshToken、アップロードファイルについて説明します.