Files
nest/packages/core/interceptors/interceptors-consumer.ts
2018-12-12 23:35:27 +01:00

55 lines
1.6 KiB
TypeScript

import { NestInterceptor } from '@nestjs/common';
import { CallHandler, Controller } from '@nestjs/common/interfaces';
import { isEmpty } from '@nestjs/common/utils/shared.utils';
import { defer, from as fromPromise, Observable } from 'rxjs';
import { mergeAll, switchMap } from 'rxjs/operators';
import { ExecutionContextHost } from '../helpers/execution-context-host';
export class InterceptorsConsumer {
public async intercept(
interceptors: NestInterceptor[],
args: any[],
instance: Controller,
callback: (...args: any[]) => any,
next: () => Promise<any>,
): Promise<any> {
if (isEmpty(interceptors)) {
return next();
}
const context = this.createContext(args, instance, callback);
const start$ = defer(() => this.transformDeffered(next));
const nextFn = (i = 0) => async () => {
if (i >= interceptors.length) {
return start$;
}
const handler: CallHandler = {
handle: () => fromPromise(nextFn(i + 1)()).pipe(mergeAll()),
};
return interceptors[i].intercept(context, handler);
};
return nextFn()();
}
public createContext(
args: any[],
instance: Controller,
callback: (...args: any[]) => any,
): ExecutionContextHost {
return new ExecutionContextHost(
args,
instance.constructor as any,
callback,
);
}
public transformDeffered(next: () => Promise<any>): Observable<any> {
return fromPromise(next()).pipe(
switchMap(res => {
const isDeffered = res instanceof Promise || res instanceof Observable;
return isDeffered ? res : Promise.resolve(res);
}),
);
}
}