smart_mapper 0.2.0
smart_mapper: ^0.2.0 copied to clipboard
Compile-time Clean Architecture mapping annotations for DTOs, local models, and domain entities.
smart_mapper #
Focused object mapping for Clean Architecture boundaries. It generates small, plain Dart mappers between Remote DTOs, Local Models, and Domain Entities.
Setup #
Add runtime annotations and generator:
dependencies:
smart_mapper: ^0.2.0
dev_dependencies:
build_runner: ^2.16.0
smart_mapper_generator: ^0.2.0
Define an abstract mapper. Same-name, assignable properties map automatically. Declare renames and converters explicitly:
import 'package:smart_mapper/smart_mapper.dart';
part 'user_mapper.g.dart';
@SmartMapper()
abstract class UserMapper {
@MapField(
target: 'name',
source: 'fullName',
using: 'normalizeName',
)
User map(UserResponse source);
UserBox toLocal(UserResponse source);
User fromLocal(UserBox source);
}
String normalizeName(String value) => value.trim();
Generate code:
dart run build_runner build
Use generated factory:
final mapper = createUserMapper();
final user = mapper.map(response);
Generated implementation stays intentionally boring: constructor calls, property reads, and explicit converter calls.
Strict validation #
Every direct assignment is checked with analyzer's type system. Invalid boundaries fail during generation instead of producing broken Dart:
Cannot assign String? to DateTime for Homework.dueDate.
Use a top-level converter when source and target types differ:
@MapField(target: 'createdAt', source: 'createdAt', using: 'parseDate')
Profile fromRemote(ProfileDto source);
DateTime parseDate(String value) => DateTime.parse(value);
Constructor controls #
@MapConstructor('fromDto')
@MapIgnore('id')
@MapDefault(target: 'status', value: 'active')
Profile fromRemote(ProfileDto source);
MapDefault accepts constant null, bool, numbers, strings, lists, sets,
and maps.
Nested collections and ObjectBox ToMany #
Declare item mapping methods beside parent mapping methods:
@SmartMapper()
abstract class ScheduleMapper {
Schedule fromRemote(ScheduleDto source);
ScheduleItem itemFromRemote(ScheduleItemDto source);
@MapRelation(
target: 'monday',
source: 'monday',
using: 'itemToLocal',
)
ScheduleBox toLocal(Schedule source);
ScheduleItemBox itemToLocal(ScheduleItem source);
Schedule fromLocal(ScheduleBox source);
ScheduleItem itemFromLocal(ScheduleItemBox source);
}
List, Set, and Iterable collections use matching item mappers. ObjectBox
relations require @MapRelation; no relation is mutated implicitly. A target
ToMany<TargetItem> field is populated after construction:
final target = ScheduleBox(group: source.group);
target.monday.addAll(source.monday.map(itemToLocal));
return target;
Missing or ambiguous item mapper methods fail during generation.
ObjectBox ToOne is also supported. Nullable targets remain nullable, with
converter calls guarded against null.
Scope #
Version 0.2.0 supports synchronous methods with exactly one required
positional source parameter and target types with an unnamed generative or
factory constructor. Named constructors, nested List/Set/Iterable,
nullable collections/items, and ObjectBox ToMany/ToOne relations are
supported. Async and update-in-place mapping remain outside current scope.