Files

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;
}
}