Skip to content

Commit f30abc2

Browse files
committed
update
1 parent 069fc66 commit f30abc2

File tree

3 files changed

+75
-40
lines changed

3 files changed

+75
-40
lines changed

.prettierignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# Add files here to ignore them from prettier formatting
2+
3+
/dist

.prettierrc

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
{
2+
"singleQuote": true,
3+
"printWidth": 120,
4+
"overrides": [
5+
{
6+
"files": "*.html",
7+
"options": {
8+
"printWidth": 10000
9+
}
10+
}
11+
]
12+
}

6/pipes.md

Lines changed: 60 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
> validation.pipe.ts
2727
2828
```typescript
29-
import { PipeTransform, Injectable, ArgumentMetadata } from "@nestjs/common";
29+
import { PipeTransform, Injectable, ArgumentMetadata } from '@nestjs/common';
3030

3131
@Injectable()
3232
export class ValidationPipe implements PipeTransform {
@@ -47,7 +47,7 @@ export class ValidationPipe implements PipeTransform {
4747

4848
```typescript
4949
export interface ArgumentMetadata {
50-
readonly type: "body" | "query" | "param" | "custom";
50+
readonly type: 'body' | 'query' | 'param' | 'custom';
5151
readonly metatype?: Type<any>;
5252
readonly data?: string;
5353
}
@@ -109,12 +109,7 @@ $ npm install --save-dev @types/hapi__joi
109109
在下一节中,你将看到我们如何使用 `@UsePipes()` 修饰器给指定的控制器方法提供需要的 schema.
110110

111111
```typescript
112-
import {
113-
PipeTransform,
114-
Injectable,
115-
ArgumentMetadata,
116-
BadRequestException
117-
} from "@nestjs/common";
112+
import { PipeTransform, Injectable, ArgumentMetadata, BadRequestException } from '@nestjs/common';
118113

119114
@Injectable()
120115
export class JoiValidationPipe implements PipeTransform {
@@ -123,7 +118,7 @@ export class JoiValidationPipe implements PipeTransform {
123118
transform(value: any, metadata: ArgumentMetadata) {
124119
const { error } = this.schema.validate(value);
125120
if (error) {
126-
throw new BadRequestException("Validation failed");
121+
throw new BadRequestException('Validation failed');
127122
}
128123
return value;
129124
}
@@ -157,7 +152,7 @@ $ npm i --save class-validator class-transformer
157152
> create-cat.dto.ts
158153
159154
```typescript
160-
import { IsString, IsInt } from "class-validator";
155+
import { IsString, IsInt } from 'class-validator';
161156

162157
export class CreateCatDto {
163158
@IsString()
@@ -178,14 +173,9 @@ export class CreateCatDto {
178173
> validation.pipe.ts
179174
180175
```typescript
181-
import {
182-
PipeTransform,
183-
Injectable,
184-
ArgumentMetadata,
185-
BadRequestException
186-
} from "@nestjs/common";
187-
import { validate } from "class-validator";
188-
import { plainToClass } from "class-transformer";
176+
import { PipeTransform, Injectable, ArgumentMetadata, BadRequestException } from '@nestjs/common';
177+
import { validate } from 'class-validator';
178+
import { plainToClass } from 'class-transformer';
189179

190180
@Injectable()
191181
export class ValidationPipe implements PipeTransform<any> {
@@ -196,7 +186,7 @@ export class ValidationPipe implements PipeTransform<any> {
196186
const object = plainToClass(metatype, value);
197187
const errors = await validate(object);
198188
if (errors.length > 0) {
199-
throw new BadRequestException("Validation failed");
189+
throw new BadRequestException('Validation failed');
200190
}
201191
return value;
202192
}
@@ -208,9 +198,19 @@ export class ValidationPipe implements PipeTransform<any> {
208198
}
209199
```
210200

211-
?> 我们已经使用了[class-transformer](https://github.com/pleerock/class-transformer) 库。它和 [class-validator](https://github.com/pleerock/class-validator) 库由同一个作者开发,所以他们配合的很好。
201+
?>我们已经使用了[class-transformer](https://github.com/pleerock/class-transformer) 库。它和 [class-validator](https://github.com/pleerock/class-validator) 库由同一个作者开发,所以他们配合的很好。
212202

213-
我们来看看这个代码。首先,请注意 `transform()` 函数是 `异步` 的。这是可能的,因为 Nest 支持**同步****异步**管道。我们这样做的原因是因为有些 `class-validator` 的验证是[可以异步的](typestack/class-validator#custom-validation-classes)(Promise)
203+
我们来看看这个代码。首先你会发现 `transform()` 函数是 `异步` 的, Nest 支持**同步****异步**管道。这样做的原因是因为有些 `class-validator` 的验证是[可以异步的](typestack/class-validator#custom-validation-classes)(Promise)
204+
205+
Next note that we are using destructuring to extract the metatype field (extracting just this member from an ArgumentMetadata) into our metatype parameter. This is just shorthand for getting the full ArgumentMetadata and then having an additional statement to assign the metatype variable.
206+
207+
Next, note the helper function toValidate(). It's responsible for bypassing the validation step when the current argument being processed is a native JavaScript type (these can't have schemas attached, so there's no reason to run them through the validation step).
208+
209+
Next, we use the class-transformer function plainToClass() to transform our plain JavaScript argument object into a typed object so that we can apply validation. The incoming body, when deserialized from the network request, does not have any type information. Class-validator needs to use the validation decorators we defined for our DTO earlier, so we need to perform this transformation.
210+
211+
Finally, as noted earlier, since this is a validation pipe it either returns the value unchanged, or throws an exception.
212+
213+
The last step is to bind the ValidationPipe. Pipes, similar to exception filters, can be method-scoped, controller-scoped, or global-scoped. Additionally, a pipe can be param-scoped. In the example below, we'll directly tie the pipe instance to the route param @Body() decorator.
214214

215215
最后一步是设置 `ValidationPipe` 。管道,与[异常过滤器](exceptionfilters.md)相同,它们可以是方法范围的、控制器范围的和全局范围的。另外,管道可以是参数范围的。我们可以直接将管道实例绑定到路由参数装饰器,例如`@Body()`。让我们来看看下面的例子:
216216

@@ -237,7 +237,7 @@ async create(@Body() createCatDto: CreateCatDto) {
237237

238238
?> `@UsePipes()` 修饰器是从 `@nestjs/common` 包中导入的。
239239

240-
`ValidationPipe` 的实例已就地立即创建。另一种可用的方法是直接传入类(而不是实例),让框架承担实例化责任,并启用**依赖注入**
240+
在上面的例子中 `ValidationPipe` 的实例已就地立即创建。另一种可用的方法是直接传入类(而不是实例),让框架承担实例化责任,并启用**依赖注入**
241241

242242
> cats.controler.ts
243243
@@ -255,35 +255,35 @@ async create(@Body() createCatDto: CreateCatDto) {
255255
256256
```typescript
257257
async function bootstrap() {
258-
const app = await NestFactory.create(ApplicationModule);
258+
const app = await NestFactory.create(AppModule);
259259
app.useGlobalPipes(new ValidationPipe());
260260
await app.listen(3000);
261261
}
262262
bootstrap();
263263
```
264264

265-
!> `useGlobalPipes()` 方法不会为网关和微服务设置管道(正在使用混合应用程序功能)
265+
!> [混合应用](6/faq?id=混合应用)`useGlobalPipes()` 方法不会为网关和微服务设置管道, 对于标准(非混合) 微服务应用使用 `useGlobalPipes()` 全局设置管道
266266

267267
全局管道用于整个应用程序、每个控制器和每个路由处理程序。就依赖注入而言,从任何模块外部注册的全局管道(如上例所示)无法注入依赖,因为它们不属于任何模块。为了解决这个问题,可以使用以下构造直接为任何模块设置管道:
268268

269269
> app.module.ts
270270
271271
```typescript
272-
import { Module } from "@nestjs/common";
273-
import { APP_PIPE } from "@nestjs/core";
272+
import { Module } from '@nestjs/common';
273+
import { APP_PIPE } from '@nestjs/core';
274274

275275
@Module({
276276
providers: [
277277
{
278278
provide: APP_PIPE,
279-
useClass: CustomGlobalPipe
279+
useClass: ValidationPipe
280280
}
281281
]
282282
})
283-
export class ApplicationModule {}
283+
export class AppModule {}
284284
```
285285

286-
?> 译者注: 上述 6.0 官方的示例代码目前是错误的,我们使用了 5.0 的示例代码。
286+
?> When using this approach to perform dependency injection for the pipe, note that regardless of the module where this construction is employed, the pipe is, in fact, global. Where should this be done? Choose the module where the pipe (ValidationPipe in the example above) is defined. Also, useClass is not the only way of dealing with custom provider registration. Learn more here.
287287

288288
?> 另一种选择是使用[执行上下文](5.0/executioncontext)功能。另外,useClass 并不是处理自定义提供者注册的唯一方法。在[这里](5.0/fundamentals?id=custom-providers)了解更多。
289289

@@ -294,27 +294,21 @@ export class ApplicationModule {}
294294
> parse-int.pipe.ts
295295
296296
```typescript
297-
import {
298-
PipeTransform,
299-
Pipe,
300-
ArgumentMetadata,
301-
HttpStatus,
302-
BadRequestException
303-
} from "@nestjs/common";
297+
import { PipeTransform, Injectable, ArgumentMetadata, BadRequestException } from '@nestjs/common';
304298

305299
@Injectable()
306-
export class ParseIntPipe implements PipeTransform<string> {
307-
async transform(value: string, metadata: ArgumentMetadata) {
300+
export class ParseIntPipe implements PipeTransform<string, number> {
301+
transform(value: string, metadata: ArgumentMetadata): number {
308302
const val = parseInt(value, 10);
309303
if (isNaN(val)) {
310-
throw new BadRequestException("Validation failed");
304+
throw new BadRequestException('Validation failed');
311305
}
312306
return val;
313307
}
314308
}
315309
```
316310

317-
这是一个 `ParseIntPipe`,它负责将一个字符串解析为一个整数值。现在我们将管道绑定到选定的参数:
311+
如下所示, 我们可以很简单的配置管道来处理所参数 id:
318312

319313
```typescript
320314
@Get(':id')
@@ -334,12 +328,36 @@ findOne(@Param('id', UserByIdPipe) userEntity: UserEntity) {
334328
}
335329
```
336330

331+
如果愿意你还可以试试 `ParseUUIDPipe` 管道, 它用来分析验证字符串是否是 UUID.
332+
333+
```typescript
334+
@Get(':id')
335+
async findOne(@Param('id', new ParseUUIDPipe()) id) {
336+
return await this.catsService.findOne(id);
337+
}
338+
```
339+
340+
?> `ParseUUIDPipe` 会使用 UUID 3,4,5 版本 来解析字符串, 你也可以单独设置需要的版本.
341+
342+
你也可以试着做一个管道自己通过 id 找到实体数据:
343+
344+
```typescript
345+
@Get(':id')
346+
findOne(@Param('id', UserByIdPipe) userEntity: UserEntity) {
347+
return userEntity;
348+
}
349+
```
350+
351+
请读者自己实现, 这个管道接收 id 参数并返回 UserEntity 数据, 这样做就可以抽象出一个根据 id 得到 UserEntity 的公共管道, 你的程序变得更符合声明式(Declarative 更好的代码语义和封装方式), 更 DRY (Don't repeat yourself 减少重复代码) 编程规范.
352+
337353
## 内置验证管道
338354

339355
幸运的是,由于 `ValidationPipe``ParseIntPipe` 是内置管道,因此您不必自己构建这些管道(请记住, `ValidationPipe` 需要同时安装 `class-validator``class-transformer` 包)。
340356

341357
内置的 `ValidationPipe` 提供了比本章描述的更多的选项,为了简单和减少学习曲线,这些选项一直保持基本。你可以在[这里](https://docs.nestjs.com/techniques/validation)查看很多例子。
342358

359+
One such option is transform. Recall the earlier discussion about deserialized body objects being vanilla JavaScript objects (i.e., not having our DTO type). So far, we've used the pipe to validate our payload. You may recall that in the process, we used class-transform to temporarily convert our plain object into a typed object so that we could do the validation. The built-in ValidationPipe can also, optionally, return this converted object. We enable this behavior by passing in a configuration object to the pipe. For this option, pass a config object with the field transform with a value true as shown below:
360+
343361
如果您查看控制器函数中的 `createCatDto`,您会发现它不是实际的 `CreateCatDto` 实例。这是因为此管道仅验证有效负载,而不将其转换为预期类型。但是,如果希望管道改变有效负载,可以通过传递适当的选项来配置它:
344362

345363
> cats.controller.ts
@@ -354,6 +372,7 @@ async create(@Body() createCatDto: CreateCatDto) {
354372

355373
?> `ValidationPipe` 是从 `@nestjs/common` 包中导入的。
356374

375+
Because this pipe is based on the class-validator and class-transformer libraries, there are many additional options available. Like the transform option above, you configure these settings via a configuration object passed to the pipe. Following are the built-in options:
357376
因为这个管道是基于 `class-validator``class-transformer` 库的,所以有更多选项。看看构造函数的可选选项。
358377

359378
```typescript
@@ -373,6 +392,7 @@ export interface ValidationPipeOptions extends ValidatorOptions {
373392
| `forbidNonWhitelisted` | `boolean` | 如果设置为 true,则验证程序将引发异常,而不是取消非白名单属性。 |
374393
| `forbidUnknownValues` | `boolean` | 如果设置为 true,未知对象的验证将立即失败。 |
375394
| `disableErrorMessages` | `boolean` | 如果设置为 true,验证错误将不会转发到客户端。 |
395+
| `exceptionFactory` | `Function` | 设置异常的工厂方法,用来定义并返回要抛出的异常信息。 |
376396
| `groups` | `string[]` | 验证对象期间要使用的组。 |
377397
| `dismissDefaultMessages` | `boolean` | 如果设置为 true,验证将不使用默认消息。如果错误消息未显式设置,则为 `undefined` 的。 |
378398
| `validationError.target` | `boolean` | 目标是否应在 `ValidationError` 中展示 |

0 commit comments

Comments
 (0)