Skip to content

Commit 28efcb6

Browse files
committed
Add GeneratorVersion enum to enforce compatible generated sources
1 parent bf29d51 commit 28efcb6

File tree

4 files changed

+67
-4
lines changed

4 files changed

+67
-4
lines changed

generator/lib/src/code_chunks.dart

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,11 @@ class CodeChunks {
104104
static String defineModel(ModelInfo model) {
105105
return '''
106106
final model = $obxInt.ModelInfo(
107+
// If this version is not found, it means that this file was generated
108+
// with an older version of the ObjectBox Dart generator.
109+
// Please regenerate this file with the current generator version.
110+
// Typically, this is done with `dart run build_runner build`.
111+
generatorVersion: $obxInt.GeneratorVersion.${generatorVersionLatest.name},
107112
entities: _entities,
108113
lastEntityId: ${createIdUid(model.lastEntityId)},
109114
lastIndexId: ${createIdUid(model.lastIndexId)},

generator/test/code_builder_test.dart

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import 'dart:convert';
12
import 'dart:io';
23

34
import 'package:logging/logging.dart';
@@ -953,4 +954,32 @@ void main() {
953954
);
954955
});
955956
});
957+
958+
group('GeneratorVersion', () {
959+
test('generated code includes GeneratorVersion parameter', () async {
960+
final source = r'''
961+
library example;
962+
import 'package:objectbox/objectbox.dart';
963+
964+
@Entity()
965+
class Example {
966+
@Id()
967+
int id = 0;
968+
}
969+
''';
970+
971+
final testEnv = GeneratorTestEnv();
972+
// Verify the generated code contains the GeneratorVersion parameter.
973+
// The matcher receives bytes, so use predicate to convert to string.
974+
final expectedVersion =
975+
'generatorVersion: obx_int.GeneratorVersion.${generatorVersionLatest.name}';
976+
await testEnv.run(
977+
source,
978+
generatedCodeMatcher: predicate<List<int>>(
979+
(bytes) => utf8.decode(bytes).contains(expectedVersion),
980+
'contains "$expectedVersion"',
981+
),
982+
);
983+
});
984+
});
956985
}

generator/test/generator_test_env.dart

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ class GeneratorTestEnv {
3838
Future<GeneratorTestResult> run(
3939
String source, {
4040
bool ignoreOutput = false,
41+
Object? generatedCodeMatcher,
4142
}) async {
4243
final library = "example";
4344
// Enable resolving imports (imported packages must be a dependency of this package)
@@ -55,7 +56,7 @@ class GeneratorTestEnv {
5556
// var modelEntity = ModelEntity.fromMap(entitiesList[0], check: false);
5657
// return modelEntity.name == "Example" && modelEntity.flags == 0;
5758
// }),
58-
'$library|lib/objectbox.g.dart': isNotNull,
59+
'$library|lib/objectbox.g.dart': generatedCodeMatcher ?? isNotNull,
5960
// Future improvement: assert generated code? Needs existing model JSON for stable IDs
6061
// '$library|lib/objectbox.g.dart': '<file-content>'
6162
};

objectbox/lib/src/modelinfo/modelinfo.dart

Lines changed: 31 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,28 @@ import 'modelentity.dart';
88
const _minModelVersion = 5;
99
const _maxModelVersion = 5;
1010

11+
/// Represents the generator version used to create the model.
12+
///
13+
/// This enum contains all supported versions by this ObjectBox runtime library.
14+
/// It is used purely for compile-time enforcement to ensure users regenerate
15+
/// code after updating the objectbox package.
16+
/// Once a version is not compatible/supported, it is removed from this enum.
17+
/// Note: using a separate, date based, versioning (YYYY_MM_DD) as the
18+
/// generator is not always updated in each library version.
19+
enum GeneratorVersion {
20+
/// The model was not created by generated code.
21+
none,
22+
23+
/// BREAKING CHANGE in ObjectBox Dart 5.1 with DateTime (date) properties:
24+
/// - DateTime properties are now stored in UTC by default(!).
25+
/// - If you rely on reading local time, you must use dateLegacy.
26+
/// - Only UTC times provide correct values for ObjectBox Sync.
27+
v2025_12_16,
28+
}
29+
30+
/// The latest generator version (aligned with this ObjectBox runtime library).
31+
const generatorVersionLatest = GeneratorVersion.v2025_12_16;
32+
1133
/// In order to represent the model stored in `objectbox-model.json` in Dart,
1234
/// several classes have been introduced. Conceptually, these classes are
1335
/// comparable to how models are handled in ObjectBox Java and ObjectBox Go.
@@ -20,6 +42,9 @@ class ModelInfo {
2042
'If you have VCS merge conflicts, you must resolve them according to ObjectBox docs.',
2143
];
2244

45+
/// The ObjectBox Dart generator version used to generate this model.
46+
GeneratorVersion generatorVersion;
47+
2348
List<ModelEntity> entities;
2449
IdUid lastEntityId, lastIndexId, lastRelationId, lastSequenceId;
2550
List<int> retiredEntityUids,
@@ -29,7 +54,8 @@ class ModelInfo {
2954
int modelVersion, modelVersionParserMinimum, version;
3055

3156
ModelInfo(
32-
{required this.entities,
57+
{required this.generatorVersion,
58+
required this.entities,
3359
required this.lastEntityId,
3460
required this.lastIndexId,
3561
required this.lastRelationId,
@@ -43,7 +69,8 @@ class ModelInfo {
4369
required this.version});
4470

4571
ModelInfo.empty()
46-
: entities = [],
72+
: generatorVersion = GeneratorVersion.none,
73+
entities = [],
4774
lastEntityId = const IdUid.empty(),
4875
lastIndexId = const IdUid.empty(),
4976
lastRelationId = const IdUid.empty(),
@@ -57,7 +84,8 @@ class ModelInfo {
5784
version = 1;
5885

5986
ModelInfo.fromMap(Map<String, dynamic> data, {bool check = true})
60-
: entities = [],
87+
: generatorVersion = GeneratorVersion.none,
88+
entities = [],
6189
lastEntityId = IdUid.fromString(data['lastEntityId'] as String?),
6290
lastIndexId = IdUid.fromString(data['lastIndexId'] as String?),
6391
lastRelationId = IdUid.fromString(data['lastRelationId'] as String?),

0 commit comments

Comments
 (0)