Generate Clean Architecture entities with Zorphy using consistent patterns for polymorphism, factories, nested objects, generics, patching, and JSON serialization.
CLI:
dart run zorphy create --name User --output lib/src/domain/entities
MCP:
mcp__zuraffa__generate --name User --output lib/src/domain/entities --generate_json true
import 'package:zorphy_annotation/zorphy_annotation.dart';
part 'user.zorphy.dart';
@Zorphy()
abstract class $User {
String get id;
String get name;
int get age;
String? get email;
}
final user = User(id: '1', name: 'Alice', age: 30);
final updated = user.copyWith(name: 'Bob');
import 'package:zorphy_annotation/zorphy_annotation.dart';
part 'payment_method.zorphy.dart';
@Zorphy(
generateJson: true,
explicitSubTypes: [$CreditCard, $PayPal, $BankTransfer],
)
abstract class $$PaymentMethod {
String get displayName;
double get amount;
}
@Zorphy(generateJson: true)
abstract class $CreditCard implements $$PaymentMethod {
String get cardNumber;
String get expiryDate;
@override
String get displayName => 'Credit Card';
}
@Zorphy(generateJson: true)
abstract class $PayPal implements $$PaymentMethod {
String get email;
String get transactionId;
@override
String get displayName => 'PayPal';
}
@Zorphy(generateJson: true)
abstract class $BankTransfer implements $$PaymentMethod {
String get accountNumber;
String get routingNumber;
String get bankName;
@override
String get displayName => 'Bank Transfer';
}
final payments = <PaymentMethod>[
CreditCard(displayName: 'John', cardNumber: '****1234', expiryDate: '12/25', amount: 100),
PayPal(displayName: 'Jane', email: '[email protected]', transactionId: 'txn_123', amount: 50),
];
for (final payment in payments) {
payment.when(
creditCard: (cc) => print(cc.cardNumber),
payPal: (pp) => print(pp.email),
bankTransfer: (bt) => print(bt.bankName),
);
}
@Zorphy(
generateJson: true,
explicitSubTypes: [$FileAttachment, $LinkAttachment],
nonSealed: true,
)
abstract class $$Attachment {
String get name;
String get mimeType;
List<int> get bytes;
}
@Zorphy(generateJson: true)
abstract class $FileAttachment implements $$Attachment {
String get filePath;
int get fileSize;
@override
String get name => 'File';
}
@Zorphy(generateJson: true)
abstract class $LinkAttachment implements $$Attachment {
String get url;
String get title;
@override
String get name => 'Link';
}
void processPayment(PaymentMethod method) {
switch (method) {
case CreditCard cc:
print(cc.cardNumber);
break;
case PayPal pp:
print(pp.email);
break;
case BankTransfer bt:
print(bt.bankName);
break;
}
}
final json = CreditCard(
displayName: 'John',
cardNumber: '1234',
expiryDate: '12/25',
amount: 100.0,
).toJson();
final restored = PaymentMethod.fromJson(json);
print(restored.runtimeType);
@Zorphy(generateJson: true)
abstract class $Chat {
String? get id;
String get title;
List<$$ChatMessage> get messages;
DateTime get createdAt;
DateTime? get updatedAt;
static Chat create({required String title, List<$$ChatMessage>? initialMessages}) => Chat(
title: title,
messages: initialMessages ?? [],
createdAt: DateTime.now(),
);
}
@Zorphy()
abstract class $Order {
String get orderId;
String get customerId;
List<$OrderItem> get items;
double get total;
static Order create({required String customerId, required List<$OrderItem> items}) {
final total = items.fold(0.0, (sum, item) => sum + item.price * item.quantity);
return Order(
orderId: 'ORD-${DateTime.now().millisecondsSinceEpoch}',
customerId: customerId,
items: items,
total: total,
);
}
}
@Zorphy()
abstract class $Address {
String get street;
String get city;
String get state;
String get zipCode;
}
@Zorphy()
abstract class $Person {
String get name;
int get age;
$Address get address;
}
@Zorphy(generateJson: true)
abstract class $CategoryNode {
String get id;
String get name;
List<$CategoryNode>? get children;
$CategoryNode? get parent;
}
final patched = person.patchWithPerson(
patchInput: PersonPatch.create()
..withAddressPatch(
AddressPatch.create()..withCity('Los Angeles'),
),
);
@Zorphy(generateJson: true)
abstract class $Result<T> {
bool get success;
T? get data;
String? get errorMessage;
}
@Zorphy(generateJson: true)
abstract class $KeyValue<K, V> {
K get key;
V get value;
}
@Zorphy(generateJson: true)
abstract class $PaginatedResponse<T> {
List<T> get items;
int get currentPage;
int get totalPages;
int get totalItems;
bool get hasNextPage;
}
@Zorphy(generateJson: true)
abstract class $Product {
String get id;
String get name;
double get price;
DateTime get createdAt;
}
final json = product.toJson();
final lean = product.toJsonLean();
final restored = Product.fromJson(json);
final updated = user.copyWith(name: 'Bob');
final changed = user.copyWith(name: 'Charlie', age: 31);
final withoutEmail = user.copyWith(email: null);
final patch = UserPatch.create()
..withName('Alice Smith')
..withAge(31);
final patched = user.patchWithUser(patchInput: patch);
@Zorphy()
abstract class $Timestamped {
DateTime get createdAt;
DateTime? get updatedAt;
}
@Zorphy()
abstract class $Identified {
String get id;
}
@Zorphy()
abstract class $Post implements $Timestamped, $Identified {
String get title;
String get content;
String get authorId;
}
enum UserStatus { active, inactive, suspended, pending }
@Zorphy(generateJson: true)
abstract class $Account {
String get username;
UserStatus get status;
DateTime get createdAt;
}
@Zorphy(explicitSubTypes: [$Circle, $Rectangle])
abstract class $$Shape {
String get name;
}
final rectangle = circle.changeToRectangle(width: 10.0, height: 15.0);
@Zorphy(generateCompareTo: true, generateJson: true)
abstract class $Document {
String get title;
String get content;
int get version;
List<String> get tags;
}
final diff = doc1.compareToDocument(doc2);
final updated = doc1.patchWithDocument(patchInput: DocumentPatch.create()..withContent(doc2.content));
lib/src/domain/entities/
├── user/
│ ├── user.dart
│ ├── user.zorphy.dart
│ └── user.g.dart
├── payment_method/
│ ├── payment_method.dart
│ ├── credit_card/
│ │ └── credit_card.dart
│ ├── pay_pal/
│ │ └── pay_pal.dart
│ └── bank_transfer/
│ └── bank_transfer.dart
└── enums/
├── index.dart
└── user_status.dart