class-transformer icon indicating copy to clipboard operation
class-transformer copied to clipboard

feature: dependecy injection

Open Arnaud-Dev-Nodejs opened this issue 5 years ago • 9 comments

Description

To follow the previous issue : https://github.com/typestack/class-transformer/issues/153 Actually using NestJS, I create a new TransformModifier like this :

import { TransformOptions } from "class-transformer";
import { defaultMetadataStorage } from "class-transformer/storage";

export function Deserialize(
  separator: string | RegExp = " ",
  options: TransformOptions = {}
): PropertyDecorator {
  const transformFn = (value: any, obj: any) => String(value).split(separator);

  return function (target: any, propertyName: string | Symbol): void {
    defaultMetadataStorage.addTransformMetadata({
      target: target.constructor,
      propertyName: propertyName as string,
      transformFn,
      options
    });
  };
}

but I require to inject ConfigService in it to get the 'separator' input to do something like that

export function Deserialize(
  appType: string | RegExp = " ",
  options: TransformOptions = {}
): PropertyDecorator {
  const separator = this.config.get<AppConfig>("MyClientConfig").splitSeperator;
  const transformFn = (value: any, obj: any) => String(value).split(separator);

  return function (target: any, propertyName: string | Symbol): void {
    defaultMetadataStorage.addTransformMetadata({
      target: target.constructor,
      propertyName: propertyName as string,
      transformFn,
      options
    });
  };
}

the problem is at the moment of the initialization of the Decorator, the data of the config are not up. So I have to inject it.

Proposed solution

class-validator offers a solution ; they add a "useContainer" functionnality like this :

 useContainer(app.select(AppModule), { fallbackOnErrors: true });

and allow in class to do that :

  constructor(@Inject('ConfigService') public readonly config: ConfigService) {
    super();
  }

Arnaud-Dev-Nodejs avatar Sep 08 '20 03:09 Arnaud-Dev-Nodejs

This is already possible with TypeDI. You can simply get any value from Container.get from TypeDI.

NoNameProvided avatar Feb 22 '21 04:02 NoNameProvided

Actually it would be nice to support other containers than TypeDI. Leaving it open.

NoNameProvided avatar Feb 22 '21 04:02 NoNameProvided

Would be really nice to be able to use Nest DI with @Transform decorators.

gterras avatar Nov 12 '22 13:11 gterras

In my case, I'd like to be able to access the database from the @Type decorator. I'm not sure if the proposal of @Arnaud-Dev-Nodejs would cover my case.

@Type((data: TypeHelpOptions) => {
    const discriminator = getFromDb();
    switch (discriminator) {
      case DeliveryTypes.DELIVERY:
        return DeliveryShipmentDto;
      case DeliveryTypes.PICKUP:
        return PickupShipmentDto;
    }
  })
@ValidateNested()
  shipment: DeliveryShipmentDto | PickupShipmentDto;

rafaelgc avatar Feb 20 '23 21:02 rafaelgc

It's been some time since we last talked about this subject. Have there been any advancements or new information? Personally, I use Serialization to transform my objects without altering their type within the service scope. Specifically, I have a pre-signed URL service and I want to inject it into the transformer to customize the fields that need conversion. The solution I have so far is Interceptor

joao-moonward avatar Jul 24 '23 22:07 joao-moonward