nestjsx / crud

NestJs CRUD for RESTful APIs
https://github.com/nestjsx/crud/wiki
MIT License
4.04k stars 533 forks source link

Use the query join option on getOneBase only #704

Open Hani-Ghazi opened 3 years ago

Hani-Ghazi commented 3 years ago

I have this controller

@Crud({
  model: {
    type: Product,
  },
  routes: {
    exclude: ['createManyBase', 'recoverOneBase'],
    getManyBase: {
      decorators: [UseGuards(OptionalJwtAuthGuard)],
    },
    createOneBase: {
      decorators: [UseGuards(AuthGuard('jwt'))],
    },
  },
  query: {
    join: {
      category: {
        eager: true,
      },
      sizes: {
        eager: true,
      },
      colors: {
        eager: true,
      },
      reviews: {
        eager: true,
      },
      'reviews.user': {
        allow: ['id', 'firstName', 'lastName'],
        eager: true,
      },
      favorites: {
        eager: true,
      },
    },
  },
})
@Controller('products')

I need to use the join reviews && reviews.user on the getOneBase route only. any advice, please?

jspizziri commented 3 years ago

AFAIK, the only way to do something like this is by modifying the nestjsx/crud controller options with a custom interceptor.

So you could do something like the following:

Controller

Add a custom interceptor to the getOneBase endpoint.

import { Controller } from '@nestjs/common';
import { Crud, CrudController } from '@nestjsx/crud';

import { Foo } from '../entities';
import { FooService } from '../services';
import { FooInterceptor } from '../interceptors';

@Crud({
  model: {
    type: Foo,
  },
  routes: {
    getOneBase: {
      interceptors: [
        FooInterceptor,
      ],
    },
  },
})
@ApiTags('Foo')
@Controller('foos')
export class FooController implements CrudController<Foo> {
  constructor(public service: FooService) {}
}

Interceptor

Modify the nestjsx crud options to perform an eager fetch on myNestedProperty for any routes using this interceptor.

import {
  Injectable,
  NestInterceptor,
  ExecutionContext,
  CallHandler,
} from '@nestjs/common';
import { PARSED_CRUD_REQUEST_KEY } from '@nestjsx/crud/lib/constants';
import { Observable } from 'rxjs';

@Injectable()
export class FooInterceptor implements NestInterceptor {
  intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
    const options = context.switchToHttp().getRequest()[PARSED_CRUD_REQUEST_KEY].options;
    options.query = {
      join: {
        myNestedProperty: {
          eager: true,
        },
      },
    };

    return next
      .handle()
    ;
  }
}

Caveat

Be aware that you may need to monkey around with custom serializers to get the DTO's correct for an approach like this.