-
Notifications
You must be signed in to change notification settings - Fork 3
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Support referencing subtypes from other files #28
base: master
Are you sure you want to change the base?
Conversation
…t, Map Also preserve type aliases in generated files Fixes atreeon#15
# Conflicts: # morphy/lib/morphy2Builder.dart # morphy/lib/morphyBuilder.dart
Thanks so much for contributing. I'll try to take a proper look over the weekend or next week. It's really nice to hear people using this package after quite a while of tumbleweed after I first published it! |
fantastik! I made more improvements. throwing error if missing imports in subclasses that are not obvious to import. added an optional method compareTo method, that compares the object against another object to have Map<String,dynamic> type diff nested. This is needed when you work with big objects and use graphql or firestore to send only delta updates. |
Here is the output of the compareToX extension I added. I made this as a default method. Since for grahql and firestore entities we need the delta json to send the update not the whole object. it can be turned off with annotation. @morphy(generateCompareTo: false) extension $CustomerCompareE on $Customer {
Map<String, dynamic> compareToCustomer(Customer other) {
final Map<String, dynamic> diff = {};
if (device != other.device) {
diff['device'] = () => device.compareToDevice(other.device);
}
if (locale != other.locale) {
diff['locale'] = () => locale.compareToLocale(other.locale);
}
if (id != other.id) {
diff['id'] = () => other.id;
}
if (code != other.code) {
diff['code'] = () => other.code;
}
if (name != other.name) {
diff['name'] = () => other.name;
}
if (description != other.description) {
diff['description'] = () => other.description;
}
if (createdAt != other.createdAt) {
diff['createdAt'] = () => other.createdAt;
}
if (updatedAt != other.updatedAt) {
diff['updatedAt'] = () => other.updatedAt;
}
return diff;
}
} and this is the customer class.It checks for all types that it implements from that has fields so all nesting is guaranteed. import 'package:morphy_annotation/morphy_annotation.dart';
import '../../../domain/entities/actor/user.dart';
import '../../../domain/entities/actor/person.dart';
import '../../../domain/entities/actor/actor.dart';
import 'package:zikzak/src/domain/entities/actor/participant.dart';
import 'package:zikzak/src/domain/entities/actor/entity.dart';
import '../../../domain/entities/device/device.dart';
import '../../../domain/types/locale.dart';
import 'id.dart';
part 'customer.morphy.dart';
part 'customer.g.dart';
@Morphy(generateJson: true)
abstract class $Customer implements $$Person {
$Device get device;
$Locale get locale;
} |
added compareToX to compare object to another object and get nested diff in map
added non null marks for not null field
It got even better. My ultimate goal was to achieving a type safe and automated way of implementing patch type. I can't simply use the class reference for that, since the class has required fields that I might not need and actually dont want to be part of my patch, like 'id'. below is the latest generated code. It creates compareToX and compareToEnumX. I really liked your idea of generering enum X$ from the fields. Thats genius. @atreeon . So I built Patch type safety on top of that. this type ensures that fields are only class fields. CustomerPatch compareToEnumCustomer(Customer other) {
final CustomerPatch diff = {};
if (device != other.device) {
diff[Customer$.device] = () => device.compareToDevice(other.device);
}
if (locale != other.locale) {
diff[Customer$.locale] = () => locale.compareToLocale(other.locale);
}
if (id != other.id) {
diff[Customer$.id] = () => other.id;
}
if (code != other.code) {
diff[Customer$.code] = () => other.code;
}
if (name != other.name) {
diff[Customer$.name] = () => other.name;
}
if (description != other.description) {
diff[Customer$.description] = () => other.description;
}
if (createdAt != other.createdAt) {
diff[Customer$.createdAt] = () => other.createdAt;
}
if (updatedAt != other.updatedAt) {
diff[Customer$.updatedAt] = () => other.updatedAt;
}
return diff;
}
typedef CustomerPatch = Map<Customer$, dynamic>;
enum Customer$ {
device,
locale,
id,
code,
name,
description,
createdAt,
updatedAt
} and this is How I simply and confidently use in my abstract repo with type safety. abstract class UserRepository {
Future<void> update({required UserPatch patch}); |
and nirvana Customer x = Customer(
device: Device(id: 's'),
locale: Locale(countryCode: 'TR', languageCode: 'tr'),
name: 'Arny');
User y = x.copyWithUser(name: () => 'ARRRRNY');
UserPatch patch = x.compareToEnumUser(y); |
added Patch type definition
added more types to primitive compare
supporting nested compareToEnum nested name
implemented comprehensive non primitive type comparisons
…les via public constructor
fixed nested toJsonLean
All tests pass now. I made sligh change to fromJson method to allow data without className key nested and used public constructors referenced from subtypes instead of same file private constructors. |
type safe entity patch
@atreeon Adrian, I really like you to check the end result. it is fantastik! I implemented auto generated type safe patching that can beautiful used as this: // Create and convert to JSON
final patch = CustomerPatch.create()
.withEmail("[email protected]")
.withName("John");
// For GraphQL
final json = patch.toJson();
// For internal use
final patchMap = patch.toPatch();
// From JSON
final patch = CustomerPatch.fromJson(jsonData); and this: // Create patch from diff
final diff = customer.compareToCustomer(otherCustomer);
final patch = CustomerPatch.create(diff);
// Create patch using with methods
final patch = CustomerPatch()
.withProfile(newProfile)
.withPreferences(newPrefs);
// Apply patch
customer.copyWithCustomer(patch.toPatch()); And here is the generated output with support of nested type patch and convert toJson for graphql: // ignore_for_file: UNNECESSARY_CAST
// ignore_for_file: type=lint
part of 'customer.dart';
// **************************************************************************
// Generator: MorphyGenerator<Morphy>
// **************************************************************************
///
///implements [User]
///
///
///implements [Actor]
///
///
///implements [Participant]
///
///
///implements [Entity]
///
///
@JsonSerializable(
explicitToJson: true,
)
class Customer extends $Customer implements User, Actor, Participant, Entity {
final CustomerProfile? profile;
final CustomerPreferences? preferences;
final List<String>? favoriteStores;
final DateTime? lastPurchaseDate;
final int? totalPurchases;
final double? totalSpent;
final int? yearOfBirth;
final String? code;
final String? name;
final String id;
final Locale locale;
final String? firstName;
final String? lastName;
final String? phoneNumber;
final Town? location;
final DateTime? lastLogin;
final bool? isAnonymous;
final String? email;
final Device? device;
final String? displayName;
final String? deviceToken;
final DateTime? registeredAt;
final ZipCode? zipCode;
final bool? isBanned;
final bool? isVerified;
final DateTime? verifiedAt;
final DateTime? bannedAt;
///
///implements [User]
///
///
///implements [Actor]
///
///
///implements [Participant]
///
///
///implements [Entity]
///
///
Customer({
this.profile,
this.preferences,
this.favoriteStores,
this.lastPurchaseDate,
this.totalPurchases,
this.totalSpent,
this.yearOfBirth,
this.code,
this.name,
required this.id,
required this.locale,
this.firstName,
this.lastName,
this.phoneNumber,
this.location,
this.lastLogin,
this.isAnonymous,
this.email,
this.device,
this.displayName,
this.deviceToken,
this.registeredAt,
this.zipCode,
this.isBanned,
this.isVerified,
this.verifiedAt,
this.bannedAt,
});
Customer._({
this.profile,
this.preferences,
this.favoriteStores,
this.lastPurchaseDate,
this.totalPurchases,
this.totalSpent,
this.yearOfBirth,
this.code,
this.name,
required this.id,
required this.locale,
this.firstName,
this.lastName,
this.phoneNumber,
this.location,
this.lastLogin,
this.isAnonymous,
this.email,
this.device,
this.displayName,
this.deviceToken,
this.registeredAt,
this.zipCode,
this.isBanned,
this.isVerified,
this.verifiedAt,
this.bannedAt,
});
String toString() =>
"(Customer-profile:${profile.toString()}|preferences:${preferences.toString()}|favoriteStores:${favoriteStores.toString()}|lastPurchaseDate:${lastPurchaseDate.toString()}|totalPurchases:${totalPurchases.toString()}|totalSpent:${totalSpent.toString()}|yearOfBirth:${yearOfBirth.toString()}|code:${code.toString()}|name:${name.toString()}|id:${id.toString()}|locale:${locale.toString()}|firstName:${firstName.toString()}|lastName:${lastName.toString()}|phoneNumber:${phoneNumber.toString()}|location:${location.toString()}|lastLogin:${lastLogin.toString()}|isAnonymous:${isAnonymous.toString()}|email:${email.toString()}|device:${device.toString()}|displayName:${displayName.toString()}|deviceToken:${deviceToken.toString()}|registeredAt:${registeredAt.toString()}|zipCode:${zipCode.toString()}|isBanned:${isBanned.toString()}|isVerified:${isVerified.toString()}|verifiedAt:${verifiedAt.toString()}|bannedAt:${bannedAt.toString()})";
int get hashCode => hashObjects([
profile.hashCode,
preferences.hashCode,
favoriteStores.hashCode,
lastPurchaseDate.hashCode,
totalPurchases.hashCode,
totalSpent.hashCode,
yearOfBirth.hashCode,
code.hashCode,
name.hashCode,
id.hashCode,
locale.hashCode,
firstName.hashCode,
lastName.hashCode,
phoneNumber.hashCode,
location.hashCode,
lastLogin.hashCode,
isAnonymous.hashCode,
email.hashCode,
device.hashCode,
displayName.hashCode,
deviceToken.hashCode,
registeredAt.hashCode,
zipCode.hashCode,
isBanned.hashCode,
isVerified.hashCode,
verifiedAt.hashCode,
bannedAt.hashCode
]);
bool operator ==(Object other) =>
identical(this, other) ||
other is Customer &&
runtimeType == other.runtimeType &&
profile == other.profile &&
preferences == other.preferences &&
(favoriteStores ?? []).equalUnorderedD(other.favoriteStores ?? []) &&
lastPurchaseDate == other.lastPurchaseDate &&
totalPurchases == other.totalPurchases &&
totalSpent == other.totalSpent &&
yearOfBirth == other.yearOfBirth &&
code == other.code &&
name == other.name &&
id == other.id &&
locale == other.locale &&
firstName == other.firstName &&
lastName == other.lastName &&
phoneNumber == other.phoneNumber &&
location == other.location &&
lastLogin == other.lastLogin &&
isAnonymous == other.isAnonymous &&
email == other.email &&
device == other.device &&
displayName == other.displayName &&
deviceToken == other.deviceToken &&
registeredAt == other.registeredAt &&
zipCode == other.zipCode &&
isBanned == other.isBanned &&
isVerified == other.isVerified &&
verifiedAt == other.verifiedAt &&
bannedAt == other.bannedAt;
User copyWithUser({
String? Function()? code,
String? Function()? name,
String Function()? id,
Locale Function()? locale,
String? Function()? firstName,
String? Function()? lastName,
String? Function()? phoneNumber,
Town? Function()? location,
DateTime? Function()? lastLogin,
bool? Function()? isAnonymous,
String? Function()? email,
Device? Function()? device,
String? Function()? displayName,
String? Function()? deviceToken,
DateTime? Function()? registeredAt,
ZipCode? Function()? zipCode,
bool? Function()? isBanned,
bool? Function()? isVerified,
DateTime? Function()? verifiedAt,
DateTime? Function()? bannedAt,
}) {
return Customer._(
code: code == null ? this.code as String? : code() as String?,
name: name == null ? this.name as String? : name() as String?,
id: id == null ? this.id as String : id() as String,
locale: locale == null ? this.locale as Locale : locale() as Locale,
firstName: firstName == null
? this.firstName as String?
: firstName() as String?,
lastName:
lastName == null ? this.lastName as String? : lastName() as String?,
phoneNumber: phoneNumber == null
? this.phoneNumber as String?
: phoneNumber() as String?,
location: location == null ? this.location as Town? : location() as Town?,
lastLogin: lastLogin == null
? this.lastLogin as DateTime?
: lastLogin() as DateTime?,
isAnonymous: isAnonymous == null
? this.isAnonymous as bool?
: isAnonymous() as bool?,
email: email == null ? this.email as String? : email() as String?,
device: device == null ? this.device as Device? : device() as Device?,
displayName: displayName == null
? this.displayName as String?
: displayName() as String?,
deviceToken: deviceToken == null
? this.deviceToken as String?
: deviceToken() as String?,
registeredAt: registeredAt == null
? this.registeredAt as DateTime?
: registeredAt() as DateTime?,
zipCode:
zipCode == null ? this.zipCode as ZipCode? : zipCode() as ZipCode?,
isBanned: isBanned == null ? this.isBanned as bool? : isBanned() as bool?,
isVerified:
isVerified == null ? this.isVerified as bool? : isVerified() as bool?,
verifiedAt: verifiedAt == null
? this.verifiedAt as DateTime?
: verifiedAt() as DateTime?,
bannedAt: bannedAt == null
? this.bannedAt as DateTime?
: bannedAt() as DateTime?,
profile: (this as Customer).profile,
preferences: (this as Customer).preferences,
favoriteStores: (this as Customer).favoriteStores,
lastPurchaseDate: (this as Customer).lastPurchaseDate,
totalPurchases: (this as Customer).totalPurchases,
totalSpent: (this as Customer).totalSpent,
yearOfBirth: (this as Customer).yearOfBirth,
) as User;
}
Actor copyWithActor({
String? Function()? code,
String? Function()? name,
String? Function()? id,
}) {
return Customer._(
code: code == null ? this.code as String? : code() as String?,
name: name == null ? this.name as String? : name() as String?,
id: id == null ? this.id as String : id() as String,
profile: (this as Customer).profile,
preferences: (this as Customer).preferences,
favoriteStores: (this as Customer).favoriteStores,
lastPurchaseDate: (this as Customer).lastPurchaseDate,
totalPurchases: (this as Customer).totalPurchases,
totalSpent: (this as Customer).totalSpent,
yearOfBirth: (this as Customer).yearOfBirth,
locale: (this as Customer).locale,
firstName: (this as Customer).firstName,
lastName: (this as Customer).lastName,
phoneNumber: (this as Customer).phoneNumber,
location: (this as Customer).location,
lastLogin: (this as Customer).lastLogin,
isAnonymous: (this as Customer).isAnonymous,
email: (this as Customer).email,
device: (this as Customer).device,
displayName: (this as Customer).displayName,
deviceToken: (this as Customer).deviceToken,
registeredAt: (this as Customer).registeredAt,
zipCode: (this as Customer).zipCode,
isBanned: (this as Customer).isBanned,
isVerified: (this as Customer).isVerified,
verifiedAt: (this as Customer).verifiedAt,
bannedAt: (this as Customer).bannedAt,
) as Actor;
}
Participant copyWithParticipant({
String? Function()? code,
String? Function()? name,
String? Function()? id,
}) {
return Customer._(
code: code == null ? this.code as String? : code() as String?,
name: name == null ? this.name as String? : name() as String?,
id: id == null ? this.id as String : id() as String,
profile: (this as Customer).profile,
preferences: (this as Customer).preferences,
favoriteStores: (this as Customer).favoriteStores,
lastPurchaseDate: (this as Customer).lastPurchaseDate,
totalPurchases: (this as Customer).totalPurchases,
totalSpent: (this as Customer).totalSpent,
yearOfBirth: (this as Customer).yearOfBirth,
locale: (this as Customer).locale,
firstName: (this as Customer).firstName,
lastName: (this as Customer).lastName,
phoneNumber: (this as Customer).phoneNumber,
location: (this as Customer).location,
lastLogin: (this as Customer).lastLogin,
isAnonymous: (this as Customer).isAnonymous,
email: (this as Customer).email,
device: (this as Customer).device,
displayName: (this as Customer).displayName,
deviceToken: (this as Customer).deviceToken,
registeredAt: (this as Customer).registeredAt,
zipCode: (this as Customer).zipCode,
isBanned: (this as Customer).isBanned,
isVerified: (this as Customer).isVerified,
verifiedAt: (this as Customer).verifiedAt,
bannedAt: (this as Customer).bannedAt,
) as Participant;
}
Entity copyWithEntity({
String? Function()? code,
String? Function()? name,
String? Function()? id,
}) {
return Customer._(
code: code == null ? this.code as String? : code() as String?,
name: name == null ? this.name as String? : name() as String?,
id: id == null ? this.id as String : id() as String,
profile: (this as Customer).profile,
preferences: (this as Customer).preferences,
favoriteStores: (this as Customer).favoriteStores,
lastPurchaseDate: (this as Customer).lastPurchaseDate,
totalPurchases: (this as Customer).totalPurchases,
totalSpent: (this as Customer).totalSpent,
yearOfBirth: (this as Customer).yearOfBirth,
locale: (this as Customer).locale,
firstName: (this as Customer).firstName,
lastName: (this as Customer).lastName,
phoneNumber: (this as Customer).phoneNumber,
location: (this as Customer).location,
lastLogin: (this as Customer).lastLogin,
isAnonymous: (this as Customer).isAnonymous,
email: (this as Customer).email,
device: (this as Customer).device,
displayName: (this as Customer).displayName,
deviceToken: (this as Customer).deviceToken,
registeredAt: (this as Customer).registeredAt,
zipCode: (this as Customer).zipCode,
isBanned: (this as Customer).isBanned,
isVerified: (this as Customer).isVerified,
verifiedAt: (this as Customer).verifiedAt,
bannedAt: (this as Customer).bannedAt,
) as Entity;
}
Customer copyWithCustomer({
CustomerProfile? Function()? profile,
CustomerPreferences? Function()? preferences,
List<String>? Function()? favoriteStores,
DateTime? Function()? lastPurchaseDate,
int? Function()? totalPurchases,
double? Function()? totalSpent,
int? Function()? yearOfBirth,
String? Function()? code,
String? Function()? name,
String Function()? id,
Locale Function()? locale,
String? Function()? firstName,
String? Function()? lastName,
String? Function()? phoneNumber,
Town? Function()? location,
DateTime? Function()? lastLogin,
bool? Function()? isAnonymous,
String? Function()? email,
Device? Function()? device,
String? Function()? displayName,
String? Function()? deviceToken,
DateTime? Function()? registeredAt,
ZipCode? Function()? zipCode,
bool? Function()? isBanned,
bool? Function()? isVerified,
DateTime? Function()? verifiedAt,
DateTime? Function()? bannedAt,
}) {
return Customer._(
profile: profile == null
? this.profile as CustomerProfile?
: profile() as CustomerProfile?,
preferences: preferences == null
? this.preferences as CustomerPreferences?
: preferences() as CustomerPreferences?,
favoriteStores: favoriteStores == null
? this.favoriteStores as List<String>?
: favoriteStores() as List<String>?,
lastPurchaseDate: lastPurchaseDate == null
? this.lastPurchaseDate as DateTime?
: lastPurchaseDate() as DateTime?,
totalPurchases: totalPurchases == null
? this.totalPurchases as int?
: totalPurchases() as int?,
totalSpent: totalSpent == null
? this.totalSpent as double?
: totalSpent() as double?,
yearOfBirth: yearOfBirth == null
? this.yearOfBirth as int?
: yearOfBirth() as int?,
code: code == null ? this.code as String? : code() as String?,
name: name == null ? this.name as String? : name() as String?,
id: id == null ? this.id as String : id() as String,
locale: locale == null ? this.locale as Locale : locale() as Locale,
firstName: firstName == null
? this.firstName as String?
: firstName() as String?,
lastName:
lastName == null ? this.lastName as String? : lastName() as String?,
phoneNumber: phoneNumber == null
? this.phoneNumber as String?
: phoneNumber() as String?,
location: location == null ? this.location as Town? : location() as Town?,
lastLogin: lastLogin == null
? this.lastLogin as DateTime?
: lastLogin() as DateTime?,
isAnonymous: isAnonymous == null
? this.isAnonymous as bool?
: isAnonymous() as bool?,
email: email == null ? this.email as String? : email() as String?,
device: device == null ? this.device as Device? : device() as Device?,
displayName: displayName == null
? this.displayName as String?
: displayName() as String?,
deviceToken: deviceToken == null
? this.deviceToken as String?
: deviceToken() as String?,
registeredAt: registeredAt == null
? this.registeredAt as DateTime?
: registeredAt() as DateTime?,
zipCode:
zipCode == null ? this.zipCode as ZipCode? : zipCode() as ZipCode?,
isBanned: isBanned == null ? this.isBanned as bool? : isBanned() as bool?,
isVerified:
isVerified == null ? this.isVerified as bool? : isVerified() as bool?,
verifiedAt: verifiedAt == null
? this.verifiedAt as DateTime?
: verifiedAt() as DateTime?,
bannedAt: bannedAt == null
? this.bannedAt as DateTime?
: bannedAt() as DateTime?,
) as Customer;
}
//$User|[]|[id:String:$User, locale:$Locale:$User, firstName:String?:$User, lastName:String?:$User, phoneNumber:String?:$User, location:$Town?:$User, lastLogin:DateTime?:$User, isAnonymous:bool?:$User, email:String?:$User, device:$Device?:$User, displayName:String?:$User, deviceToken:String?:$User, registeredAt:DateTime?:$User, zipCode:$ZipCode?:$User, isBanned:bool?:$User, isVerified:bool?:$User, verifiedAt:DateTime?:$User, bannedAt:DateTime?:$User, code:String?:$Entity, name:String?:$Entity]$Actor|[]|[code:String?:$Entity, name:String?:$Entity, id:String?:$Entity]$$Participant|[]|[code:String?:$Entity, name:String?:$Entity, id:String?:$Entity]$Entity|[]|[code:String?:$Entity, name:String?:$Entity, id:String?:$Entity]$Customer|[]|[profile:CustomerProfile?:null, preferences:CustomerPreferences?:null, favoriteStores:List<String>?:null, lastPurchaseDate:DateTime?:null, totalPurchases:int?:null, totalSpent:double?:null, yearOfBirth:int?:null, code:String?:null, name:String?:null, id:String:null, locale:Locale:null, firstName:String?:null, lastName:String?:null, phoneNumber:String?:null, location:Town?:null, lastLogin:DateTime?:null, isAnonymous:bool?:null, email:String?:null, device:Device?:null, displayName:String?:null, deviceToken:String?:null, registeredAt:DateTime?:null, zipCode:ZipCode?:null, isBanned:bool?:null, isVerified:bool?:null, verifiedAt:DateTime?:null, bannedAt:DateTime?:null]
//
factory Customer.fromJson(Map<String, dynamic> json) {
if (json['_className_'] == null) {
return _$CustomerFromJson(json);
}
if (json['_className_'] == "Customer") {
return _$CustomerFromJson(json);
}
throw UnsupportedError(
"The _className_ '${json['_className_']}' is not supported by the Customer.fromJson constructor.");
}
// ignore: unused_field
Map<Type, Object? Function(Never)> _fns = {};
Map<String, dynamic> toJsonCustom([Map<Type, Object? Function(Never)>? fns]) {
_fns = fns ?? {};
return toJson();
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = _$CustomerToJson(this);
data['_className_'] = 'Customer';
return data;
}
Map<String, dynamic> toJsonLean() {
final Map<String, dynamic> data = _$CustomerToJson(
this,
);
return _sanitizeJson(data);
}
dynamic _sanitizeJson(dynamic json) {
if (json is Map<String, dynamic>) {
json.remove('_className_');
return json
..forEach((key, value) {
json[key] = _sanitizeJson(value);
});
} else if (json is List) {
return json.map((e) => _sanitizeJson(e)).toList();
}
return json;
}
}
extension $CustomerCompareE on $Customer {
Map<String, dynamic> compareToCustomer(Customer other) {
final Map<String, dynamic> diff = {};
if (profile != other.profile) {
diff['profile'] = () => other.profile;
}
if (preferences != other.preferences) {
diff['preferences'] = () => other.preferences;
}
if (favoriteStores != other.favoriteStores) {
if (favoriteStores != null && other.favoriteStores != null) {
if (favoriteStores!.length != other.favoriteStores!.length) {
diff['favoriteStores'] = () => other.favoriteStores;
} else {
var hasDiff = false;
for (var i = 0; i < favoriteStores!.length; i++) {
if (favoriteStores![i] != other.favoriteStores![i]) {
hasDiff = true;
break;
}
}
if (hasDiff) {
diff['favoriteStores'] = () => other.favoriteStores;
}
}
} else {
diff['favoriteStores'] = () => other.favoriteStores;
}
}
if (lastPurchaseDate != other.lastPurchaseDate) {
if (lastPurchaseDate != null && other.lastPurchaseDate != null) {
if (!lastPurchaseDate!.isAtSameMomentAs(other.lastPurchaseDate!)) {
diff['lastPurchaseDate'] = () => other.lastPurchaseDate;
}
} else {
diff['lastPurchaseDate'] = () => other.lastPurchaseDate;
}
}
if (totalPurchases != other.totalPurchases) {
diff['totalPurchases'] = () => other.totalPurchases;
}
if (totalSpent != other.totalSpent) {
diff['totalSpent'] = () => other.totalSpent;
}
if (yearOfBirth != other.yearOfBirth) {
diff['yearOfBirth'] = () => other.yearOfBirth;
}
if (code != other.code) {
diff['code'] = () => other.code;
}
if (name != other.name) {
diff['name'] = () => other.name;
}
if (id != other.id) {
diff['id'] = () => other.id;
}
if (locale != other.locale) {
diff['locale'] = () => other.locale;
}
if (firstName != other.firstName) {
diff['firstName'] = () => other.firstName;
}
if (lastName != other.lastName) {
diff['lastName'] = () => other.lastName;
}
if (phoneNumber != other.phoneNumber) {
diff['phoneNumber'] = () => other.phoneNumber;
}
if (location != other.location) {
diff['location'] = () => other.location;
}
if (lastLogin != other.lastLogin) {
if (lastLogin != null && other.lastLogin != null) {
if (!lastLogin!.isAtSameMomentAs(other.lastLogin!)) {
diff['lastLogin'] = () => other.lastLogin;
}
} else {
diff['lastLogin'] = () => other.lastLogin;
}
}
if (isAnonymous != other.isAnonymous) {
diff['isAnonymous'] = () => other.isAnonymous;
}
if (email != other.email) {
diff['email'] = () => other.email;
}
if (device != other.device) {
diff['device'] = () => other.device;
}
if (displayName != other.displayName) {
diff['displayName'] = () => other.displayName;
}
if (deviceToken != other.deviceToken) {
diff['deviceToken'] = () => other.deviceToken;
}
if (registeredAt != other.registeredAt) {
if (registeredAt != null && other.registeredAt != null) {
if (!registeredAt!.isAtSameMomentAs(other.registeredAt!)) {
diff['registeredAt'] = () => other.registeredAt;
}
} else {
diff['registeredAt'] = () => other.registeredAt;
}
}
if (zipCode != other.zipCode) {
diff['zipCode'] = () => other.zipCode;
}
if (isBanned != other.isBanned) {
diff['isBanned'] = () => other.isBanned;
}
if (isVerified != other.isVerified) {
diff['isVerified'] = () => other.isVerified;
}
if (verifiedAt != other.verifiedAt) {
if (verifiedAt != null && other.verifiedAt != null) {
if (!verifiedAt!.isAtSameMomentAs(other.verifiedAt!)) {
diff['verifiedAt'] = () => other.verifiedAt;
}
} else {
diff['verifiedAt'] = () => other.verifiedAt;
}
}
if (bannedAt != other.bannedAt) {
if (bannedAt != null && other.bannedAt != null) {
if (!bannedAt!.isAtSameMomentAs(other.bannedAt!)) {
diff['bannedAt'] = () => other.bannedAt;
}
} else {
diff['bannedAt'] = () => other.bannedAt;
}
}
return diff;
}
}
extension $CustomerchangeToE on $Customer {
Customer changeToCustomer({
CustomerProfile? Function()? profile,
CustomerPreferences? Function()? preferences,
List<String>? Function()? favoriteStores,
DateTime? Function()? lastPurchaseDate,
int? Function()? totalPurchases,
double? Function()? totalSpent,
int? Function()? yearOfBirth,
String? Function()? code,
String? Function()? name,
String Function()? id,
Locale Function()? locale,
String? Function()? firstName,
String? Function()? lastName,
String? Function()? phoneNumber,
Town? Function()? location,
DateTime? Function()? lastLogin,
bool? Function()? isAnonymous,
String? Function()? email,
Device? Function()? device,
String? Function()? displayName,
String? Function()? deviceToken,
DateTime? Function()? registeredAt,
ZipCode? Function()? zipCode,
bool? Function()? isBanned,
bool? Function()? isVerified,
DateTime? Function()? verifiedAt,
DateTime? Function()? bannedAt,
}) {
return Customer._(
profile: profile == null
? this.profile as CustomerProfile?
: profile() as CustomerProfile?,
preferences: preferences == null
? this.preferences as CustomerPreferences?
: preferences() as CustomerPreferences?,
favoriteStores: favoriteStores == null
? this.favoriteStores as List<String>?
: favoriteStores() as List<String>?,
lastPurchaseDate: lastPurchaseDate == null
? this.lastPurchaseDate as DateTime?
: lastPurchaseDate() as DateTime?,
totalPurchases: totalPurchases == null
? this.totalPurchases as int?
: totalPurchases() as int?,
totalSpent: totalSpent == null
? this.totalSpent as double?
: totalSpent() as double?,
yearOfBirth: yearOfBirth == null
? this.yearOfBirth as int?
: yearOfBirth() as int?,
code: code == null ? this.code as String? : code() as String?,
name: name == null ? this.name as String? : name() as String?,
id: id == null ? this.id as String : id() as String,
locale: locale == null ? this.locale as Locale : locale() as Locale,
firstName: firstName == null
? this.firstName as String?
: firstName() as String?,
lastName:
lastName == null ? this.lastName as String? : lastName() as String?,
phoneNumber: phoneNumber == null
? this.phoneNumber as String?
: phoneNumber() as String?,
location: location == null ? this.location as Town? : location() as Town?,
lastLogin: lastLogin == null
? this.lastLogin as DateTime?
: lastLogin() as DateTime?,
isAnonymous: isAnonymous == null
? this.isAnonymous as bool?
: isAnonymous() as bool?,
email: email == null ? this.email as String? : email() as String?,
device: device == null ? this.device as Device? : device() as Device?,
displayName: displayName == null
? this.displayName as String?
: displayName() as String?,
deviceToken: deviceToken == null
? this.deviceToken as String?
: deviceToken() as String?,
registeredAt: registeredAt == null
? this.registeredAt as DateTime?
: registeredAt() as DateTime?,
zipCode:
zipCode == null ? this.zipCode as ZipCode? : zipCode() as ZipCode?,
isBanned: isBanned == null ? this.isBanned as bool? : isBanned() as bool?,
isVerified:
isVerified == null ? this.isVerified as bool? : isVerified() as bool?,
verifiedAt: verifiedAt == null
? this.verifiedAt as DateTime?
: verifiedAt() as DateTime?,
bannedAt: bannedAt == null
? this.bannedAt as DateTime?
: bannedAt() as DateTime?,
) as Customer;
}
}
enum Customer$ {
profile,
preferences,
favoriteStores,
lastPurchaseDate,
totalPurchases,
totalSpent,
yearOfBirth,
code,
name,
id,
locale,
firstName,
lastName,
phoneNumber,
location,
lastLogin,
isAnonymous,
email,
device,
displayName,
deviceToken,
registeredAt,
zipCode,
isBanned,
isVerified,
verifiedAt,
bannedAt
}
class CustomerPatch {
final Map<Customer$, dynamic> _patch = {};
static CustomerPatch create([Map<String, dynamic>? diff]) {
final patch = CustomerPatch();
if (diff != null) {
diff.forEach((key, value) {
try {
final enumValue = Customer$.values.firstWhere((e) => e.name == key);
if (value is Function) {
patch._patch[enumValue] = value();
} else {
patch._patch[enumValue] = value;
}
} catch (_) {}
});
}
return patch;
}
Map<Customer$, dynamic> toPatch() => Map.from(_patch);
Map<String, dynamic> toJson() {
final json = <String, dynamic>{};
_patch.forEach((key, value) {
if (value != null) {
if (value is DateTime) {
json[key.name] = value.toIso8601String();
} else if (value is List) {
json[key.name] = value.map((e) => e?.toJson ?? e).toList();
} else {
json[key.name] = value?.toJson ?? value;
}
}
});
return json;
}
static CustomerPatch fromJson(Map<String, dynamic> json) {
return create(json);
}
CustomerPatch withprofile(CustomerProfile? value) {
_patch[Customer$.profile] = value;
return this;
}
CustomerPatch withpreferences(CustomerPreferences? value) {
_patch[Customer$.preferences] = value;
return this;
}
CustomerPatch withfavoriteStores(List<String>? value) {
_patch[Customer$.favoriteStores] = value;
return this;
}
CustomerPatch withlastPurchaseDate(DateTime? value) {
_patch[Customer$.lastPurchaseDate] = value;
return this;
}
CustomerPatch withtotalPurchases(int? value) {
_patch[Customer$.totalPurchases] = value;
return this;
}
CustomerPatch withtotalSpent(double? value) {
_patch[Customer$.totalSpent] = value;
return this;
}
CustomerPatch withyearOfBirth(int? value) {
_patch[Customer$.yearOfBirth] = value;
return this;
}
CustomerPatch withcode(String? value) {
_patch[Customer$.code] = value;
return this;
}
CustomerPatch withname(String? value) {
_patch[Customer$.name] = value;
return this;
}
CustomerPatch withid(String value) {
_patch[Customer$.id] = value;
return this;
}
CustomerPatch withlocale(Locale value) {
_patch[Customer$.locale] = value;
return this;
}
CustomerPatch withfirstName(String? value) {
_patch[Customer$.firstName] = value;
return this;
}
CustomerPatch withlastName(String? value) {
_patch[Customer$.lastName] = value;
return this;
}
CustomerPatch withphoneNumber(String? value) {
_patch[Customer$.phoneNumber] = value;
return this;
}
CustomerPatch withlocation(Town? value) {
_patch[Customer$.location] = value;
return this;
}
CustomerPatch withlastLogin(DateTime? value) {
_patch[Customer$.lastLogin] = value;
return this;
}
CustomerPatch withisAnonymous(bool? value) {
_patch[Customer$.isAnonymous] = value;
return this;
}
CustomerPatch withemail(String? value) {
_patch[Customer$.email] = value;
return this;
}
CustomerPatch withdevice(Device? value) {
_patch[Customer$.device] = value;
return this;
}
CustomerPatch withdisplayName(String? value) {
_patch[Customer$.displayName] = value;
return this;
}
CustomerPatch withdeviceToken(String? value) {
_patch[Customer$.deviceToken] = value;
return this;
}
CustomerPatch withregisteredAt(DateTime? value) {
_patch[Customer$.registeredAt] = value;
return this;
}
CustomerPatch withzipCode(ZipCode? value) {
_patch[Customer$.zipCode] = value;
return this;
}
CustomerPatch withisBanned(bool? value) {
_patch[Customer$.isBanned] = value;
return this;
}
CustomerPatch withisVerified(bool? value) {
_patch[Customer$.isVerified] = value;
return this;
}
CustomerPatch withverifiedAt(DateTime? value) {
_patch[Customer$.verifiedAt] = value;
return this;
}
CustomerPatch withbannedAt(DateTime? value) {
_patch[Customer$.bannedAt] = value;
return this;
}
} |
Hey @arrrrny I'm gonna try to take a look today or tomorrow. Bit of a backlog of work here but you have been on my mind! |
Hi @atreeon take your time. I will create another PR for you to see where I am latest. I implemented an amazing patching mechanism, that I just tested and works great. the only issue with that is, I completely neglected the Generic, as I was not in need and I immediately needed a working version. I will show the example of whats new on that branch. |
This was an important feature for me to move from freezed to Morphy. dont mind the many git commits and reverts, I was learning the package:
Key changes:
fixes #4
I added the explicitToJson parameter decorator from @miklcct commits. Howver all the __ typedefs to only support a variable named 'Type' is unneccsary. So I removed them.
The tests only fail at the part where I chaged the if else to switch and used interface .fromJson for subtypes. it works smoothly and allow the outside file reference for sub types.
@atreeon thanks for the nice package, if you merge this PR, I will keep contributing to it. I am moving away from freezed to morphy.
Here is my source file app_user.dart
and firebase_user.dart
and supabase_user.dart
and here is the beautifully generated app_user.morphy.dart
and the firebase
app_user_g.dart