Please enable Javascript to view the contents

1-NestJs+GraphQl-安装与最简实例

 ·  ☕ 5 分钟

本篇文章将会讲解 NestJs+GraphQl 的安装部署,最后会实现一个最简实例

安装 Nest

npm i -g @nestjs/cli

创建与运行 Nest 应用

nest g application
填写你的 app 名,完成后进入对应的 app 文件夹,运行npm i安装依赖

npm run start:dev 就可以运行应用了,在 127.0.0.1:3000 可以看到

安装 GraphQl

事实上 NestJs 中有 GraphQl 的相关模块,https://docs.nestjs.com/graphql/quick-start

运行官网的安装命令
$ npm i @nestjs/graphql @nestjs/apollo graphql apollo-server-express

删除项目不必要内容

src/main.ts 是项目启动的根文件,其中引用了 AppModule
所有东西都是在 AppModule 中引入的

项目 generate 后 app.module.ts 中已经有了对应的文件,我们先删除这些文件和@Module 中的引用

import { Module } from '@nestjs/common';

@Module({
  import: [],
  controller: [],
  providers: []
})

现在我们需要使用 GraphQl 这个 module,很显然需要在 AppModule 中引入,于是我们在@Module 的 import 中导入

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

@Module({
  import: [
    GraphQLModule.forRoot({
      autoSchemaFile: true, // 用ts自动生成Schema文件
    })
  ],
  controller: [],
  providers: []
})

生成第一个模块

我们生成一个叫restaurant的模块,g mo 是generate module的简写。

nest g mo restaurants

在 AppModule 中导入 restaurants 的 module

import { Module } from '@nestjs/common';
import { GraphQLModule } from '@nestjs/graphql';
import { RestaurantsModule } from './restaurants/restaurants.module';

@Module({
  import: [
    GraphQLModule.forRoot({
      autoSchemaFile: true, // 用ts自动生成Schema文件
    })
    RestaurantsModule,
  ],
  controller: [],
  providers: []
})

编写 Restaurants 模块

restaurants.module.ts

import { Module } from '@nestjs/common';
import { RestaurantResolver } from './restaurants.resolver';

@Module({
  providers: [RestaurantResolver],
})
export class RestaurantsModule {}

restaurants.resolver.ts

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

@Resolver()
export class RestaurantsResolver {
  // 这里将会记录数据增删改查的方法

  @Query(returns => Boolean)
  isAuth() {
    return true;
  }
}

至此就可以解决 GraphQl 没有 shema 的报错了(GraphQL 有自己的类型系统,该系统用于定义 API 的 schema。编写 schema 的语法称为模式定义语言,即 Schema Definition Language,SDL)

使用 ObjectType

ObjectType from @nestjs/graphql 可以让我们使用 ts 来编写 GraphQl
在 restaurant module 下创建 entities/restaurant.entity.ts

entity 对应的就是数据库中的 module,ObjectType 会创建一个 restaurant 的数据表对象

entities/restaurant.entity.ts

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

@ObjectType()
export class Restaurant {
  @Field((type) => String) // Field需要返回一个returnTypeFunction GraphQL 数据类型
  name: string; // 字段ts数据类型

  @Field((type) => Boolean, { nullable: true }) // 非必填时用nullable
  isVegan?: boolean;

  @Field((type) => String)
  address: string;

  @Field((type) => String)
  ownerName: string;
}

编写 Restaurant 的 Query 方法

import { Args, Query, Resolver } from '@nestjs/graphql';
import { CreateRestaurantDto } from './dtos/create-restaurant.dto';
import { Restaurant } from './entities/restaurant.entity';

@Resolver((of) => Restaurant) // Restaurant entity 的解析库(保存增删改查的地方)
export class RestaurantResolver {
  @Query((returns) => [Restaurant])
  // 这里查询的入参是veganOnly是否为素食餐厅,同样需要GraphQl的装饰器Args
  restaurants(
    @Args('veganOnly')
    veganOnly: boolean
  ): Restaurant[] {
    return [];
  }
}

在 127.0.0.1:3000/graphql 中可以看到 GraphQl 的数据操作台

编写 Restaurant 的 Create 方法

方法1

restaurants.resolver.ts

import { Args, Mutation, Query, Resolver } from '@nestjs/graphql';
import { CreateRestaurantDto } from './dtos/create-restaurant.dto';
import { Restaurant } from './entities/restaurant.entity';

@Resolver((of) => Restaurant) // Restaurant entity 的解析器
export class RestaurantResolver {
  @Query((returns) => [Restaurant])
  // 这里查询的入参是veganOnly是否为素食餐厅,同样需要GraphQl的装饰器Args
  restaurants(
    @Args('veganOnly')
    veganOnly: boolean
  ): Restaurant[] {
    return [];
  }

  // 方法1: 入参为create一个restaurant所需的所有字段
  @Mutation((returns) => Boolean)
  createRestaurant1(
    @Args('name') name: string,
    @Args('isVegan') isVegan: boolean,
    @Args('address') address: string,
    @Args('ownerName') ownerName: string,
  ): boolean {
    return true;
  }
}

方法2

可以使用inputType来传递一个完整的对象,对象包含create restaurant所需的所有字段
这个对象是一种dto(data transfer object)
在restaurants module下创建文件夹dtos/create-restaurant.dto.ts

src/restaurants/dtos/create-restaurant.dto.ts

@InputType()
export class CreateRestaurantDto {
  @Field(type => String)
  name: string;
  @Field(type => Boolean)
  isVegan: boolean;
  @Field(type => String)
  address: string;
  @Field(type => String)
  ownerName: string;
}

src/restaurants/restaurants.resolver.ts

import { Args, Mutation, Query, Resolver } from '@nestjs/graphql';
import { CreateRestaurantDto } from './dtos/create-restaurant.dto';
import { Restaurant } from './entities/restaurant.entity';

@Resolver((of) => Restaurant) // Restaurant entity 的解析器
export class RestaurantResolver {
  @Query((returns) => [Restaurant])
  // 这里查询的入参是veganOnly是否为素食餐厅,同样需要GraphQl的装饰器Args
  restaurants(
    @Args('veganOnly')
    veganOnly: boolean
  ): Restaurant[] {
    return [];
  }

  @Mutation((returns) => Boolean)
  createRestaurant(
    @Args('createRestaurantInput') 
    createRestaurantInput: CreateRestaurantDto // 直接使用InputType类型
  ): boolean {
    return true;
  }
}

方法3

InputType 在实际使用的时候还需要使用键名,InputType把一个对象(需要的值包含在对象中)传递给GraphQl

mutation {
  createRestaurant(createRestaurantInput: {
    name: 'Llane-eats',
    isVegan: false,
    address: 'Shanghai';
    ownerName: 'Llane zhang'
  })
}

如果使用ArgsType可以再简化,ArgsType可以把单独的多个值传递给GraphQl

src/restaurants/dtos/create-restaurant.dto.ts

@ArgsType()
export class CreateRestaurantDto {
  @Field(type => String)
  name: string;
  @Field(type => Boolean)
  isVegan: boolean;
  @Field(type => String)
  address: string;
  @Field(type => String)
  ownerName: string;
}

src/restaurants/restaurants.resolver.ts

import { Args, Mutation, Query, Resolver } from '@nestjs/graphql';
import { CreateRestaurantDto } from './dtos/create-restaurant.dto';
import { Restaurant } from './entities/restaurant.entity';

@Resolver((of) => Restaurant) // Restaurant entity 的解析器
export class RestaurantResolver {
  @Query((returns) => [Restaurant])
  // 这里查询的入参是veganOnly是否为素食餐厅,同样需要GraphQl的装饰器Args
  restaurants(
    @Args('veganOnly')
    veganOnly: boolean
  ): Restaurant[] {
    return [];
  }

  @Mutation((returns) => Boolean)
  createRestaurant(
    @Args() 
    createRestaurantDto: CreateRestaurantDto // 直接使用InputType类型
  ): boolean {
    return true;
  }
}

此时mutation可以不用写key值了

mutation {
  createRestaurant(
    name: 'Llane-eats',
    isVegan: false,
    address: 'Shanghai';
    ownerName: 'Llane zhang'
  )
}

安装class-validator

class-validator 可以让我们用类装饰器的方式来对字段做进一步的验证
比如可以限制name为5-10个字符串

安装

npm i class-validator class-transformer

创建application validation pipeline

main.ts

import { ValidationPipe } from '@nestjs/common';
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';

async function bootstrap() {
  const app = await NestFactory.create(AppModule);
  app.useGlobalPipes(new ValidationPipe()); // 创建validation pipeline
  await app.listen(3000);
}
bootstrap();

使用 class-validator

src/restaurants/dtos/create-restaurant.dto.ts

@ArgsType()
export class CreateRestaurantDto {
  @Field(type => String)
  @IsString() // 是字符串类型
  @Length(5, 10) // 长度5-10
  name: string;
  
  @Field(type => Boolean)
  @IsBoolean() // 是boolean类型
  isVegan: boolean;
  
  @Field(type => String)
  @IsString()
  address: string;
  
  @Field(type => String)
  @IsString()
  @Length(5, 10)
  ownerName: string;
}

此时如果mutation 执行createRestaurant时参数不符合标准就会报错

安装PostgreSQL

直接去官网下载安装包,不太建议新手用brew install之类的安装

和mysql,sql server一样PostgreSQL也有类似的可视化操作软件
windows 用户推荐 pgAdmin
mac 用户推荐 postico

这里记录一些实用的命令

// 列出所有用户
\du;

// 改变指定用户的密码
ALTER USER '制定的用户名' WITH PASSWORD '新密码';

使用连接PostgreSQL

NestJS有一个叫TypeORM的集成,可以用来连接数据库
@nestjs/typeorm
官网教程

npm install --save @nestjs/typeorm typeorm pg
分享

Llane00
作者
Llane00
Web Developer