Skip to content

Commit

Permalink
feat(nestjs): add MapInterceptor
Browse files Browse the repository at this point in the history
  • Loading branch information
nartc committed Jan 11, 2021
1 parent 822c790 commit 1a811e5
Show file tree
Hide file tree
Showing 4 changed files with 94 additions and 0 deletions.
1 change: 1 addition & 0 deletions packages/nestjs/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@ export * from './lib/automapper.module';
export * from './lib/interfaces';
export * from './lib/di';
export * from './lib/abstracts';
export * from './lib/interceptors';
1 change: 1 addition & 0 deletions packages/nestjs/src/lib/interceptors/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './map.interceptor';
71 changes: 71 additions & 0 deletions packages/nestjs/src/lib/interceptors/map.interceptor.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
import type { MapOptions, Mapper } from '@automapper/types';
import type {
CallHandler,
ExecutionContext,
NestInterceptor,
} from '@nestjs/common';
import { mixin, Optional } from '@nestjs/common';
import type { Observable } from 'rxjs';
import { map } from 'rxjs/operators';
import { InjectMapper } from '../di';
import { memoize } from './memoize.util';

export const MapInterceptor: (
to: unknown,
from: unknown,
options?: { isArray?: boolean; mapperName?: string } & MapOptions
) => NestInterceptor = memoize(createMapInterceptor);

function createMapInterceptor(
to: unknown,
from: unknown,
options?: { isArray?: boolean; mapperName?: string }
): new (...args) => NestInterceptor {
const { isArray = false, mapperName, ...mapOptions } = options || {};

class MixinMapInterceptor implements NestInterceptor {
constructor(
@Optional() @InjectMapper(mapperName) private readonly mapper: Mapper
) {}

async intercept(
context: ExecutionContext,
next: CallHandler
): Promise<Observable<unknown>> {
if (!this.mapper || !to || !from) {
return next.handle();
}

try {
return next.handle().pipe(
map((response) => {
if (isArray) {
if (!Array.isArray(response)) return response;
return this.mapper.mapArray(
response,
// eslint-disable-next-line @typescript-eslint/no-explicit-any
to as any,
// eslint-disable-next-line @typescript-eslint/no-explicit-any
from as any,
mapOptions
);
}

return this.mapper.map(
response,
// eslint-disable-next-line @typescript-eslint/no-explicit-any
to as any,
// eslint-disable-next-line @typescript-eslint/no-explicit-any
from as any,
mapOptions
);
})
);
} catch {
return next.handle();
}
}
}

return mixin(MixinMapInterceptor);
}
21 changes: 21 additions & 0 deletions packages/nestjs/src/lib/interceptors/memoize.util.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
const defaultKey = 'default';

// eslint-disable-next-line @typescript-eslint/ban-types
export function memoize(fn: Function) {
const cache = {};
return (...args) => {
const n =
args.reduce(
(key, arg) =>
key.concat('|', typeof arg === 'string' ? arg : arg.toString()),
''
) || defaultKey;
if (n in cache) {
return cache[n];
}

const result = n === defaultKey ? fn() : fn(...args);
cache[n] = result;
return result;
};
}

0 comments on commit 1a811e5

Please sign in to comment.