Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add GenerateAdapters annotation #47

Merged
merged 3 commits into from
Nov 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions hive/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## 2.8.0

- Adds `GenerateAdapters` annotation and relevant documentation

## 2.7.0+1

- Adds a storage benchmark to compare Hive CE with Hive v4
Expand Down
89 changes: 65 additions & 24 deletions hive/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@ Hive CE is a spiritual continuation of Hive v2 with the following new features:
- Support for constructor parameter defaults
- Freezed support
- Support for generating adapters with classes that use named imports
- Automatic type adapter generation using the `GenerateAdapters` annotation
- No more manually adding annotations to every type and field
- Generate adapters for classes outside the current package

## Hive CE (v2) vs Hive v4 (Isar)

Expand Down Expand Up @@ -187,19 +190,34 @@ Hive not only supports primitives, lists, and maps but also any Dart object you
```dart
import 'package:hive_ce/hive.dart';

@HiveType(typeId: 0)
class Person extends HiveObject {
Person({required this.name, required this.age});

@HiveField(0)
String name;

@HiveField(1)
int age;
}

```

### Create a `GenerateAdapters` annotation

Usually this is placed in `lib/hive/hive_adapters.dart`

<!-- embedme readme/store_objects/hive_adapters.dart -->

```dart
import 'package:hive_ce/hive.dart';
import 'person.dart';

part 'hive_adapters.g.dart';

@GenerateAdapters([AdapterSpec<Person>()])
// Annotations must be on some element
// ignore: unused_element
void _() {}

```

### Update `pubspec.yaml`

```yaml
Expand All @@ -214,10 +232,20 @@ dev_dependencies:
dart pub run build_runner build --delete-conflicting-outputs
```

This will generate all of your `TypeAdapter`s as well as a Hive extension to register them all in one go
This will generate the following:

- TypeAdapters for the specified AdapterSpecs
- TypeAdapters for all explicitly defined HiveTypes
- A `hive_adapters.g.dart` file containing all adapters generated from the `GenerateAdapters` annotation
- A `hive_adapters.g.yaml` file
- A `hive_registrar.g.dart` file containing an extension method to register all generated adapters

All of the generated files should be checked into version control. These files are explained in more detail below.

### Use the Hive registrar

The Hive Registrar allows you to register all generated TypeAdapters in one call

```dart
import 'dart:io';
import 'package:hive_ce/hive.dart';
Expand Down Expand Up @@ -256,6 +284,38 @@ void example() async {

```

### About `hive_adapters.g.yaml`

The Hive schema is a generated yaml file that contains the information necessary to incrementally update the generated TypeAdapters as your model classes evolve.

Some migrations may require manual modifications to the Hive schema file. One example is class/field renaming. Without manual intervention, the generator will see both an added and removed class/field. To resolve this, manually rename the class/field in the schema.

### Migrating to `GenerateAdapters`

If you already have model classes with `HiveType` and `HiveField` annotations, you can take the following steps to migrate to the new `GenerateAdapters` annotation:

1. Convert all default values to constructor parameter defaults
2. Add the following to your `build.yaml` file:

```yaml
targets:
$default:
builders:
hive_ce_generator|hive_schema_migrator:
enabled: true
```

3. Run the `build_runner`. This will generate `lib/hive/hive_adapters.dart` and `lib/hive/hive_adapters.g.yaml`.
4. Revert the `build.yaml` changes
5. Remove all explicit `HiveType` and `HiveField` annotations from your model classes
6. Run the `build_runner` again

### Explicitly defining HiveTypes

The old method of defining HiveTypes is still supported, but should be unnecessary now that Hive CE supports constructor parameter defaults. If you have a use-case that `GenerateAdapters` does not support, please [create an issue on GitHub](https://github.com/IO-Design-Team/hive_ce/issues/new).

Unfortunately it is not possible for `GenerateAdapters` to handle private fields. You can use `@protected` instead if necessary.

## Add fields to objects

When adding a new non-nullable field to an existing object, you need to specify a default value to ensure compatibility with existing data.
Expand All @@ -267,14 +327,10 @@ For example, consider an existing database with a `Person` object:
```dart
import 'package:hive_ce/hive.dart';

@HiveType(typeId: 0)
class Person extends HiveObject {
Person({required this.name, required this.age});

@HiveField(0)
String name;

@HiveField(1)
int age;
}

Expand All @@ -287,31 +343,16 @@ If you want to add a `balance` field, you must specify a default value or else r
```dart
import 'package:hive_ce/hive.dart';

@HiveType(typeId: 0)
class Person extends HiveObject {
Person({required this.name, required this.age, this.balance = 0});

@HiveField(0)
String name;

@HiveField(1)
int age;

@HiveField(2)
double balance;
}

```

Or specify it in the `HiveField` annotation:

```dart
@HiveField(2, defaultValue: 0)
int balance;
```

Alternatively, you can write custom migration code to handle the transition.

After modifying the model, remember to run `build_runner` to regenerate the TypeAdapters

## Hive ❤️ Flutter
Expand Down
9 changes: 3 additions & 6 deletions hive/example/lib/freezed.dart
Original file line number Diff line number Diff line change
@@ -1,15 +1,12 @@
import 'package:freezed_annotation/freezed_annotation.dart';
import 'package:hive_ce/hive.dart';

part 'freezed.freezed.dart';
part 'freezed.g.dart';

@freezed
@HiveType(typeId: 100)
class FreezedPerson with _$FreezedPerson {
const factory FreezedPerson({
@HiveField(0) required String firstName,
@HiveField(1) required String lastName,
@HiveField(2) required int age,
required String firstName,
required String lastName,
required int age,
}) = _FreezedPerson;
}
29 changes: 6 additions & 23 deletions hive/example/lib/freezed.freezed.dart
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,8 @@ final _privateConstructorUsedError = UnsupportedError(

/// @nodoc
mixin _$FreezedPerson {
@HiveField(0)
String get firstName => throw _privateConstructorUsedError;
@HiveField(1)
String get lastName => throw _privateConstructorUsedError;
@HiveField(2)
int get age => throw _privateConstructorUsedError;

/// Create a copy of FreezedPerson
Expand All @@ -36,10 +33,7 @@ abstract class $FreezedPersonCopyWith<$Res> {
FreezedPerson value, $Res Function(FreezedPerson) then) =
_$FreezedPersonCopyWithImpl<$Res, FreezedPerson>;
@useResult
$Res call(
{@HiveField(0) String firstName,
@HiveField(1) String lastName,
@HiveField(2) int age});
$Res call({String firstName, String lastName, int age});
}

/// @nodoc
Expand Down Expand Up @@ -86,10 +80,7 @@ abstract class _$$FreezedPersonImplCopyWith<$Res>
__$$FreezedPersonImplCopyWithImpl<$Res>;
@override
@useResult
$Res call(
{@HiveField(0) String firstName,
@HiveField(1) String lastName,
@HiveField(2) int age});
$Res call({String firstName, String lastName, int age});
}

/// @nodoc
Expand Down Expand Up @@ -130,18 +121,13 @@ class __$$FreezedPersonImplCopyWithImpl<$Res>

class _$FreezedPersonImpl implements _FreezedPerson {
const _$FreezedPersonImpl(
{@HiveField(0) required this.firstName,
@HiveField(1) required this.lastName,
@HiveField(2) required this.age});
{required this.firstName, required this.lastName, required this.age});

@override
@HiveField(0)
final String firstName;
@override
@HiveField(1)
final String lastName;
@override
@HiveField(2)
final int age;

@override
Expand Down Expand Up @@ -175,18 +161,15 @@ class _$FreezedPersonImpl implements _FreezedPerson {

abstract class _FreezedPerson implements FreezedPerson {
const factory _FreezedPerson(
{@HiveField(0) required final String firstName,
@HiveField(1) required final String lastName,
@HiveField(2) required final int age}) = _$FreezedPersonImpl;
{required final String firstName,
required final String lastName,
required final int age}) = _$FreezedPersonImpl;

@override
@HiveField(0)
String get firstName;
@override
@HiveField(1)
String get lastName;
@override
@HiveField(2)
int get age;

/// Create a copy of FreezedPerson
Expand Down
13 changes: 13 additions & 0 deletions hive/example/lib/hive/hive_adapters.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import 'package:example/freezed.dart';
import 'package:example/main.dart';
import 'package:hive_ce/hive.dart';

part 'hive_adapters.g.dart';

@GenerateAdapters([
AdapterSpec<Person>(),
AdapterSpec<FreezedPerson>(),
])
// This is for code generation
// ignore: unused_element
void _() {}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

25 changes: 25 additions & 0 deletions hive/example/lib/hive/hive_adapters.g.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# Generated by Hive CE
# Manual modifications may be necessary for certain migrations
# Check in to version control
nextTypeId: 2
types:
Person:
typeId: 0
nextIndex: 3
fields:
name:
index: 0
age:
index: 1
friends:
index: 2
FreezedPerson:
typeId: 1
nextIndex: 3
fields:
firstName:
index: 0
lastName:
index: 1
age:
index: 2
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,7 @@
// Check in to version control

import 'package:hive_ce/hive.dart';
import 'package:example/freezed.dart';
import 'package:example/main.dart';
import 'package:example/hive/hive_adapters.dart';

extension HiveRegistrar on HiveInterface {
void registerAdapters() {
Expand Down
10 changes: 1 addition & 9 deletions hive/example/lib/main.dart
Original file line number Diff line number Diff line change
@@ -1,21 +1,13 @@
import 'dart:io';

import 'package:example/hive_registrar.g.dart';
import 'package:example/hive/hive_registrar.g.dart';
import 'package:hive_ce/hive.dart';

part 'main.g.dart';

@HiveType(typeId: 1)
class Person {
Person({required this.name, required this.age, required this.friends});

@HiveField(0)
String name;

@HiveField(1)
int age;

@HiveField(2)
List<String> friends;

@override
Expand Down
Loading