本篇文章将会讲解 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