zorphy
Dart/Flutter용 강력한 코드 생성 패키지로, copyWith, JSON 직렬화, toString, 동등성 및 상속 지원을 포함한 깔끔한 클래스 정의를 제공합니다
🦒 Zuraffa용 다형성 클래스 생성기. Dart 및 Flutter 클린 아키텍처 프레임워크
Dart/Flutter용 강력한 코드 생성 패키지로, copyWith, JSON 직렬화, toString, 동등성 및 상속 지원을 포함한 깔끔한 클래스 정의를 제공합니다
zorphy 코드 생성 패키지용 주석으로, copyWith, JSON 직렬화, toString, 동등성 및 상속을 지원하는 깔끔한 클래스 정의를 제공합니다
아래는 영문 원문 스냅샷입니다. 최신 내용은 GitHub에서 확인하세요.
Zorphy is a powerful code generation package for Dart/Flutter that provides clean, immutable class definitions with advanced features including copyWith methods, JSON serialization, equality, toString, inheritance support, and sophisticated patch mechanisms.
https://zuzu.dev Sponsored by ZikZak AI
Thanks to ZikZak AI for sponsoring this project!
ZikZak AI is an AI-Powered Price Comparison app that you scan barcodes, and discover amazing savings instantly. Your personal shopping assistant that never sleeps.
https://raw.githubusercontent.com/arrrrny/zorphy/HEAD/assets/app-store-badge.png https://raw.githubusercontent.com/arrrrny/zorphy/HEAD/assets/google-play-badge.png
Visit the official documentation at arrrrny.github.io/zorphy for detailed guides, examples, and API references.
You can also find the package on pub.dev.
copyWith methods for creating modified copiescopyWithField(Field<E, T> field, T value) replaces a single field via the typed Field selector; passing null to a nullable field preserves the current valuetoJson/fromJson support with polymorphic type handling== operator and hashCodeBoth generate immutable data classes. Zorphy goes further — it is a full entity toolkit with a nested patch system, filter/query descriptors, compareTo diffs, and an AI-agent CLI/MCP server.
| Capability | zorphy 2.0 | freezed 3.2.5 |
|---|---|---|
| Immutable data classes + copyWith | ✅ | ✅ |
Function-based copyWith (copyWithFn) |
✅ opt-in (ZorphyPreset.full) |
❌ |
JSON + polymorphic discriminators + toJsonLean |
✅ | ✅ (no toJsonLean) |
| Sealed unions | ✅ sealed $$Base + Dart 3 pattern matching |
✅ via when/map helpers |
| Nested patch system (partial updates of deep graphs) | ✅ UserPatch()..withAddressPatch(...) |
❌ manual nested copyWith chains |
Filter/query descriptors (Field<E, T>) |
✅ | ❌ |
| compareTo diffs between instances | ✅ | ❌ |
| changeTo conversions between subtypes | ✅ | ❌ |
| Multiple interface inheritance with generics | ✅ | ❌ |
| Self-referencing types | ✅ | ✅ |
| CLI + MCP server for scaffolding | ✅ | ❌ |
| Output size control | ✅ ZorphyPreset.lean/standard/full + per-feature flags |
❌ |
| analyzer 14 support | ✅ >=13.0.0 <15.0.0 |
❌ caps analyzer <11.0.0 (as of 2026-07-30) |
Where freezed differs (honest notes): freezed's mixin pattern
(with _$Foo) keeps the annotated class itself concrete; zorphy uses
abstract class $Foo + generated Foo. freezed's when/map helpers
are answered in zorphy by Dart 3's native exhaustive switch on the
sealed base. Freezed's ecosystem is older and larger.
1. Simple data class — freezed:
@freezed
class User with _$User {
const factory User({required String id, required String name, String? email}) = _User;
factory User.fromJson(Map<String, dynamic> json) => _$UserFromJson(json);
}
zorphy (lean preset — no patch/filter/compareTo bloat):
@Zorphy(preset: ZorphyPreset.lean, generateJson: true)
abstract class $User {
String get id;
String get name;
String? get email;
}
2. Sealed union — freezed:
@freezed
class Result with _$Result {
const factory Result.ok(String value) = Ok;
const factory Result.err(String message) = Err;
}
zorphy (real sealed hierarchy, exhaustive Dart 3 switch):
@Zorphy(explicitSubTypes: [$Ok, $Err])
abstract class $$Result {}
@Zorphy()
abstract class $Ok implements $$Result { String get value; }
@Zorphy()
abstract class $Err implements $$Result { String get message; }
String describe(Result r) => switch (r) {
Ok(:final value) => 'ok: $value',
Err(:final message) => 'err: $message', // exhaustive — no default needed
};
3. Nested partial update — freezed requires manual deep copyWith:
user.copyWith(address: user.address.copyWith(city: 'Berlin'));
zorphy's patch system composes:
final patch = ProfilePatch()
..withName('Ada')
..withAddressPatch(AddressPatch()..withCity('Berlin'));
final updated = patch.applyTo(profile);
All three zorphy examples are real, compilable code — see
zorphy/example/lib/comparison/.
Migrating from freezed? Use the
zorphy_migrator codemod:
dart pub global activate zorphy_migrator
zorphy_migrator migrate lib/ --dry-run # preview unified diff
zorphy_migrator migrate lib/ --apply --report MIGRATION.md
It converts simple classes, sealed unions, @Default, @JsonKey, and
fromJson/toJson automatically, and reports anything that needs human
attention with file:line — nothing is silently dropped. See the
migration guide.
Add the dependencies to your pubspec.yaml:
dependencies:
zorphy_annotation: ^2.4.3
dev_dependencies:
zorphy: ^2.4.3
build_runner: ^2.4.0
Install the CLI globally:
dart pub global activate zorphy
The Zorphy CLI is designed for optimal AI agent usage:
# Create entity
zorphy create -n User
# Create with fields
zorphy create -n Product \
--field name:String \
--field price:double \
--field inStock:bool
# Quick create (simple entity with defaults)
zorphy new -n Category
# Build all entities
zorphy build
# List entities
zorphy list
Or create classes manually:
import 'package:zorphy_annotation/zorphy_annotation.dart';
part 'user.zorphy.dart';
@Zorphy()
abstract class $User {
String get name;
int get age;
String? get email;
}
Run the generator:
dart run build_runner build
Use the generated class:
void main() {
final user = User(name: 'Alice', age: 30);
// Copy with changes
final olderUser = user.copyWith(age: 31);
// Convert to JSON (if generateJson: true)
final json = user.toJson();
// Create from JSON
final fromJson = User.fromJson(json);
}
The Zorphy CLI provides an intuitive interface for creating and managing entities, optimized for both human developers and AI agents.
# Install globally
dart pub global activate zorphy
# Or run directly
dart run zorphy:zorphy_cli
create - Create New EntityCreate a new Zorphy entity with full control over options:
zorphy create [options]
Options:
-n, --name - Entity name (required)-o, --output - Output directory (default: lib/src/domain/entities)-p, --package - Package name for imports--json - Enable JSON serialization (default: true)--copywith-fn - Enable function-based copyWith (default: false)--compare - Enable compareTo (default: true)--filter - Enable filter descriptors (default: false)--sealed - Create sealed class (default: false)--non-sealed - Create non-sealed class (default: false)--field - Add fields directly (name:type or name:type?), repeatable--extends - Interface to extend (e.g., $BaseEntity)--subtypes - Explicit subtypes for polymorphism (repeatable)--generate-subs - Auto-generate subtype stubs for sealed classes--dry-run - Preview generated code without writing filesExamples:
# Create with fields
zorphy create -n User \
--field name:String \
--field age:int \
--field email:String?
# With all options
zorphy create -n Product \
--output lib/models \
--json \
--compare \
--field name:String \
--field price:double \
--field category:String?
# Sealed class with subtypes
zorphy create -n Result --sealed \
--subtypes Ok \
--subtypes Err
# Dry run (preview only)
zorphy create -n User --field name:String --dry-run
# With inheritance
zorphy create -n Admin \
--extends '$User' \
--field permissions:List<String>
new - Quick CreateCreate a simple entity with default settings:
zorphy new -n EntityName
Options:
-n, --name - Entity name (required)-o, --output - Output directory (default: lib/src/domain/entities)--json - Enable JSON (default: true)Example:
zorphy new -n Product
build - Run Code GenerationGenerate code for all Zorphy entities:
zorphy build [options]
Options:
-w, --watch - Watch for changes (default: false)-c, --clean - Clean before build (default: false)--dry-run - Preview without writing (default: false)--force - Force rebuild even if up to date (default: false)Examples:
# Build once
zorphy build
# Clean and build
zorphy build --clean
# Watch mode
zorphy build --watch
# Force rebuild
zorphy build --force
list - List EntitiesList all Zorphy entities in a directory:
zorphy list [options]
Options:
-o, --output - Directory to search (default: lib/src/domain/entities)Example:
zorphy list
# Output:
# 📂 Zorphy Entities in lib/src/domain/entities:
#
# 📄 User
# File: lib/src/domain/entities/user.dart
# ✓ JSON support
# ✓ Function-based copyWith
#
# Total: 1 entity/entities
The CLI supports various field types:
String, int, double, bool, num, DateTime? after type (e.g., String?, int?)List<Type>, Set<Type>, Map<KeyType, ValueType>Examples:
--field name:String
--field age:int
--field email:String?
--field tags:List<String>
--field metadata:Map<String, dynamic>
--field createdAt:DateTime
enum - Create EnumCreate a new Zorphy-compatible enum:
zorphy enum -n Status --value active,inactive,pending
Options:
-n, --name - Enum name (required)--value - Comma-separated enum values (required)-o, --output - Output directory (default: lib/src/domain/entities)Example:
zorphy enum -n UserRole --value admin,user,guest
add-field - Add Field to Existing EntityAdd a field to an existing Zorphy entity file:
zorphy add-field -n User -f email:String?
Options:
-n, --name - Entity name (required)-f, --field - Field to add (name:type or name:type?) (required)Example:
zorphy add-field -n User -f avatarUrl:String?
zorphy add-field -n Product -f tags:List<String>
watch - Watch and RebuildWatch for file changes and automatically rebuild:
zorphy watch
from-json - Create Entity from JSONGenerate a Zorphy entity from a JSON sample:
zorphy from-json -n User --json-input '{"name": "Alice", "age": 30}'
Options:
-n, --name - Entity name (required)--json-input - JSON string to generate from (required)-o, --output - Output directory (default: lib/src/domain/entities)The Model Context Protocol (MCP) server enables AI agents like Claude to programmatically create and manage Zorphy entities.
Add to your Claude/MCP client configuration:
{
"mcpServers": {
"zorphy": {
"command": "zorphy_mcp_server"
}
}
}
The
zorphy_mcp_serverexecutable is registered when you rundart pub global activate zorphy. Alternatively, usedart run zorphy:zorphy_mcp_server.
create_entityCreate a new Zorphy entity programmatically.
Parameters:
{
"name": "string (required)",
"outputDir": "string (default: lib/src/domain/entities)",
"package": "string (optional)",
"generateJson": "boolean (default: true)",
"generateCompareTo": "boolean (default: true)",
"sealed": "boolean (default: false)",
"nonSealed": "boolean (default: false)",
"extends": "string (optional)",
"explicitSubTypes": ["string"],
"fields": [
{
"name": "string",
"type": "string"
}
]
}
Note: Parameters are flat (no nested
optionsobject). Fields use the?suffix in the type string for nullable fields (e.g.,"type": "String?").
Example:
{
"name": "User",
"fields": [
{ "name": "id", "type": "String" },
{ "name": "name", "type": "String" },
{ "name": "email", "type": "String?" },
{ "name": "age", "type": "int" }
],
"generateJson": true,
"generateCompareTo": true
}
create_enumCreate a new Zorphy-compatible enum.
Parameters:
{
"name": "string (required)",
"values": ["string (required)"],
"outputDir": "string (default: lib/src/domain/entities)"
}
Example:
{
"name": "UserRole",
"values": ["admin", "user", "guest"]
}
add_fieldAdd a field to an existing Zorphy entity.
Parameters:
{
"name": "string (required) — entity name",
"fields": [
{
"name": "string (required)",
"type": "string (required)"
}
]
}
Example:
{
"name": "User",
"fields": [{ "name": "avatarUrl", "type": "String?" }]
}
list_entitiesList all Zorphy entities in a directory.
Parameters:
{
"directory": "string (default: lib/src/domain/entities)"
}
Example 1: Agent Creating a User Entity
# Agent using MCP server
mcp.call_tool("create_entity", {
"name": "User",
"fields": [
{"name": "id", "type": "String"},
{"name": "username", "type": "String"},
{"name": "email", "type": "String?"},
{"name": "createdAt", "type": "DateTime"}
],
"generateJson": True,
"generateCompareTo": True
})
Example 2: Agent Creating a Sealed Hierarchy
# Create the sealed base
mcp.call_tool("create_entity", {
"name": "PaymentMethod",
"sealed": True,
"explicitSubTypes": ["$CreditCard", "$PayPal"]
})
# Create each variant
mcp.call_tool("create_entity", {
"name": "CreditCard",
"extends": "$$PaymentMethod",
"fields": [
{"name": "cardNumber", "type": "String"},
{"name": "expiryDate", "type": "String"}
]
})
mcp.call_tool("create_entity", {
"name": "PayPal",
"extends": "$$PaymentMethod",
"fields": [
{"name": "email", "type": "String"}
]
})
Example 3: Agent Adding a Field and Listing Entities
# List existing entities
entities = mcp.call_tool("list_entities", {})
# Add a field to an existing entity
mcp.call_tool("add_field", {
"name": "User",
"fields": [{"name": "avatarUrl", "type": "String?"}]
})
# Create an enum
mcp.call_tool("create_enum", {
"name": "UserRole",
"values": ["admin", "user", "guest"]
})
Use a single $ prefix for concrete classes:
@Zorphy()
abstract class $Person {
String get firstName;
String get lastName;
int? get age;
}
// Usage: Omit the $ when using
final person = Person(firstName: 'John', lastName: 'Doe');
Use $$ prefix for sealed abstract classes. Sealed classes enable exhaustiveness checking:
@Zorphy()
abstract class $$Shape {
double get area;
}
@Zorphy()
abstract class $Circle implements $$Shape {
double get radius;
@override
double get area => 3.14159 * radius * radius;
}
@Zorphy()
abstract class $Rectangle implements $$Shape {
double get width;
double get height;
@override
double get area => width * height;
}
// Exhaustiveness checking
String describeShape(Shape shape) => switch (shape) {
Circle() => 'A circle',
Rectangle() => 'A rectangle',
};
Use nonSealed: true to create non-sealed abstract classes:
@Zorphy(nonSealed: true)
abstract class $$BaseEntity {
String get id;
DateTime get createdAt;
}
Enable JSON generation with generateJson: true:
@Zorphy(generateJson: true)
abstract class $User {
String get id;
String get name;
String? get email;
}
Features:
toJson() and fromJson()toJsonLean() removes metadata for cleaner output@Zorphy()
abstract class $$Animal {}
@Zorphy(generateJson: true)
abstract class $Dog implements $$Animal {
String get breed;
}
@Zorphy(generateJson: true)
abstract class $Cat implements $$Animal {
double get whiskerLength;
}
// Serialization includes type discriminator
final dog = Dog(breed: 'Labrador');
final json = dog.toJson();
// {"__typename": "Dog", "breed": "Labrador"}
// Deserialization automatically handles type
final animal = Animal.fromJson(json);
print(animal); // Instance of Dog
@Zorphy()
abstract class $User {
String get name;
int get age;
}
final user = User(name: 'Alice', age: 30);
final updated = user.copyWith(name: 'Bob');
// User(name: 'Bob', age: 30)
Enable with generateCopyWithFn: true:
@Zorphy(generateCopyWithFn: true)
abstract class $Counter {
int get value;
}
final counter = Counter(value: 0);
final incremented = counter.copyWithCounterFn(
value: () => counter.value + 1,
);
// Counter(value: 1)
@Zorphy()
abstract class $Pet {
String get name;
int get age;
}
@Zorphy()
abstract class $Dog implements $Pet {
String get breed;
}
final dog = Dog(name: 'Buddy', age: 5, breed: 'Labrador');
final updated = dog.copyWithDog(breed: 'Golden Retriever');
// Updates only Dog-specific fields
The patch system provides powerful partial updates with nested support:
@Zorphy()
abstract class $User {
String get name;
int get age;
}
// Create a patch
final patch = UserPatch.create()
..withName('New Name')
..withAge(25);
// Apply patch
final updated = user.patchWithUser(patchInput: patch);
@Zorphy()
abstract class $Address {
String get street;
String get city;
}
@Zorphy()
abstract class $User {
String get name;
Address get address;
}
// Nested patching
final patch = UserPatch.create()
..withName('Updated Name')
..withAddressPatch((addrPatch) => addrPatch
..withStreet('123 New St')
..withCity('New York'));
final updated = user.patchWithUser(patchInput: patch);
@Zorphy()
abstract class $TodoList {
String get title;
List<Todo> get todos;
}
// Update specific item in list
final patch = TodoListPatch.create()
..updateTodosAt(0, (todoPatch) => todoPatch
..withCompleted(true)
..withTitle('Updated Title'));
// Using functions for computed updates
final patch = CounterPatch.create()
..withValue((current) => current + 1);
final updated = counter.patchWithCounter(patchInput: patch);
@Zorphy()
abstract class $Pet {
String get name;
int get age;
}
@Zorphy()
abstract class $Dog {
String get barkSound;
}
@Zorphy()
abstract class $Cat {
double get whiskerLength;
}
// Implement multiple interfaces
@Zorphy()
abstract class $FrankensteinsDogCat implements $Dog, $Pet, $Cat {
// Inherits all fields from all interfaces
}
@Zorphy()
abstract class $$Repository<T> {
T? find(String id);
List<T> getAll();
}
@Zorphy()
abstract class $UserRepository implements $$Repository<User> {
@override
User? find(String id);
@override
List<User> getAll();
}
@Zorphy()
abstract class $$Base<T> {
T get value;
}
@Zorphy()
abstract class $Derived<T extends num> implements $$Base<T> {
@override
T get value;
T get doubled => value * 2;
}
Use explicitSubTypes to enable cross-type operations:
@Zorphy(explicitSubTypes: [$Dog, $Cat])
abstract class $Pet {
String get name;
int get age;
}
@Zorphy()
abstract class $Dog implements $Pet {
String get breed;
}
@Zorphy()
abstract class $Cat implements $Pet {
double get whiskerLength;
}
This generates changeTo methods:
final dog = Dog(name: 'Buddy', age: 5, breed: 'Labrador');
// Convert Dog to Cat
final cat = dog.changeToCat(whiskerLength: 3.5);
// Cat(name: 'Buddy', age: 5, whiskerLength: 3.5)
Generate comparison methods showing differences between instances:
@Zorphy(generateCompareTo: true)
abstract class $User {
String get name;
int get age;
}
final user1 = User(name: 'Alice', age: 30);
final user2 = User(name: 'Alice', age: 35);
final diff = user1.compareToUser(user2);
// {'age': () => 35}
Full enum integration with JSON serialization:
enum Status {
active,
inactive,
pending,
}
@Zorphy(generateJson: true)
abstract class $User {
String get name;
Status get status;
}
final user = User(name: 'Alice', status: Status.active);
final json = user.toJson();
// {"name": "Alice", "status": "active"}
final fromJson = User.fromJson(json);
// User(name: 'Alice', status: Status.active)
Handle tree structures and hierarchical data:
@Zorphy(generateJson: true)
abstract class $TreeNode {
String get value;
List<TreeNode>? get children;
TreeNode? get parent;
}
final tree = TreeNode(
value: 'root',
children: [
TreeNode(value: 'child1'),
TreeNode(value: 'child2'),
],
);
Support for custom factory constructors:
@Zorphy()
abstract class $Person {
String get firstName;
String get lastName;
// Custom factory method
factory $Person.fromNames(String first, String last) = _PersonFromNames;
// Default factory
factory $Person.empty() => Person(firstName: '', lastName: '');
}
class _PersonFromNames extends Person {
_PersonFromNames({
required String first,
required String last,
}) : super(
firstName: first.toUpperCase(),
lastName: last.toUpperCase(),
);
}
// Usage
final person = Person.fromNames('john', 'doe');
// Person(firstName: 'JOHN', lastName: 'DOE')
Use underscore suffix to hide public constructor:
@Zorphy(hidePublicConstructor: true)
abstract class $Config_ {
String get apiKey;
String get endpoint;
}
// Define custom factory in the same file
Config createProductionConfig() {
return Config._(
apiKey: 'prod-key',
endpoint: 'https://api.prod.com',
);
}
Config createDevConfig() {
return Config._(
apiKey: 'dev-key',
endpoint: 'https://api.dev.com',
);
}
// Usage - Config() constructor is not available
final config = createProductionConfig();
Enable constant constructors for immutable values:
@Zorphy()
abstract class $Color {
int get red;
int get green;
int get blue;
const $Color();
}
// Usage
const red = Color(red: 255, green: 0, blue: 0);
Full null safety support:
@Zorphy()
abstract class $User {
String get name;
String? get email;
String? get phone;
}
final user = User(name: 'Alice');
// email and phone are null
final withEmail = user.copyWith(email: 'alice@example.com');
@Zorphy()
abstract class $Company {
String get name;
List<Department> get departments;
}
@Zorphy()
abstract class $Department {
String get name;
List<Employee> get employees;
}
@Zorphy()
abstract class $Employee {
String get name;
String? get title;
}
// Deep nesting with proper JSON support
final company = Company(
name: 'Tech Corp',
departments: [
Department(
name: 'Engineering',
employees: [
Employee(name: 'Alice', title: 'Engineer'),
],
),
],
);
typedef JsonConverter<T> = T Function(dynamic);
@Zorphy()
abstract class $ApiResponse<T> {
bool get success;
T? get data;
String? get error;
}
@Zorphy()
abstract class $UserListResponse implements $ApiResponse<List<User>> {
@override
bool get success;
@override
List<User>? get data;
@override
String? get error;
}
enum UserRole {
admin,
user,
guest,
}
@Zorphy(
generateJson: true,
generateCopyWithFn: true,
generateCompareTo: true,
)
abstract class $User {
String get id;
String get name;
String? get email;
int get age;
UserRole get role;
DateTime get createdAt;
List<String>? get tags;
}
// All features available
final user = User(
id: '1',
name: 'Alice',
age: 30,
role: UserRole.admin,
createdAt: DateTime.now(),
);
// CopyWith
final updated = user.copyWith(email: 'alice@example.com');
// Function-based CopyWith
final aged = user.copyWithUserFn(age: () => user.age + 1);
// Patch
final patched = user.patchWithUser(
patchInput: UserPatch.create()..withTags(['developer', 'dart']),
);
// CompareTo
final diff = user.compareToUser(updated);
// JSON
final json = user.toJson();
final fromJson = User.fromJson(json);
The @Zorphy annotation supports these options:
| Option | Type | Default | Description |
|---|---|---|---|
preset |
ZorphyPreset? |
null |
Preset that controls defaults for multiple options (lean, standard, full). When set, per-flag defaults inherit from the preset |
generateJson |
bool |
false |
Enable JSON serialization (toJson/fromJson) |
generateCopyWith |
bool? |
null |
Generate copyWith methods; inherits from preset if null |
generateCopyWithFn |
bool? |
null |
Generate function-based copyWith methods; inherits from preset if null |
generatePatch |
bool? |
null |
Generate patch classes for partial updates; inherits from preset if null |
generateFilter |
bool? |
null |
Generate filter/query descriptor fields; inherits from preset if null |
generateCompareTo |
bool? |
null |
Generate comparison methods; inherits from preset if null |
generatePropertyHelpers |
bool? |
null |
Generate property helper extensions; inherits from preset if null |
generateEqualsToString |
bool? |
null |
Generate ==, hashCode, and toString; inherits from preset if null |
generateChangeTo |
bool? |
null |
Generate changeTo conversion methods between subtypes; inherits from preset if null |
explicitSubTypes |
List<Type> |
null |
Specify explicit subtypes for polymorphic operations |
explicitToJson |
bool |
true |
Control JSON serialization generation |
hidePublicConstructor |
bool |
false |
Hide the public constructor for custom factories |
nonSealed |
bool |
false |
Create non-sealed abstract classes instead of sealed |
By default, Zorphy runs as part of the build process. The builder is configured in build.yaml:
targets:
$default:
builders:
zorphy:zorphy:
enabled: true
Run the generator:
# Build once
dart run build_runner build
# Build and watch for changes
dart run build_runner watch
# Clean generated files
dart run build_runner clean
# Or use the CLI
zorphy build
zorphy build --watch
zorphy build --clean
$ClassName - Concrete class definition (use ClassName in code)$$ClassName - Sealed abstract class (exhaustiveness checking)$ClassName_ - Class with hidden private constructor*.zorphy.dart - Generated code from @Zorphy annotationClassName$ - Enum of field names for patch systemClassNamePatch - Patch class for partial updatesZorphy is designed for easy migration from Morphy:
@Morphy with @Zorphymorphy_annotation dependency with zorphy_annotationzikzak_morphy dependency with zorphydart run build_runner cleandart run build_runner buildKey Differences:
If you get type not found errors, ensure:
part 'filename.zorphy.dart'; to your filedart run build_runner build or zorphy buildpackage:zorphy_annotation/zorphy_annotation.dartWhen using generics, ensure type parameter names match between parent and child:
// ✅ Correct - Same generic name
abstract class $A<T> { }
abstract class $B<T> implements $A<T> { }
// ❌ Wrong - Different generic names
abstract class $A<T1> { }
abstract class $B<T2> implements $A<T1> { }
Note:
@Zorphy2is deprecated in v2. The single-pass v2 generator handles ordering automatically — you no longer need to annotate build-order dependencies manually.
If you are migrating from v1 code that uses @Zorphy2, simply replace all @Zorphy2() annotations with @Zorphy() — the v2 generator will resolve the correct build order.
MIT License - see LICENSE file for details
Inspired by and designed to improve upon the Morphy code generation package.
Made with 🔥 by the ZikZak AI team for the community and AI agents