normalizeIncludes method
Normalize inputs
Implementation
Map<String, RelationScope> normalizeIncludes(dynamic includesInput)
{
// Accept both List and Map for root
final List includes = includesInput is Map
? [includesInput]
: (includesInput ?? []) as List;
final Map<String, RelationScope> result = {};
// Helper: merge two scopes together
RelationScope mergeScopes(RelationScope? oldScope, RelationScope newScope) {
if (oldScope == null) return newScope;
return (q) {
final q1 = oldScope(q);
final q2 = newScope(q1);
return q2;
};
}
// Helper: create a scope from nested include list
RelationScope scopeFromNested(List nested) {
return (q) => q.include(nested);
}
for (final inc in includes) {
// CASE 1: Simple string (dot path)
if (inc is String) {
final parts = inc.split('.');
final rel = parts.first;
if (parts.length == 1) {
// simple relation
result[rel] = mergeScopes(result[rel], (q) => q);
} else {
final nested = [parts.sublist(1).join('.')];
result[rel] =
mergeScopes(result[rel], scopeFromNested(nested));
}
continue;
}
// CASE 2: Map { relation: config }
if (inc is Map) {
for (final entry in inc.entries) {
final relName = entry.key.toString();
final cfg = entry.value;
RelationScope newScope;
if (cfg is Function) {
newScope = (q) {
final out = cfg(q);
return out is Query ? out : q;
};
} else if (cfg is List) {
newScope = scopeFromNested(cfg);
} else if (cfg is Map) {
newScope = scopeFromNested([cfg]);
} else if (cfg == true) {
newScope = (q) => q;
} else {
throw Exception("Invalid include config for '$relName': $cfg");
}
result[relName] = mergeScopes(result[relName], newScope);
}
continue;
}
// CASE 3: List inside list → flatten / merge
if (inc is List) {
if (inc.isEmpty) continue;
final nested = normalizeIncludes(inc); // recursion
for (final e in nested.entries) {
result[e.key] = mergeScopes(result[e.key], e.value);
}
continue;
}
// print("normalizeIncludes() invalid inc type: ${inc.runtimeType} value=$inc");
throw Exception("Invalid include type: $inc");
}
return result;
}