smotastic / smartstruct

Dart Code Generator for generating mapper classes
35 stars 18 forks source link

Injectable Issue #88

Open Jaew00Shin opened 1 year ago

Jaew00Shin commented 1 year ago

Hello, I am going to apply smartstruct packages to my company projects. I am using freezed & injectable. I want you to add a new feature for smartstruct with injectable.

This code is what I have written.

class DependencyOrder {
  static const int dataMapper = 1; // mapper
}
class DataMapper extends Injectable {
  const DataMapper({
    super.as,
    super.env,
    super.scope,
  }) : super(order: DependencyOrder.dataMapper);
abstract class Mappable<M, E> {
  M call(E entity);
}
@DataMapper(as: Mappable<User, UserRes>)
class UserMapper implements Mappable<User, UserRes> {
  @override
  User call(UserRes entity) {
    return User(
      admin: entity.admin,
      email: entity.email,
      imageUrl: entity.imageUrl.isNotEmpty ? entity.imageUrl : null,
      name: entity.name,
    );
  }
}

I want to convert my UserMapper class to same one with smart struct.

I have a problem with now version of smart struct. 1.4.0 User & UserRes class is composed of freezed.

If I apply smart struct to this code, I should change UserMapper to abstract class. And I also would set useInjectable to true.

Then UserMapperImpl class generated by build_runner would have a @LazySingleton(as: UserMapper).

I want to custom value of as. not UserMapper but Mappable<User, UserRes>

// custom singleton or injectable or lazySingleton
@Injectable(
   as: Mappable<User, UserRes>, // custom
   order: DependencyOrder.dataMapper, // custom
)
class UserMapperImpl implements UserMapper {
  // generated code ...
}

I hope you to add this feature that custom injectable properties.

petrnymsa commented 1 year ago

@Jaew00Shin Hi, can you elaborate little bit more what are you trying to achieve?

Jaew00Shin commented 1 year ago

In now version, I can set just boolean value for useInjectable. If the value of useInjectable is true, the injectable annotation is generated to @LazySingleton(as: UserMapper).

But I want to choose freely the annotation, whether it is injectable, singleton or lazy singleton. Also, I want to set the arguments of the annotation.

In now version,

@Mapper(useInjectable: true)
abstract class UserMapper implements Mappable<User, UserRes> {
  @override
  @Mapping(target: 'copyWith', ignore: true)
  User call(UserRes entity);
}
@LazySingleton(as: UserMapper)
class UserMapperImpl implements UserMapper {
  // generated code ...
}

After applying what I want,

// packages
import 'package:injectable/injectable.dart';

// order
import 'dependency_order.dart';

const dataMapper = DataMapper();

class DataMapper extends Injectable {
  const DataMapper({
    super.as,
    super.env,
    super.scope,
  }) : super(order: DependencyOrder.dataMapper);
}
@DataMapper(
   useInjectable: DataMapper(as: Mappable<User,UserRes>),
)
abstract class UserMapper implements Mappable<User, UserRes> {
  @override
  @Mapping(target: 'copyWith', ignore: true)
  User call(UserRes entity);
}
// custom singleton or injectable or lazySingleton
@Injectable(
   as: Mappable<User, UserRes>, // custom
   order: DependencyOrder.dataMapper, // custom
)
class UserMapperImpl implements UserMapper {
  // generated code ...
}

The key point is that the value of useInjectable should be more customable.

petrnymsa commented 1 year ago

@Jaew00Shin , ah, I see… That is for sure not possible right now, and unfortunately, based on activity with issues and PRs, I am unsure whether these changes will be implemented or merged soon. However (and sorry for the self-promo, just giving other options that fulfill your needs) you can try out our quite new package AutoMappr, where this and other features you want are supported. It is highly customizable, with support for generics, enums, iterables, etc. I’ve prepared an example of how to use it with Injectable and you can use whatever annotation you like. LINK