parseRelations static method

List<RelationMeta> parseRelations(
  1. List raw
)

Parses a raw list of relation inputs into a list of RelationMeta.

Supports multiple input formats:

  • Simple strings: 'posts', 'user:paginated', 'comments:page=1:perPage=10'
  • Nested relations: 'user.posts'
  • Complex objects: {'posts': {'paginate': true, 'page': 1, 'perPage': 10, 'with': ['comments']}}

Parameters:

  • raw: List of relation specifications (strings or maps)

Returns: List of parsed RelationMeta objects containing relation metadata

Implementation

static List<RelationMeta> parseRelations(List<dynamic> raw) {
  final Map<String, RelationMeta> grouped = {};

  void addOrMergeMeta(RelationMeta newMeta) {
    if (grouped.containsKey(newMeta.key)) {
      final existing = grouped[newMeta.key]!;
      existing.nested.addAll(newMeta.nested);
      // We could also merge pagination settings if needed, but for now we keep the existing or override.
      // We'll keep the existing logic simple by just updating pagination if it's explicitly set in newMeta.
      grouped[newMeta.key] = RelationMeta(
        key: existing.key,
        paginate: newMeta.paginate || existing.paginate,
        page: newMeta.page ?? existing.page,
        perPage: newMeta.perPage ?? existing.perPage,
        nested: existing.nested.toSet().toList(), // unique
        query: newMeta.query ?? existing.query,
      );
    } else {
      grouped[newMeta.key] = newMeta;
    }
  }

  for (final entry in raw) {
    if (entry is String) {
      final nestedSplit = entry.split('.');
      final mainPart = nestedSplit.first;
      final nested = nestedSplit.length > 1
          ? [nestedSplit.sublist(1).join('.')]
          : [];

      final segments = mainPart.split(':');

      final key = segments.first;
      bool paginate = false;
      int? page;
      int? perPage;

      for (var segment in segments.skip(1)) {
        if (segment == 'paginated') {
          paginate = true;
        } else if (segment.startsWith('page=')) {
          page = int.tryParse(segment.replaceFirst('page=', ''));
        } else if (segment.startsWith('perPage=')) {
          perPage = int.tryParse(segment.replaceFirst('perPage=', ''));
        }
      }

      addOrMergeMeta(
        RelationMeta(
          key: key,
          paginate: paginate,
          page: page,
          perPage: perPage,
          nested: nested,
        ),
      );
    } else if (entry is Map || entry is Map<String, dynamic>) {
      if (entry is Map) {
        entry.forEach((key, val) {
          if (val is Map) {
            final nested = val['with'] ?? [];
            final nestedList = nested is List ? nested : [nested];

            addOrMergeMeta(
              RelationMeta(
                key: key.toString(),
                paginate: val['paginate'] ?? false,
                page: val['page'],
                perPage: val['perPage'],
                nested: List<dynamic>.from(nestedList),
                query: val['query'],
              ),
            );
          }
        });
      }
    } else if (entry is With) {
      addOrMergeMeta(
        RelationMeta(
          key: entry.relation,
          paginate: entry.paginate,
          page: entry.page,
          perPage: entry.perPage,
          nested: List<dynamic>.from(entry.nested),
          query: entry.query,
        ),
      );
    }
  }

  return grouped.values.toList();
}