axor_generator 1.0.0
axor_generator: ^1.0.0 copied to clipboard
Code generator for Axor NoSQL database that creates type-safe models, adapters, and query extensions at build time.
Axor Generator - Code Generation for Axor Database #
Code generator for the Axor NoSQL database. This package provides build-time code generation for models, adapters, schemas, and type-safe query extensions.
π― What it generates #
- Schema classes with full type information
- Adapter classes for optimized JSON serialization
- Query extensions with type-safe methods like
.ageGreaterThan() - Collection accessors with compile-time validation
- Migration helpers for schema evolution
π¦ Installation #
Add to your pubspec.yaml:
dev_dependencies:
axor_generator: ^1.0.0
build_runner: ^2.4.7
π Usage #
1. Annotate your models #
import 'package:axor/axor.dart';
part 'user.g.dart'; // Important: add this line
@collection
class User {
Id id = Axor.autoIncrement;
@index
String name;
@index
String email;
int age;
Address? address;
}
@embedded
class Address {
String street;
String city;
Address({this.street = '', this.city = ''});
Map<String, dynamic> toJson() => {
'street': street,
'city': city,
};
factory Address.fromJson(Map<String, dynamic> json) => Address(
street: json['street'] ?? '',
city: json['city'] ?? '',
);
}
2. Run code generation #
# One-time generation
dart run build_runner build
# Watch for changes during development
dart run build_runner watch
3. Use generated code #
// Generated schema is automatically available
final axor = await Axor.open(schemas: [UserSchema]);
// Generated query extensions
final adults = await axor.users.ageGreaterThan(18).findAll();
final johns = await axor.users.nameStartsWith('John').findAll();
final locals = await axor.users.addressCityEqualTo('New York').findAll();
ποΈ Generated Code Structure #
For a model like User, the generator creates:
UserSchema #
class UserSchema extends GeneratedSchema<User> {
static const instance = UserSchema._();
String get name => 'users';
Type get type => User;
int get version => 1;
// Field definitions, indexes, serialization methods...
}
Query Extensions #
extension UserQueryExtensions on Query<User> {
// For each field, generates appropriate query methods
Query<User> nameEqualTo(String value) => equalTo('name', value);
Query<User> nameStartsWith(String value) => startsWith('name', value);
Query<User> ageGreaterThan(int value) => greaterThan('age', value);
Query<User> ageBetween(int lower, int upper) => between('age', lower, upper);
// Null checks
Query<User> nameIsNull() => isNull('name');
Query<User> nameIsNotNull() => isNotNull('name');
// Collection operations
Query<User> nameOneOf(List<String> values) => oneOf('name', values);
}
Collection Extensions #
extension UserCollectionExtensions on CollectionAccessor<User> {
// Convenient access methods
Query<User> findByName(String name) => filter().nameEqualTo(name);
Query<User> findActive() => filter().isActiveEqualTo(true);
Query<User> findAdults() => filter().ageGreaterThan(18);
}
βοΈ Configuration #
Configure the generator in build.yaml:
targets:
$default:
builders:
axor_generator|axor:
enabled: true
generate_for:
- lib/models/*.dart
options:
auto_dispose: true
nullable_safety: true
generate_copyWith: false
πͺ Supported Annotations #
@collection #
Marks a class as a database collection:
@Collection(name: 'custom_users') // Custom collection name
class User { ... }
@collection // Uses class name (snake_case)
class User { ... }
@index #
Creates indexes for fast queries:
@index
String email; // Simple index
@Index(type: IndexType.hash, unique: true)
String userId; // Hash index with unique constraint
@Index(composite: ['firstName', 'lastName'])
String fullName; // Composite index
@embedded #
For nested objects:
@embedded
class Address { ... }
@field #
Custom field configuration:
@Field(name: 'user_email', defaultValue: '')
String email;
@Field(maxLength: 100, required: true)
String name;
@ignore #
Exclude fields from database:
@ignore
String computedValue;
π§ Advanced Features #
Custom Serialization #
@Field(type: AxorType.string)
DateTime customDate; // Store DateTime as string
@Field(name: 'data_json')
Map<String, dynamic> metadata; // Custom field name
Validation #
@Field(minValue: 0, maxValue: 150)
int age;
@Field(pattern: r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$')
String email;
Migration Support #
The generator automatically creates migration code when schemas change:
// Generated migration code handles:
// - Adding new fields with default values
// - Renaming fields
// - Changing field types (with conversion)
// - Adding/removing indexes
π Troubleshooting #
Common Issues #
Build fails with "part file not found"
- Make sure you have
part 'filename.g.dart';in your model file - Run
dart run build_runner buildto generate the part file
"No schema found" error
- Ensure your model class has the
@collectionannotation - Check that the generated file is included in your imports
Generated methods not available
- Make sure you import the file containing your model
- The generated extensions should be automatically available
Hot reload not working with generated code
- Use
dart run build_runner watchduring development - Restart your app after major schema changes
Getting Help #
- Check the main Axor documentation
- File issues on GitHub
- Join our Discord community
π License #
This project is licensed under the MIT License - see the LICENSE file for details.