buildOperationUri function
The URI of one call: the path template filled from params, the declared query and then the extra query. The path
replaces baseUrl's own path; pathPrefix (/api) goes before it.
Implementation
Uri buildOperationUri(String baseUrl, Operation operation, Map<String, Object?> params, {String pathPrefix = ''}) {
var path = operation.path.replaceAllMapped(RegExp(r'\{([^}]+)\}'), (m) {
final value = params[m.group(1)];
return value == null || value == '' ? '' : Uri.encodeComponent('$value');
});
path = '$pathPrefix$path'.replaceAll(RegExp(r'/{2,}'), '/').replaceAll(RegExp(r'/+$'), '');
final query = <String, List<String>>{};
void add(String name, Object? value) {
if (value == null) return;
if (value is Iterable) {
query[name] = value.where((v) => v != null).map((v) => _queryValue(v as Object)).toList();
} else {
query[name] = [_queryValue(value)];
}
}
for (final name in operation.query) {
add(name, params[name]);
}
// The extra query comes after the declared names and never replaces one of them.
final extra = params[extraQueryKey];
if (extra is Map) {
extra.forEach((name, value) {
final key = '$name';
if (key.isEmpty || operation.query.contains(key) || query.containsKey(key)) return;
add(key, value);
});
}
final base = Uri.parse(baseUrl);
return base.replace(path: path.isEmpty ? '/' : path, queryParameters: query.isEmpty ? null : query);
}