import 'dart:convert'; import 'package:decimal/decimal.dart'; import 'package:json_annotation/json_annotation.dart'; import 'package:http/http.dart' as http; part '_helper.g.dart'; @JsonSerializable(explicitToJson: true, includeIfNull: true, createFactory: false) class ExplicitNull { dynamic set; ExplicitNull(); Null toJson() => null; } dynamic anyToJson(dynamic any) { if (any is List) { return any.map((e) => anyToJson(e)).toList(); } else if (any is int) { return any; } else if (any is double) { return any; } else if (any is bool) { return any; } else if (any is String) { return any; } else if (any == null) { return null; } else if (any is DateTime) { return any.toIso8601String(); } else if (any is Decimal) { return any.toString(); } else { return any.toJson(); } } String fromTeoDate(Map arg) { return arg["\$date"]! as String; } DateTime fromTeoDateTime(Map arg) { return DateTime.parse(arg["\$datetime"]! as String); } Decimal fromTeoDecimal(Map arg) { return Decimal.parse(arg["\$decimal"]! as String); } @JsonSerializable(explicitToJson: true, includeIfNull: false) class TeoError implements Exception { String type; String message; Map? errors; TeoError({ required this.type, required this.message, this.errors }); factory TeoError.fromJson(Map json) => _$TeoErrorFromJson(json); Map toJson() => _$TeoErrorToJson(this); @override String toString() => toJson().toString(); } class TeoFile { String path; TeoFile({ required this.path }); } Future formRequest( String method, String path, Map input, T Function(Map) convertFromJson, Map? headers, String? query, ) async { var request = http.MultipartRequest(method, Uri.parse({{ conf.host.to_host_string() }} + path + (query != null ? "?$query" : ""))); if (headers != null) { headers.forEach((k, v) => request.headers[k] = v); } for (var inputEntry in input.entries) { var key = inputEntry.key; var value = inputEntry.value; if (value is List) { for (var valueEntry in value.asMap().entries) { var index = valueEntry.key; var val = valueEntry.value; if (val is TeoFile) { request.files.add(await http.MultipartFile.fromPath("$key[$index]", val.path)); } else { request.fields["$key[$index]"] = val; } } } else { if (value is TeoFile) { request.files.add(await http.MultipartFile.fromPath(key, value.path)); } else { request.fields[key] = value; } } } final streamedRes = await request.send(); var res = await http.Response.fromStream(streamedRes); final Map jsonData = jsonDecode(res.body); if (jsonData.containsKey("error")) { throw TeoError.fromJson(jsonData["error"]); } else { return convertFromJson(jsonData); } } Future jsonRequest( String method, String path, dynamic input, T Function(Map) convertFromJson, Map? headers, String? query, ) async { var request = http.Request(method, Uri.parse({{ conf.host.to_host_string() }} + path + (query != null ? "?$query" : ""))); if (headers != null) { headers.forEach((k, v) => request.headers[k] = v); } if (input != null) { request.body = jsonEncode(input); } final streamedRes = await request.send(); var res = await http.Response.fromStream(streamedRes); final Map jsonData = jsonDecode(res.body); if (jsonData.containsKey("error")) { throw TeoError.fromJson(jsonData["error"]); } else { return convertFromJson(jsonData); } } String replacePathArguments(String path, Map args) { var resultPath = path; args.forEach((key, value) { resultPath = resultPath.replaceFirst("{$key}", value); }); return resultPath; }