nestjs-query icon indicating copy to clipboard operation
nestjs-query copied to clipboard

Assembler's convertAsyncToEntity is not used

Open petyunchik opened this issue 4 years ago • 6 comments

There is convertAsyncToEntity method declared in Assembler class, but it's not in use anywhere. Would be very useful to make it work similar way as convertAsyncToDTO to perform async transformations.

And thank you for the library!

petyunchik avatar Jul 14 '20 16:07 petyunchik

@petyunchik I'm not sure I understand the comment. You can use it if you inject the assembler.

doug-martin avatar Jul 16 '20 02:07 doug-martin

@doug-martin Sorry, I mean that AssemblerQueryService is not calling Assembler's convertAsyncToEntity method anywhere. Even if some async logic will be added to convertAsyncToEntity it wouldn't be executed by default AssemblerQueryService.

petyunchik avatar Jul 22 '20 15:07 petyunchik

By default, the auto-generated resolver executes convertToDto, if you need to handle async operations on the assembler we need to override the resolver in order to call the convertAsyncToDto which is a bit redundant in my perspective. Why not always call convertAsyncToDto?

This is not ideal, now I have 2 services (MongooseQueryService, AssemblerQueryService), 1 assembler, and 1 custom resolver just to convert a string to another string with an async operation?!

My code:

export class CompaniesService extends AssemblerQueryService<CompanyDTO, Company> {
  constructor(
    readonly assembler: CompaniesAssembler,
    @Inject(CompaniesQueryService) readonly service: CompaniesQueryService,
  ) {
    super(assembler, service);
  }

  async findById(id: string): Promise<CompanyDTO> {
    const company = await this.service.findById(id)
    return this.assembler.convertAsyncToDTO(Promise.resolve(company))
  }
}
@Assembler(CompanyDTO, Company)
export class CompaniesAssembler extends ClassTransformerAssembler<CompanyDTO, Company> {
  constructor(
    @Inject(S3Service) private readonly s3: S3Service
  ) {
    super();
  }


  async convertAsyncToDTO(entity: Promise<Company>): Promise<CompanyDTO> {
    console.log('here???')
    const company = await entity
    const dto = super.convertToDTO(company)

    if (company.logo) {
      dto.logo = await this.s3.getObjectSignedUrl(company?.logo)
    }

    return dto
  }

  async convertAsyncToDTOs(entities: Promise<Company[]>): Promise<CompanyDTO[]> {
    const companies = await entities
    const dtos = await Promise.all(
      companies.map(async company => this.convertAsyncToDTO(Promise.resolve(company)))
    )
    return dtos
  }
}
import { Inject } from '@nestjs/common';
import { Resolver, Query, Args, ArgsType, ObjectType, Mutation, Field, InputType, ResolveField, Parent, ID } from '@nestjs/graphql';
import { CheckPolicies } from '../casl/check-policies.decorator';
import { CompaniesQueryService } from './companies.queryService';
import { CompaniesService } from './companies.service';
import { CompanyDTO } from './dto/company.dto';

@Resolver(() => CompanyDTO)
export class CompanyResolver {
  constructor(
    @Inject(CompaniesQueryService) private readonly queryService: CompaniesQueryService,
    @Inject(CompaniesService) private readonly service: CompaniesService
  ) {}

  @Query(() => CompanyDTO)
  async company(@Args('id', { type: () => ID }) id: string): Promise<CompanyDTO> {
    return this.service.findById(id)
  }
}
const modules = [
  NestjsQueryGraphQLModule.forFeature({
    assemblers: [CompaniesAssembler],
    imports: [
      NestjsQueryMongooseModule.forFeature([
        { document: Company, name: Company.name, schema: CompanySchema },
      ]),
    ],
    services: [CompaniesService, CompaniesQueryService],
    resolvers: [
      {
        ServiceClass: CompaniesService,
        AssemblerClass: CompaniesAssembler,
        DTOClass: CompanyDTO,
        EntityClass: Company,
        CreateDTOClass: CompanyInputDTO,
        create: { decorators: [CheckPolicies(CreateCompanyPolicyHandler)] },
        read: { decorators: [CheckPolicies(ReadCompanyPolicyHandler)] },
        update: { decorators: [CheckPolicies(UpdateCompanyPolicyHandler)] },
        delete: { decorators: [CheckPolicies(DeleteCompanyPolicyHandler)] },
        pagingStrategy: PagingStrategies.OFFSET
      }
    ],
  }),
]
@Module({
  providers: [CompanyResolver],
  imports: modules,
  exports: modules
})
export class CompaniesModule { }

Fatxx avatar Mar 27 '21 11:03 Fatxx

@doug-martin

Fatxx avatar Mar 27 '21 11:03 Fatxx

Same issue like @Fatxx described, I just need to create s3 signed url :(

awHamer avatar Aug 19 '21 11:08 awHamer

@Fatxx How did you managed DI to work in Assembler? Looks like it's impossible, since the class creates by the custom factory https://github.com/doug-martin/nestjs-query/blob/master/packages/core/src/assemblers/assembler.factory.ts

awHamer avatar Aug 19 '21 15:08 awHamer