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

76 lines
2.2 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';
/// Represents a relationship in which the current [service] "belongs to"
/// multiple members of the service at [servicePath]. Use [as] to set the name
/// on the target object.
///
/// Defaults:
/// * [foreignKey]: `userId`
/// * [localKey]: `id`
HookedServiceEventListener belongsToMany(Pattern servicePath,
2021-06-20 12:37:20 +00:00
{String? as,
String? foreignKey,
String? localKey,
Function(dynamic obj)? getForeignKey,
Function(dynamic foreign, dynamic obj)? assignForeignObject}) {
var localId = localKey;
2017-03-04 21:00:17 +00:00
var foreignName =
2021-06-20 12:37:20 +00:00
as?.isNotEmpty == true ? as! : pluralize.plural(servicePath.toString());
2017-03-04 21:00:17 +00:00
2021-06-20 12:37:20 +00:00
localId ??= foreignName + 'Id';
2017-03-04 21:00:17 +00:00
return (HookedServiceEvent e) async {
2021-02-16 02:10:09 +00:00
var ref = e.getService(servicePath);
2017-03-04 21:00:17 +00:00
if (ref == null) throw noService(servicePath);
2021-06-20 12:37:20 +00:00
dynamic _getForeignKey(obj) {
if (getForeignKey != null) {
2017-03-04 21:00:17 +00:00
return getForeignKey(obj);
2021-06-20 12:37:20 +00:00
} else if (obj is Map) {
2017-03-04 21:00:17 +00:00
return obj[localId];
2021-06-20 12:37:20 +00:00
} else if (localId == null || localId == 'userId') {
2017-03-04 21:00:17 +00:00
return obj.userId;
2021-06-20 12:37:20 +00:00
} else {
return reflect(obj).getField(Symbol(localId)).reflectee;
}
2017-03-04 21:00:17 +00:00
}
2021-06-20 12:37:20 +00:00
dynamic _assignForeignObject(foreign, obj) {
if (assignForeignObject != null) {
return assignForeignObject(foreign as List?, obj);
} 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
Future<void> _normalize(obj) async {
2017-03-04 21:00:17 +00:00
if (obj != null) {
var id = await _getForeignKey(obj);
var indexed = await ref.index({
'query': {foreignKey ?? 'id': id}
});
if (indexed == null || indexed is! List || indexed.isNotEmpty != true) {
await _assignForeignObject(null, obj);
} else {
var child = indexed is Iterable ? indexed.toList() : [indexed];
await _assignForeignObject(child, 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
};
}