@@ -28,6 +28,8 @@ class EntityResolver extends Builder {
2828 final _indexChecker = const TypeChecker .fromRuntime (Index );
2929 final _backlinkChecker = const TypeChecker .fromRuntime (Backlink );
3030 final _hnswChecker = const TypeChecker .fromRuntime (HnswIndex );
31+ final _externalTypeChecker = const TypeChecker .fromRuntime (ExternalType );
32+ final _externalNameChecker = const TypeChecker .fromRuntime (ExternalName );
3133
3234 @override
3335 FutureOr <void > build (BuildStep buildStep) async {
@@ -68,6 +70,11 @@ class EntityResolver extends Builder {
6870 null ,
6971 uidRequest: ! entityUid.isNull && entityUid.intValue == 0 );
7072
73+ // @ExternalName
74+ _externalNameChecker.runIfMatches (classElement, (annotation) {
75+ entity.externalName = _readExternalNameParams (annotation);
76+ });
77+
7178 // Sync: check if enabled and options
7279 _syncChecker.runIfMatches (classElement, (annotation) {
7380 entity.flags | = OBXEntityFlags .SYNC_ENABLED ;
@@ -171,6 +178,7 @@ class EntityResolver extends Builder {
171178 final backlinkAnnotations =
172179 _backlinkChecker.annotationsOfExact (annotated);
173180 if (backlinkAnnotations.isNotEmpty) {
181+ // Handles ToMany based on other ToOne or ToMany relation (backlink)
174182 if (! isToManyRel) {
175183 log.severe (
176184 " Skipping property '${f .name }': @Backlink() may only be used with ToMany." );
@@ -183,14 +191,33 @@ class EntityResolver extends Builder {
183191 entity.backlinks.add (backlink);
184192 log.info (' $backlink ' );
185193 } else if (isToManyRel) {
194+ // Handles standalone (non backlink) ToMany relation
195+
196+ // @ExternalType
197+ int ? externalType;
198+ _externalTypeChecker.runIfMatches (annotated, (annotation) {
199+ final externalTypeId = _readExternalTypeParams (annotation);
200+ externalType = externalTypeId;
201+ });
202+
203+ // @ExternalName
204+ String ? externalName;
205+ _externalNameChecker.runIfMatches (annotated, (annotation) {
206+ externalName = _readExternalNameParams (annotation);
207+ });
208+
186209 // create relation
187210 final rel = ModelRelation .create (IdUid (0 , propUid ?? 0 ), f.name,
188211 targetName: relTargetName,
189- uidRequest: propUid != null && propUid == 0 );
212+ uidRequest: propUid != null && propUid == 0 ,
213+ externalName: externalName,
214+ externalType: externalType);
215+
190216 entity.relations.add (rel);
191217
192218 log.info (' $rel ' );
193219 } else {
220+ // Handles regular properties
194221 // create property (do not use readEntity.createProperty in order to avoid generating new ids)
195222 final prop = ModelProperty .create (
196223 IdUid (0 , propUid ?? 0 ), f.name, fieldType,
@@ -226,6 +253,17 @@ class EntityResolver extends Builder {
226253 _readHnswIndexParams (annotation, prop);
227254 });
228255
256+ // @ExternalType
257+ _externalTypeChecker.runIfMatches (annotated, (annotation) {
258+ final externalTypeId = _readExternalTypeParams (annotation);
259+ prop.externalType = externalTypeId;
260+ });
261+
262+ // @ExternalName
263+ _externalNameChecker.runIfMatches (annotated, (annotation) {
264+ prop.externalName = _readExternalNameParams (annotation);
265+ });
266+
229267 // for code generation
230268 prop.dartFieldType =
231269 f.type.element! .name! + (isNullable (f.type) ? '?' : '' );
@@ -555,6 +593,27 @@ class EntityResolver extends Builder {
555593 annotation.getField ('vectorCacheHintSizeKB' )! .toIntValue ());
556594 property.hnswParams = ModelHnswParams .fromAnnotation (hnswRestored);
557595 }
596+
597+ int _readExternalTypeParams (DartObject annotation) {
598+ final typeIndex =
599+ _enumValueIndex (annotation.getField ('type' )! , "ExternalType.type" );
600+ final type =
601+ typeIndex != null ? ExternalPropertyType .values[typeIndex] : null ;
602+ if (type == null ) {
603+ throw InvalidGenerationSourceError (
604+ "'type' attribute not specified in @ExternalType annotation" );
605+ }
606+ return externalTypeToOBXExternalType (type);
607+ }
608+
609+ String _readExternalNameParams (DartObject annotation) {
610+ final name = annotation.getField ('name' )! .toStringValue ();
611+ if (name == null ) {
612+ throw InvalidGenerationSourceError (
613+ "'name' attribute not specified in @ExternalName annotation" );
614+ }
615+ return name;
616+ }
558617}
559618
560619extension _TypeCheckerExtensions on TypeChecker {
0 commit comments