Line data Source code
1 : part of flutter_data; 2 : 3 : extension IterableX<T> on Iterable<T> { 4 12 : @protected 5 : @visibleForTesting 6 21 : T? get safeFirst => isNotEmpty ? first : null; 7 : 8 3 : @protected 9 : @visibleForTesting 10 6 : bool containsFirst(T model) => safeFirst == model; 11 : 12 5 : @protected 13 : @visibleForTesting 14 5 : List<T> toImmutableList() => List.unmodifiable(this); 15 : } 16 : 17 : extension _DataModelListX on Iterable<DataModel> { 18 5 : String toShortLog() { 19 20 : final ids = map((m) => m.id).toSet(); 20 5 : return ids.isEmpty 21 : ? 'none' 22 10 : : (ids.length > 5 23 4 : ? '${ids.take(5).toSet()} (and ${ids.length - 5} more)' 24 1 : : ids) 25 5 : .toString(); 26 : } 27 : } 28 : 29 : extension IterableNullX<T> on Iterable<T?> { 30 12 : @protected 31 : @visibleForTesting 32 36 : Iterable<T> get filterNulls => where((elem) => elem != null).cast(); 33 : } 34 : 35 : extension StringUtilsX on String { 36 1 : String capitalize() => 37 5 : isEmpty ? '' : '${this[0].toUpperCase()}${substring(1)}'; 38 : 39 12 : String decapitalize() => 40 60 : isEmpty ? '' : '${this[0].toLowerCase()}${substring(1)}'; 41 : 42 24 : String pluralize() => inflection.pluralize(this); 43 : 44 2 : String singularize() => inflection.singularize(this); 45 : 46 14 : Uri get asUri => Uri.parse(this); 47 : 48 11 : String namespaceWith(String prefix) { 49 22 : assert(!prefix.contains(':')); 50 11 : return '$prefix:$this'; 51 : } 52 : 53 12 : String typifyWith(String type) { 54 24 : assert(!type.contains('#')); 55 12 : if (isEmpty) { 56 : return type; 57 : } 58 12 : return '$type#$this'; 59 : } 60 : 61 18 : String? get namespace => split(':').safeFirst; 62 : 63 0 : String? get type => split('#').safeFirst; 64 : 65 11 : String denamespace() { 66 : // need to re-join with : in case there were other :s in the text 67 33 : return (split(':')..removeAt(0)).join(':'); 68 : } 69 : 70 6 : String detypify() { 71 : // need to re-join with # in case there were other #s in the id 72 18 : return (split('#')..removeAt(0)).join('#'); 73 : } 74 : } 75 : 76 : extension MapUtilsX<K, V> on Map<K, V> { 77 11 : @protected 78 : @visibleForTesting 79 27 : Map<K, V> operator &(Map<K, V>? more) => {...this, ...?more}; 80 : 81 1 : @protected 82 : @visibleForTesting 83 1 : Map<K, V> get filterNulls => { 84 1 : for (final e in entries) 85 4 : if (e.value != null) e.key: e.value 86 : }; 87 : } 88 : 89 : extension UriUtilsX on Uri { 90 7 : Uri operator /(String path) { 91 35 : return replace(path: path_helper.posix.normalize('/${this.path}/$path')); 92 : } 93 : 94 14 : Uri operator &(Map<String, dynamic> params) => params.isNotEmpty 95 5 : ? replace( 96 15 : queryParameters: queryParameters & _flattenQueryParameters(params)) 97 : : this; 98 : } 99 : 100 5 : Map<String, String> _flattenQueryParameters(Map<String, dynamic> params) { 101 20 : return params.entries.fold<Map<String, String>>({}, (acc, e) { 102 10 : if (e.value is Map<String, dynamic>) { 103 3 : for (final e2 in (e.value as Map<String, dynamic>).entries) { 104 6 : acc['${e.key}[${e2.key}]'] = e2.value.toString(); 105 : } 106 : } else { 107 20 : acc[e.key] = e.value.toString(); 108 : } 109 : return acc; 110 : }); 111 : }