108 lines
3.0 KiB
Dart
108 lines
3.0 KiB
Dart
import 'dart:convert';
|
|
import 'package:http/http.dart' as http;
|
|
import 'models.dart';
|
|
|
|
class APIError implements Exception {
|
|
final int statusCode;
|
|
final String message;
|
|
APIError(this.statusCode, this.message);
|
|
@override
|
|
String toString() => 'APIError $statusCode: $message';
|
|
}
|
|
|
|
class APIClient {
|
|
final String baseUrl;
|
|
|
|
APIClient({this.baseUrl = 'http://localhost:8000'});
|
|
|
|
String _url(String path) => '$baseUrl$path';
|
|
|
|
static dynamic _decodeBody(http.Response response) {
|
|
return jsonDecode(response.body);
|
|
}
|
|
|
|
static Map<String, dynamic>? _asMap(dynamic d) {
|
|
if (d is Map<String, dynamic>) return d;
|
|
if (d is Map) return d.cast<String, dynamic>();
|
|
return null;
|
|
}
|
|
|
|
static void _checkError(http.Response response) {
|
|
if (response.statusCode >= 400) {
|
|
final body = _decodeBody(response);
|
|
final map = _asMap(body) ?? {};
|
|
throw APIError(
|
|
response.statusCode,
|
|
map['error'] as String? ?? 'Request failed',
|
|
);
|
|
}
|
|
}
|
|
|
|
Future<List<Pipeline>> listPipelines() async {
|
|
final res = await http.get(Uri.parse(_url('/api/pipelines')));
|
|
_checkError(res);
|
|
final data = _decodeBody(res);
|
|
final arr = data is List ? data : [];
|
|
final result = <Pipeline>[];
|
|
for (final e in arr) {
|
|
final m = _asMap(e);
|
|
if (m != null) result.add(Pipeline.fromJson(m));
|
|
}
|
|
return result;
|
|
}
|
|
|
|
Future<Pipeline> getPipeline(String id) async {
|
|
final res = await http.get(Uri.parse(_url('/api/pipelines/$id')));
|
|
_checkError(res);
|
|
final data = _decodeBody(res);
|
|
final map = _asMap(data) ?? {};
|
|
final inner = _asMap(map['data']) ?? map;
|
|
return Pipeline.fromJson(inner);
|
|
}
|
|
|
|
Future<Pipeline> createPipeline(Pipeline pipeline) async {
|
|
final res = await http.post(
|
|
Uri.parse(_url('/api/pipelines')),
|
|
headers: {'Content-Type': 'application/json'},
|
|
body: jsonEncode(pipeline.toJson()),
|
|
);
|
|
_checkError(res);
|
|
final data = _decodeBody(res);
|
|
final map = _asMap(data) ?? {};
|
|
final inner = _asMap(map['data']) ?? map;
|
|
return Pipeline.fromJson(inner);
|
|
}
|
|
|
|
Future<void> deletePipeline(String id) async {
|
|
final res = await http.delete(Uri.parse(_url('/api/pipelines/$id')));
|
|
_checkError(res);
|
|
}
|
|
|
|
Future<Map<String, dynamic>> startRun(String pipelineId) async {
|
|
final res = await http.post(
|
|
Uri.parse(_url('/api/runs')),
|
|
headers: {'Content-Type': 'application/json'},
|
|
body: jsonEncode({'pipeline_id': pipelineId}),
|
|
);
|
|
_checkError(res);
|
|
final data = _decodeBody(res);
|
|
final map = _asMap(data) ?? {};
|
|
return _asMap(map['data']) ?? map;
|
|
}
|
|
|
|
Future<RunState> getRunStatus(String runId) async {
|
|
final res = await http.get(Uri.parse(_url('/api/runs/$runId/status')));
|
|
_checkError(res);
|
|
final data = _decodeBody(res);
|
|
final map = _asMap(data) ?? {};
|
|
final inner = _asMap(map['data']) ?? map;
|
|
return RunState.fromJson(inner);
|
|
}
|
|
|
|
Future<String> getRunLog(String runId) async {
|
|
final res = await http.get(Uri.parse(_url('/api/runs/$runId/log')));
|
|
_checkError(res);
|
|
return res.body;
|
|
}
|
|
}
|