platform/packages/relations/lib/src/has_many_through.dart

98 lines
2.9 KiB
Dart
Raw Normal View History

2017-03-04 21:00:17 +00:00
import 'dart:async';
import 'dart:mirrors';
import 'package:angel_framework/angel_framework.dart';
import 'plural.dart' as pluralize;
import 'no_service.dart';
HookedServiceEventListener hasManyThrough(String servicePath, String pivotPath,
2021-06-20 12:37:20 +00:00
{String? as,
String? localKey,
String? pivotKey,
String? foreignKey,
Function(dynamic obj)? getLocalKey,
Function(dynamic obj)? getPivotKey,
Function(dynamic obj)? getForeignKey,
Function(dynamic foreign, dynamic obj)? assignForeignObjects}) {
2017-03-04 21:00:17 +00:00
var foreignName =
as?.isNotEmpty == true ? as : pluralize.plural(servicePath.toString());
return (HookedServiceEvent e) async {
var pivotService = e.getService(pivotPath);
var foreignService = e.getService(servicePath);
2021-06-20 12:37:20 +00:00
if (pivotService == null) {
2017-03-04 21:00:17 +00:00
throw noService(pivotPath);
2021-06-20 12:37:20 +00:00
} else if (foreignService == null) throw noService(servicePath);
2017-03-04 21:00:17 +00:00
2021-06-20 12:37:20 +00:00
dynamic _assignForeignObjects(foreign, obj) {
if (assignForeignObjects != null) {
2017-03-04 21:00:17 +00:00
return assignForeignObjects(foreign, obj);
2021-06-20 12:37:20 +00:00
} else if (obj is Map) {
2017-03-04 21:00:17 +00:00
obj[foreignName] = foreign;
2021-06-20 12:37:20 +00:00
} else {
reflect(obj).setField(Symbol(foreignName!), foreign);
}
2017-03-04 21:00:17 +00:00
}
2021-06-20 12:37:20 +00:00
dynamic _getLocalKey(obj) {
if (getLocalKey != null) {
2017-03-04 21:00:17 +00:00
return getLocalKey(obj);
2021-06-20 12:37:20 +00:00
} else if (obj is Map) {
2017-03-04 21:00:17 +00:00
return obj[localKey ?? 'id'];
2021-06-20 12:37:20 +00:00
} else if (localKey == null || localKey == 'id') {
2017-03-04 21:00:17 +00:00
return obj.id;
2021-06-20 12:37:20 +00:00
} else {
return reflect(obj).getField(Symbol(localKey)).reflectee;
}
2017-03-04 21:00:17 +00:00
}
2021-06-20 12:37:20 +00:00
dynamic _getPivotKey(obj) {
if (getPivotKey != null) {
2017-03-04 21:00:17 +00:00
return getPivotKey(obj);
2021-06-20 12:37:20 +00:00
} else if (obj is Map) {
2017-03-04 21:00:17 +00:00
return obj[pivotKey ?? 'id'];
2021-06-20 12:37:20 +00:00
} else if (pivotKey == null || pivotKey == 'id') {
2017-03-04 21:00:17 +00:00
return obj.id;
2021-06-20 12:37:20 +00:00
} else {
return reflect(obj).getField(Symbol(pivotKey)).reflectee;
}
2017-03-04 21:00:17 +00:00
}
2021-06-20 12:37:20 +00:00
Future _normalize(obj) async {
2017-03-04 21:00:17 +00:00
// First, resolve pivot
var id = await _getLocalKey(obj);
var indexed = await pivotService.index({
'query': {pivotKey ?? 'userId': id}
});
2021-06-20 12:37:20 +00:00
if (indexed is! List || indexed.isNotEmpty != true) {
2017-03-04 21:00:17 +00:00
await _assignForeignObjects([], obj);
} else {
// Now, resolve from foreign service
var mapped = await Future.wait(indexed.map((pivot) async {
var id = await _getPivotKey(obj);
var indexed = await foreignService.index({
'query': {foreignKey ?? 'postId': id}
});
2021-06-20 12:37:20 +00:00
if (indexed is! List || indexed.isNotEmpty != true) {
2017-03-04 21:00:17 +00:00
await _assignForeignObjects([], pivot);
} else {
await _assignForeignObjects(indexed, pivot);
}
return pivot;
}));
await _assignForeignObjects(mapped, obj);
}
}
if (e.result is Iterable) {
2021-06-20 12:37:20 +00:00
//await Future.wait(e.result.map(_normalize));
await e.result.map(_normalize);
} else {
2017-03-04 21:00:17 +00:00
await _normalize(e.result);
2021-06-20 12:37:20 +00:00
}
2017-03-04 21:00:17 +00:00
};
}