mirror of
https://github.com/nestjs/nest.git
synced 2026-02-21 23:11:44 +00:00
58 lines
1.9 KiB
TypeScript
58 lines
1.9 KiB
TypeScript
import type { NestInterceptor, Type } from '@nestjs/common';
|
|
import { AsyncResource } from 'async_hooks';
|
|
import { Observable, defer, from as fromPromise } from 'rxjs';
|
|
import { mergeAll, switchMap } from 'rxjs/operators';
|
|
import { ExecutionContextHost } from '../helpers/execution-context-host.js';
|
|
import type { CallHandler, ContextType } from '@nestjs/common';
|
|
import { type Controller, isEmpty } from '@nestjs/common/internal';
|
|
|
|
export class InterceptorsConsumer {
|
|
public async intercept<TContext extends string = ContextType>(
|
|
interceptors: NestInterceptor[],
|
|
args: unknown[],
|
|
instance: Controller,
|
|
callback: (...args: unknown[]) => unknown,
|
|
next: () => Promise<unknown>,
|
|
type?: TContext,
|
|
): Promise<unknown> {
|
|
if (isEmpty(interceptors)) {
|
|
return next();
|
|
}
|
|
const context = this.createContext(args, instance, callback);
|
|
context.setType<TContext>(type!);
|
|
|
|
const nextFn = async (i = 0) => {
|
|
if (i >= interceptors.length) {
|
|
return defer(AsyncResource.bind(() => this.transformDeferred(next)));
|
|
}
|
|
const handler: CallHandler = {
|
|
handle: () =>
|
|
defer(AsyncResource.bind(() => nextFn(i + 1))).pipe(mergeAll()),
|
|
};
|
|
return interceptors[i].intercept(context, handler);
|
|
};
|
|
return defer(() => nextFn()).pipe(mergeAll());
|
|
}
|
|
|
|
public createContext(
|
|
args: unknown[],
|
|
instance: Controller,
|
|
callback: (...args: unknown[]) => unknown,
|
|
): ExecutionContextHost {
|
|
return new ExecutionContextHost(
|
|
args,
|
|
instance.constructor as Type<unknown>,
|
|
callback,
|
|
);
|
|
}
|
|
|
|
public transformDeferred(next: () => Promise<any>): Observable<any> {
|
|
return fromPromise(next()).pipe(
|
|
switchMap(res => {
|
|
const isDeferred = res instanceof Promise || res instanceof Observable;
|
|
return isDeferred ? res : Promise.resolve(res);
|
|
}),
|
|
);
|
|
}
|
|
}
|