diff --git a/client/lib/src/client.dart b/client/lib/src/client.dart index 4bfc657..6475106 100644 --- a/client/lib/src/client.dart +++ b/client/lib/src/client.dart @@ -2,38 +2,97 @@ import 'dart:convert'; import 'dart:io'; import 'package:http/http.dart' as http; +import 'package:meta/meta.dart'; import 'package:musicus_database/musicus_database.dart'; /// A simple http client for the Musicus server. class MusicusClient { - /// The URL of the Musicus server to connect to. + /// URI scheme to use for the connection. + /// + /// This will be used as the scheme parameter when creating Uri objects. + final String scheme; + + /// The host name of the Musicus server to connect to. + /// + /// This will be used as the host parameter when creating Uri objects. final String host; + /// This will be used as the port parameter when creating Uri objects. + final int port; + final _client = http.Client(); - MusicusClient(this.host); + MusicusClient({ + this.scheme = 'https', + this.port = 443, + @required this.host, + }) : assert(scheme != null), + assert(port != null), + assert(host != null); + + /// Get a list of persons. + /// + /// You can get another page using the [page] parameter. If a non empty + /// [search] string is provided, the persons will get filtered based on that + /// string. + Future> getPersons([int page, String search]) async { + final params = {}; + + if (page != null) { + params['p'] = page.toString(); + } + + if (search != null) { + params['s'] = search; + } + + final response = await _client.get(Uri( + scheme: scheme, + host: host, + port: port, + path: '/persons', + queryParameters: params, + )); - /// Get a list of all available persons. - Future> getPersons() async { - final response = await _client.get('$host/persons'); final json = jsonDecode(response.body); return json.map((j) => Person.fromJson(j)).toList(); } /// Get a person by ID. Future getPerson(int id) async { - final response = await _client.get('$host/persons/$id'); + final response = await _client.get(Uri( + scheme: scheme, + host: host, + port: port, + path: '/persons/$id', + )); + final json = jsonDecode(response.body); return Person.fromJson(json); } + /// Delete a person by ID. + Future deletePerson(int id) async { + await _client.delete(Uri( + scheme: scheme, + host: host, + port: port, + path: '/persons/$id', + )); + } + /// Create or update a person. /// /// Returns true, if the operation was successful. Future putPerson(Person person) async { try { final response = await _client.put( - '$host/persons/${person.id}', + Uri( + scheme: scheme, + host: host, + port: port, + path: '/persons/${person.id}', + ), headers: {'Content-Type': 'application/json'}, body: jsonEncode(person.toJson()), ); @@ -44,16 +103,43 @@ class MusicusClient { } } - /// Get a list of all available instruments. - Future> getInstruments() async { - final response = await _client.get('$host/instruments'); + /// Get a list of instruments. + /// + /// You can get another page using the [page] parameter. If a non empty + /// [search] string is provided, the results will get filtered based on that + /// string. + Future> getInstruments([int page, String search]) async { + final params = {}; + + if (page != null) { + params['p'] = page.toString(); + } + + if (search != null) { + params['s'] = search; + } + + final response = await _client.get(Uri( + scheme: scheme, + host: host, + port: port, + path: '/instruments', + queryParameters: params, + )); + final json = jsonDecode(response.body); return json.map((j) => Instrument.fromJson(j)).toList(); } /// Get an instrument by ID. Future getInstrument(int id) async { - final response = await _client.get('$host/instruments/$id'); + final response = await _client.get(Uri( + scheme: scheme, + host: host, + port: port, + path: '/instruments/$id', + )); + final json = jsonDecode(response.body); return Instrument.fromJson(json); } @@ -64,7 +150,12 @@ class MusicusClient { Future putInstrument(Instrument instrument) async { try { final response = await _client.put( - '$host/instruments/${instrument.id}', + Uri( + scheme: scheme, + host: host, + port: port, + path: '/instruments/${instrument.id}', + ), headers: {'Content-Type': 'application/json'}, body: jsonEncode(instrument.toJson()), ); @@ -75,23 +166,86 @@ class MusicusClient { } } - /// Get all works composed by the person with the ID [personId]. - Future> getWorks(int personId) async { - final response = await _client.get('$host/persons/$personId/works'); + /// Delete an instrument by ID. + Future deleteInstrument(int id) async { + await _client.delete(Uri( + scheme: scheme, + host: host, + port: port, + path: '/instruments/$id', + )); + } + + /// Get a list of works written by the person with the ID [personId]. + /// + /// You can get another page using the [page] parameter. If a non empty + /// [search] string is provided, the results will get filtered based on that + /// string. + Future> getWorks(int personId, + [int page, String search]) async { + final params = {}; + + if (page != null) { + params['p'] = page.toString(); + } + + if (search != null) { + params['s'] = search; + } + + final response = await _client.get(Uri( + scheme: scheme, + host: host, + port: port, + path: '/persons/$personId/works', + queryParameters: params, + )); + final json = jsonDecode(response.body); return json.map((j) => WorkInfo.fromJson(j)).toList(); } /// Get a work by ID. Future getWork(int id) async { - final response = await _client.get('$host/works/$id'); + final response = await _client.get(Uri( + scheme: scheme, + host: host, + port: port, + path: '/works/$id', + )); + final json = jsonDecode(response.body); return WorkInfo.fromJson(json); } - /// Get all recordings of the work with the ID [workId]. - Future> getRecordings(int workId) async { - final response = await _client.get('$host/works/$workId/recordings'); + /// Delete a work by ID. + Future deleteWork(int id) async { + await _client.delete(Uri( + scheme: scheme, + host: host, + port: port, + path: '/works/$id', + )); + } + + /// Get a list of recordings of the work with the ID [workId]. + /// + /// You can get another page using the [page] parameter. + Future> getRecordings(int workId, [int page]) async { + final params = {}; + + if (page != null) { + params['p'] = page.toString(); + } + + final response = await _client.get(Uri( + scheme: scheme, + host: host, + port: port, + path: '/works/$workId/recordings', + queryParameters: params, + )); + final json = jsonDecode(response.body); return json.map((j) => RecordingInfo.fromJson(j)).toList(); } @@ -102,7 +256,12 @@ class MusicusClient { Future putWork(WorkInfo workInfo) async { try { final response = await _client.put( - '$host/works/${workInfo.work.id}', + Uri( + scheme: scheme, + host: host, + port: port, + path: '/works/${workInfo.work.id}', + ), headers: {'Content-Type': 'application/json'}, body: jsonEncode(workInfo.toJson()), ); @@ -113,16 +272,43 @@ class MusicusClient { } } - /// Get a list of all ensembles. - Future> getEnsembles() async { - final response = await _client.get('$host/ensembles'); + /// Get a list of ensembles. + /// + /// You can get another page using the [page] parameter. If a non empty + /// [search] string is provided, the results will get filtered based on that + /// string. + Future> getEnsembles([int page, String search]) async { + final params = {}; + + if (page != null) { + params['p'] = page.toString(); + } + + if (search != null) { + params['s'] = search; + } + + final response = await _client.get(Uri( + scheme: scheme, + host: host, + port: port, + path: '/ensembles', + queryParameters: params, + )); + final json = jsonDecode(response.body); return json.map((j) => Ensemble.fromJson(j)).toList(); } /// Get an ensemble by ID. Future getEnsemble(int id) async { - final response = await _client.get('$host/ensembles/$id'); + final response = await _client.get(Uri( + scheme: scheme, + host: host, + port: port, + path: '/ensembles/$id', + )); + final json = jsonDecode(response.body); return Ensemble.fromJson(json); } @@ -133,7 +319,12 @@ class MusicusClient { Future putEnsemble(Ensemble ensemble) async { try { final response = await _client.put( - '$host/ensembles/${ensemble.id}', + Uri( + scheme: scheme, + host: host, + port: port, + path: '/ensembles/${ensemble.id}', + ), headers: {'Content-Type': 'application/json'}, body: jsonEncode(ensemble.toJson()), ); @@ -144,9 +335,25 @@ class MusicusClient { } } + /// Delete an ensemble by ID. + Future deleteEnsemble(int id) async { + await _client.delete(Uri( + scheme: scheme, + host: host, + port: port, + path: '/ensembles/$id', + )); + } + /// Get a recording by ID. Future getRecording(int id) async { - final response = await _client.get('$host/recordings/$id'); + final response = await _client.get(Uri( + scheme: scheme, + host: host, + port: port, + path: '/recordings/$id', + )); + final json = jsonDecode(response.body); return RecordingInfo.fromJson(json); } @@ -157,7 +364,12 @@ class MusicusClient { Future putRecording(RecordingInfo recordingInfo) async { try { final response = await _client.put( - '$host/recordings/${recordingInfo.recording.id}', + Uri( + scheme: scheme, + host: host, + port: port, + path: '/recordings/${recordingInfo.recording.id}', + ), headers: {'Content-Type': 'application/json'}, body: jsonEncode(recordingInfo.toJson()), ); @@ -168,6 +380,16 @@ class MusicusClient { } } + /// Delete a recording by ID. + Future deleteRecording(int id) async { + await _client.delete(Uri( + scheme: scheme, + host: host, + port: port, + path: '/recordings/$id', + )); + } + /// Close the internal http client. void dispose() { _client.close(); diff --git a/client/pubspec.yaml b/client/pubspec.yaml index ba9945e..4d6bda6 100644 --- a/client/pubspec.yaml +++ b/client/pubspec.yaml @@ -7,5 +7,6 @@ environment: dependencies: http: + meta: musicus_database: path: ../database \ No newline at end of file