flutter_boilerplate_generator 2.3.0 copy "flutter_boilerplate_generator: ^2.3.0" to clipboard
flutter_boilerplate_generator: ^2.3.0 copied to clipboard

A Dart code generator for Flutter boilerplate: model, entity, hive, and cubit state. Generates JSON serialization, copyWith, value equality, entity/Hive mapping, and pattern-matching extensions.

flutter_boilerplate_generator #

Code generator untuk Flutter yang mengotomasi boilerplate pada Model dan CubitState: JSON serialization, entity/Hive mapping, copyWith, value equality, dan pattern-matching extensions.

Digunakan bersama flutter_boilerplate_annotations.


Daftar Isi #


Instalasi #

Tambahkan ke pubspec.yaml project Anda:

dependencies:
  flutter_boilerplate_annotations: ^1.0.1

dev_dependencies:
  build_runner: ^2.15.0
  flutter_boilerplate_generator: ^2.0.0

Kemudian jalankan:

dart pub get

Setup #

1. build.yaml (opsional, untuk kustomisasi output path) #

Tanpa konfigurasi tambahan, file .g.dart akan di-generate di direktori yang sama dengan source file. Jika ingin memisahkan file generated ke subfolder generated/:

# build.yaml (di root project Anda)
targets:
  $default:
    builders:
      flutter_boilerplate_generator|model:
        generate_for:
          - lib/**.dart
      flutter_boilerplate_generator|state:
        generate_for:
          - lib/**.dart
      source_gen:combining_builder:
        options:
          build_extensions:
            "^lib/model/{{file}}.dart": "lib/model/generated/{{file}}.g.dart"
            "^lib/state/{{file}}.dart": "lib/state/generated/{{file}}.g.dart"

2. Jalankan generator #

dart run build_runner build

Untuk mode watch (otomatis regenerate saat file berubah):

dart run build_runner watch

Annotations #

Import annotations dari package annotations:

import 'package:flutter_boilerplate_annotations/flutter_boilerplate_annotations.dart';

@Model #

Annotation utama untuk generate boilerplate pada class model.

const Model({
  Type? entity,              // Class domain entity untuk mapping
  Type? hiveObject,          // Class Hive object untuk mapping
  bool fromJson = true,      // Generate factory fromJson
  bool toJson = true,        // Generate method toJson
  bool fromEntity = false,   // Generate factory fromEntity
  bool toEntity = true,      // Generate method toEntity
  bool fromHiveObject = true, // Generate factory fromHiveObject
  bool toHiveObject = true,   // Generate method toHiveObject
  bool genericAugmented = false, // Aktifkan dukungan generic type <T>
})

Persyaratan class:

  • Harus abstract
  • Harus menggunakan with _$ClassName
  • Constructor utama harus const factory dengan redirecting ke _ClassName
  • Deklarasi part untuk file generated
import 'package:flutter_boilerplate_annotations/flutter_boilerplate_annotations.dart';

part 'generated/product_model.g.dart';

@Model(entity: ProductEntity, fromEntity: true, toEntity: true)
abstract class ProductModel with _$ProductModel {
  const factory ProductModel({
    int? id,
    String? name,
  }) = _ProductModel;

  factory ProductModel.fromJson(Map<String, dynamic> json) =>
      _$ProductModelFromJson(json);

  factory ProductModel.fromEntity(ProductEntity? entity) =>
      _$ProductModelFromEntity(entity);
}

@CubitState #

Annotation untuk generate sealed state class bergaya union type, lengkap dengan pattern-matching extensions.

const CubitState({
  bool when = true,        // Generate .when(...)
  bool maybeWhen = true,   // Generate .maybeWhen(...)
  bool whenOrNull = true,  // Generate .whenOrNull(...)
  bool map = true,         // Generate .map(...)
  bool maybeMap = true,    // Generate .maybeMap(...)
  bool mapOrNull = true,   // Generate .mapOrNull(...)
})

Persyaratan class:

  • Harus abstract
  • Setiap state adalah const factory yang meredirect ke class child
  • Nama child class diambil dari nama setelah =
import 'package:flutter_boilerplate_annotations/flutter_boilerplate_annotations.dart';

part 'generated/product_state.g.dart';

@CubitState()
abstract class ProductState {
  const factory ProductState.initial() = ProductInitial;
  const factory ProductState.loading() = ProductLoading;
  const factory ProductState.success({
    required List<ProductModel> products,
    @Default(0) int total,
  }) = ProductSuccess;
  const factory ProductState.failure({
    required String message,
    int? code,
  }) = ProductFailure;
}

@JsonKey #

Override nama key JSON untuk field tertentu.

class JsonKey {
  final String? name; // Nama key di JSON
  const JsonKey({this.name});
}

Penggunaan:

const factory ProductModel({
  @JsonKey(name: 'product_name') String? name,
  @JsonKey(name: 'created_at') DateTime? createdAt,
}) = _ProductModel;

JSON yang dihasilkan akan menggunakan product_name dan created_at sebagai key, bukan name dan createdAt.


@Default #

Memberikan nilai default pada field. Digunakan di dalam parameter constructor.

class Default {
  final Object? value;
  const Default(this.value);
}

Penggunaan di Model:

const factory ProductModel({
  @Default(0.0) double? price,
  @Default(0) int? stock,
  @Default(true) bool? isAvailable,
  @Default([]) List<String>? tags,
}) = _ProductModel;

Penggunaan di CubitState:

const factory ProductState.success({
  required List<ProductModel> products,
  @Default(0) int total,
}) = ProductSuccess;

@EnumValue #

Override nilai string yang digunakan saat enum di-serialize ke/dari JSON atau Hive.

class EnumValue {
  final String value;
  const EnumValue(this.value);
}

Penggunaan:

import 'package:flutter_boilerplate_annotations/flutter_boilerplate_annotations.dart';

enum ProductStatus {
  @EnumValue('active')
  active,

  @EnumValue('inactive')
  inactive,

  @EnumValue('pending_review')
  pendingReview, // → JSON value: "pending_review"
}

Tanpa @EnumValue, generator menggunakan nama field enum itu sendiri (pendingReview). Dengan @EnumValue, serialization menggunakan value yang ditentukan (pending_review).


Fitur yang Di-generate #

Model #

Semua fitur berikut di-generate otomatis dari satu @Model annotation:

== operator & hashCode

Membandingkan dua instance berdasarkan nilai seluruh field (value equality):

final a = ProductModel(id: 1, name: 'Apple');
final b = ProductModel(id: 1, name: 'Apple');

print(a == b);                    // true
print(a.hashCode == b.hashCode);  // true

toString

Menghasilkan representasi string yang mudah dibaca:

print(product.toString());
// ProductModel(id: 1, name: Apple, price: 10000.0, ...)

copyWith

Membuat salinan instance dengan mengganti nilai field tertentu:

final updated = product.copyWith(
  name: 'New Name',
  price: 15000.0,
);
// Field yang tidak diisi tetap sama dengan original

Untuk field bertipe model (non-primitive), tersedia nested copyWith:

final updated = product.copyWith.address(
  city: 'Jakarta',
);

toJson & fromJson

Serialisasi ke/dari Map<String, dynamic>:

// Serialize
final json = product.toJson();
// {'product_name': 'Apple', 'price': 10000.0, ...}

// Deserialize
final product = ProductModel.fromJson(json);

Tipe yang didukung:

Dart Type JSON Type
int number
double number
String string
bool boolean
DateTime string (ISO 8601)
Duration number (microseconds)
List<T> array
Map<K, V> object
Enum string (via @EnumValue)
Nested model object (via .fromJson())

Catatan: Field nullable yang bernilai null akan dihilangkan dari JSON output. Saat fromJson, field yang tidak ada di JSON akan bernilai null.

toEntity & fromEntity

Konversi antara model dan domain entity:

// Entity → Model
final model = ProductModel.fromEntity(productEntity);

// Model → Entity
final entity = model.toEntity();

Field yang namanya sama di antara model dan entity akan di-mapping otomatis. Field yang hanya ada di salah satu sisi diabaikan.

Untuk field bertipe model (nested), generator otomatis memanggil .fromEntity() / .toEntity() secara rekursif:

// ProductModel.address: AddressModel?
// ProductEntity.address: AddressEntity?
// → otomatis: AddressModel.fromEntity(entity.address)
//           : addressModel.toEntity()

toHiveObject & fromHiveObject

Konversi antara model dan Hive object:

// Hive Object → Model
final model = ProductModel.fromHiveObject(productObject);

// Model → Hive Object
final hiveObject = model.toHiveObject();

Untuk field enum, generator otomatis menyimpan sebagai String (via .name) dan me-restore kembali ke enum saat membaca dari Hive. Tidak membutuhkan Hive adapter untuk enum.

Untuk nested model, generator otomatis memanggil .toHiveObject() / .fromHiveObject() secara rekursif.


CubitState #

Child Classes

Generator membuat class concrete untuk setiap state:

// Dari:
const factory ProductState.success({required List<ProductModel> products}) = ProductSuccess;

// Di-generate:
class ProductSuccess with _$ComparablePropsMixin implements ProductState {
  final List<ProductModel> products;
  const ProductSuccess({required this.products});

  @override List<Object?> get props => [products];
  @override String toString() => ...;
}

Setiap child class mendapat value equality dan toString otomatis.

Pattern Matching Extensions

Generator menghasilkan 6 extension method untuk pattern matching:

when — semua case wajib dihandle:

final message = state.when(
  initial: () => 'Siap',
  loading: () => 'Loading...',
  success: (products, total) => 'Ditemukan $total produk',
  failure: (message, code) => 'Error: $message',
);

maybeWhen — hanya handle case tertentu, sisanya ke orElse:

final widget = state.maybeWhen(
  success: (products, total) => ProductList(products: products),
  orElse: () => const LoadingWidget(),
);

whenOrNull — handle case tertentu, sisanya return null:

final products = state.whenOrNull(
  success: (products, total) => products,
);

map — menerima child instance, bukan field:

state.map(
  initial: (s) => ...,       // s is ProductInitial
  loading: (s) => ...,       // s is ProductLoading
  success: (s) => s.products, // s is ProductSuccess
  failure: (s) => s.message,  // s is ProductFailure
);

maybeMap — sama seperti map tapi dengan orElse:

state.maybeMap(
  success: (s) => ProductList(products: s.products),
  orElse: () => const SizedBox(),
);

mapOrNull — sama seperti map tapi return null untuk case yang tidak dihandle:

final successState = state.mapOrNull(
  success: (s) => s,
);

Contoh Lengkap #

1. Enum dengan Custom Value #

// lib/enum/product_status.dart
import 'package:flutter_boilerplate_annotations/flutter_boilerplate_annotations.dart';

enum ProductStatus {
  @EnumValue('active') active,
  @EnumValue('inactive') inactive,
  @EnumValue('pending_review') pendingReview,
}

2. Domain Entity #

// lib/entity/product_entity.dart
class ProductEntity {
  final int? id;
  final String? name;
  final double? price;
  final bool? isAvailable;
  final DateTime? createdAt;
  final List<String>? tags;
  final ProductStatus? status;
  final AddressEntity? address;

  const ProductEntity({
    this.id, this.name, this.price, this.isAvailable,
    this.createdAt, this.tags, this.status, this.address,
  });
}

3. Hive Object #

// lib/hive/product_object.dart
class ProductObject {
  final int? id;
  final String? name;
  final double? price;
  final bool? isAvailable;
  final String? status;         // enum disimpan sebagai String
  final AddressObject? address; // nested hive object

  ProductObject({
    this.id, this.name, this.price, this.isAvailable,
    this.status, this.address,
  });
}

4. Model dengan Semua Fitur #

// lib/model/product_model.dart
import 'package:flutter_boilerplate_annotations/flutter_boilerplate_annotations.dart';

part 'generated/product_model.g.dart';

@Model(
  entity: ProductEntity,
  fromEntity: true,
  toEntity: true,
  hiveObject: ProductObject,
  fromHiveObject: true,
  toHiveObject: true,
)
abstract class ProductModel with _$ProductModel {
  const factory ProductModel({
    int? id,
    @JsonKey(name: 'product_name') String? name,
    String? description,
    @Default(0.0) double? price,
    @Default(0) int? stock,
    @Default(true) bool? isAvailable,
    DateTime? createdAt,
    List<String>? tags,
    ProductStatus? status,
    AddressModel? address,
  }) = _ProductModel;

  factory ProductModel.fromJson(Map<String, dynamic> json) =>
      _$ProductModelFromJson(json);

  factory ProductModel.fromEntity(ProductEntity? entity) =>
      _$ProductModelFromEntity(entity);

  factory ProductModel.fromHiveObject(ProductObject hiveObject) =>
      _$ProductModelFromHiveObject(hiveObject);
}

5. CubitState #

// lib/state/product_state.dart
import 'package:flutter_boilerplate_annotations/flutter_boilerplate_annotations.dart';

part 'generated/product_state.g.dart';

@CubitState()
abstract class ProductState {
  const factory ProductState.initial() = ProductInitial;
  const factory ProductState.loading() = ProductLoading;
  const factory ProductState.success({
    required List<ProductModel> products,
    @Default(0) int total,
  }) = ProductSuccess;
  const factory ProductState.failure({
    required String message,
    int? code,
  }) = ProductFailure;
}

6. Penggunaan di Cubit #

class ProductCubit extends Cubit<ProductState> {
  ProductCubit() : super(const ProductState.initial());

  Future<void> fetchProducts() async {
    emit(const ProductState.loading());
    try {
      final entities = await repository.getAll();
      final models = entities.map(ProductModel.fromEntity).toList();
      emit(ProductState.success(products: models, total: models.length));
    } catch (e) {
      emit(ProductState.failure(message: e.toString()));
    }
  }
}

7. Penggunaan di Widget #

BlocBuilder<ProductCubit, ProductState>(
  builder: (context, state) {
    return state.when(
      initial: () => const SizedBox(),
      loading: () => const CircularProgressIndicator(),
      success: (products, total) => Column(
        children: [
          Text('Total: $total'),
          ...products.map((p) => Text(p.name ?? '')),
        ],
      ),
      failure: (message, code) => Text('Error $code: $message'),
    );
  },
)

Referensi Opsi #

@Model — semua parameter #

Parameter Type Default Keterangan
entity Type? null Domain entity class untuk mapping
hiveObject Type? null Hive object class untuk mapping
fromJson bool true Generate _$ClassFromJson()
toJson bool true Generate _$ClassToJson() + toJson() method
fromEntity bool false Generate _$ClassFromEntity()
toEntity bool true Generate _$ClassToEntity() + toEntity() method
fromHiveObject bool true Generate _$ClassFromHiveObject()
toHiveObject bool true Generate _$ClassToHiveObject() + toHiveObject() method
genericAugmented bool false Aktifkan dukungan generic type <T> untuk toJson/fromJson

@CubitState — semua parameter #

Parameter Type Default Keterangan
when bool true Generate .when(...) extension
maybeWhen bool true Generate .maybeWhen(...) extension
whenOrNull bool true Generate .whenOrNull(...) extension
map bool true Generate .map(...) extension
maybeMap bool true Generate .maybeMap(...) extension
mapOrNull bool true Generate .mapOrNull(...) extension

Konstanta siap pakai #

// Ekuivalen dengan @Model() tanpa argumen (semua default)
const Model model = Model();

// Ekuivalen dengan @CubitState() tanpa argumen (semua default)
const CubitState cubitState = CubitState();
@model       // shorthand untuk @Model()
abstract class SimpleModel with _$SimpleModel { ... }

@cubitState  // shorthand untuk @CubitState()
abstract class AppState { ... }

Catatan Penting #

Field mapping entity/hive hanya memetakan field yang namanya sama di antara model dan entity/hive object. Field yang hanya ada di satu sisi diabaikan.

Nested model pada toEntity dan toHiveObject otomatis memanggil .toEntity() / .toHiveObject() pada tipe non-primitive. Pastikan nested model juga memiliki method tersebut.

Nested model pada fromEntity memanggil NestedModel.fromEntity(entity.field) — pastikan factory fromEntity pada nested model menerima parameter nullable (EntityType? entity).

Enum di Hive disimpan sebagai String (nama field enum atau nilai @EnumValue) dan di-restore via lookup. Tidak membutuhkan Hive adapter untuk enum.

Null fields di JSON: field nullable yang bernilai null tidak dimasukkan ke map hasil toJson. Saat fromJson, field yang tidak ada di JSON akan bernilai null.

1
likes
130
points
99
downloads

Documentation

API reference

Publisher

unverified uploader

Weekly Downloads

A Dart code generator for Flutter boilerplate: model, entity, hive, and cubit state. Generates JSON serialization, copyWith, value equality, entity/Hive mapping, and pattern-matching extensions.

Homepage

License

MIT (license)

Dependencies

analyzer, build, flutter_boilerplate_annotations, glob, source_gen

More

Packages that depend on flutter_boilerplate_generator