-
-
Notifications
You must be signed in to change notification settings - Fork 7.8k
/
Copy pathclass-serializer.interceptor.ts
85 lines (76 loc) · 2.47 KB
/
class-serializer.interceptor.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';
import { Inject, Injectable } from '../decorators/core';
import { ClassTransformOptions } from '../interfaces/external/class-transform-options.interface';
import { loadPackage } from '../utils/load-package.util';
import { isObject } from '../utils/shared.utils';
import {
CallHandler,
ExecutionContext,
NestInterceptor,
} from './../interfaces';
import { CLASS_SERIALIZER_OPTIONS } from './class-serializer.constants';
let classTransformer: any = {};
export interface PlainLiteralObject {
[key: string]: any;
}
// NOTE (external)
// We need to deduplicate them here due to the circular dependency
// between core and common packages
const REFLECTOR = 'Reflector';
@Injectable()
export class ClassSerializerInterceptor implements NestInterceptor {
constructor(@Inject(REFLECTOR) protected readonly reflector: any) {
classTransformer = loadPackage(
'class-transformer',
'ClassSerializerInterceptor',
() => require('class-transformer'),
);
require('class-transformer');
}
intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
const options = this.getContextOptions(context);
return next
.handle()
.pipe(
map((res: PlainLiteralObject | Array<PlainLiteralObject>) =>
this.serialize(res, options),
),
);
}
serialize(
response: PlainLiteralObject | Array<PlainLiteralObject>,
options: ClassTransformOptions,
): PlainLiteralObject | PlainLiteralObject[] {
const isArray = Array.isArray(response);
if (!isObject(response) && !isArray) {
return response;
}
return isArray
? (response as PlainLiteralObject[]).map(item =>
this.transformToPlain(item, options),
)
: this.transformToPlain(response, options);
}
transformToPlain(
plainOrClass: any,
options: ClassTransformOptions,
): PlainLiteralObject {
return plainOrClass && plainOrClass.constructor !== Object
? classTransformer.classToPlain(plainOrClass, options)
: plainOrClass;
}
private getContextOptions(
context: ExecutionContext,
): ClassTransformOptions | undefined {
return (
this.reflectSerializeMetadata(context.getHandler()) ||
this.reflectSerializeMetadata(context.getClass())
);
}
private reflectSerializeMetadata(
obj: object | Function,
): ClassTransformOptions | undefined {
return this.reflector.get(CLASS_SERIALIZER_OPTIONS, obj);
}
}