diff --git a/CHANGELOG.md b/CHANGELOG.md index 7c92931..4f95814 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [0.6.0] - 2019-03-25 +### Changed +- JSON:API Document moved out +- Renamed `client.removeToOne` to `client.deleteToOne` + ## [0.5.0] - 2019-03-21 ### Changed - More BC-breaking changes in the Server @@ -47,7 +52,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added - Client: fetch resources, collections, related resources and relationships -[Unreleased]: https://github.com/f3ath/json-api-dart/compare/0.5.0...HEAD +[Unreleased]: https://github.com/f3ath/json-api-dart/compare/0.6.0...HEAD +[0.6.0]: https://github.com/f3ath/json-api-dart/compare/0.5.0...0.6.0 [0.5.0]: https://github.com/f3ath/json-api-dart/compare/0.4.0...0.5.0 [0.4.0]: https://github.com/f3ath/json-api-dart/compare/0.3.0...0.4.0 [0.3.0]: https://github.com/f3ath/json-api-dart/compare/0.2.0...0.3.0 diff --git a/README.md b/README.md index a9e9f0b..5a89b89 100644 --- a/README.md +++ b/README.md @@ -2,29 +2,27 @@ [JSON:API](http://jsonapi.org) is a specification for building APIs in JSON. This library implements a Client (VM, Flutter, Web), and a Server (VM only). -## Supported features -- Fetching single resources and resource collections +## Features +- Fetching single resources, resource collections, related resources +- Fetching/updating relationships +- Creating/updating/deleting resources - Collection pagination -- Fetching relationships and related resources and collections -- Fetching single resources -- Creating resources -- Deleting resources -- Updating resource's attributes -- Updating resource's relationships -- Updating relationships - Compound documents -- Related collection pagination - Asynchronous processing ## Usage -In the VM: +### Creating a client instance +JSON:API Client uses the Dart's native HttpClient. Depending on the platform, +you may want to use either the one which comes from `dart:io` or the `BrowserClient`. + +In the VM/Flutter you don't need to provide any dependencies: ```dart import 'package:json_api/client.dart'; final client = JsonApiClient(); ``` -In a browser: +In a browser use the `BrowserClient`: ```dart import 'package:json_api/client.dart'; import 'package:http/browser_client.dart'; @@ -32,4 +30,55 @@ import 'package:http/browser_client.dart'; final client = JsonApiClient(factory: () => BrowserClient()); ``` -For usage examples see the [functional tests](https://github.com/f3ath/json-api-dart/tree/master/test/functional). \ No newline at end of file +### Making requests +The client provides a set of methods to manipulate resources and relationships. +- Fetching + - `fetchCollection` - resource collection, either primary or related + - `fetchResource` - a single resource, either primary or related + - `fetchRelationship` - a generic relationship (either to-one, to-many or even incomplete) + - `fetchToOne` - a to-one relationship + - `fetchToMany` - a to-many relationship +- Manipulating resources + - `createResource` - creates a new primary resource + - `updateResource` - updates the existing resource by its type and id + - `deleteResource` - deletes the existing resource +- Manipulating relationships + - `replaceToOne` - replaces the existing to-one relationship with a new resource identifier + - `deleteToOne` - deletes the existing to-one relationship by setting the resrouce identifier to null + - `replaceToMany` - replaces the existing to-many relationship with the given set of resource identifiers + - `addToMany` - adds the given identifiers to the existing to-many relationship + +These methods accept the target URI and the object to update (except for fetch and delete requests). +You can also pass an optional map of HTTP headers e.g. for authentication. The return value +is `Response` object bearing the HTTP response status and headers and the JSON:API +document with the primary data according to the type of the request. + +Here's a collection fetching example: + +```dart +import 'package:json_api/client.dart'; + +void main() async { + final client = JsonApiClient(); + final companiesUri = Uri.parse('http://localhost:8080/companies'); + final response = await client.fetchCollection(companiesUri); + + print('Status: ${response.status}'); + print('Headers: ${response.headers}'); + + print('The collection page size is ${response.data.collection.length}'); + + final resource = response.data.collection.first.toResource(); + print('The first element is ${resource}'); + + print('Attributes:'); + resource.attributes.forEach((k, v) => print('$k=$v')); + + print('Relationships:'); + resource.toOne.forEach((k, v) => print('$k=$v')); + resource.toMany.forEach((k, v) => print('$k=$v')); +} +``` + + +For more usage examples refer to the [functional tests](https://github.com/f3ath/json-api-dart/tree/master/test/functional). \ No newline at end of file diff --git a/example/README.md b/example/README.md index f57bc3d..7704f96 100644 --- a/example/README.md +++ b/example/README.md @@ -7,5 +7,9 @@ You can run it locally to play around. - In you console run `dart example/cars_server.dart`, this will start the server at port 8080. - Open http://localhost:8080/companies in the browser. -## [Cars Client](./cars_client.dart) -A simple client for Cars Server API. It is also used in the tests. \ No newline at end of file +## [Fetch example](./fetch_collection.dart) +With the server running, call +``` +dart example/fetch_collection.dart +``` +This will make a `fetchCollection()` call and print the response. \ No newline at end of file diff --git a/example/fetch_collection.dart b/example/fetch_collection.dart new file mode 100644 index 0000000..8487ae3 --- /dev/null +++ b/example/fetch_collection.dart @@ -0,0 +1,19 @@ +import 'package:json_api/client.dart'; + +void main() async { + final client = JsonApiClient(); + final companiesUri = Uri.parse('http://localhost:8080/companies'); + final response = await client.fetchCollection(companiesUri); + print('Status: ${response.status}'); + print('Headers: ${response.headers}'); + + final resource = response.data.collection.first.toResource(); + + print('The collection page size is ${response.data.collection.length}'); + print('The first element is ${resource}'); + print('Attributes:'); + resource.attributes.forEach((k, v) => print('$k=$v')); + print('Relationships:'); + resource.toOne.forEach((k, v) => print('$k=$v')); + resource.toMany.forEach((k, v) => print('$k=$v')); +} diff --git a/lib/src/client/client.dart b/lib/src/client/client.dart index eb57552..e646aa8 100644 --- a/lib/src/client/client.dart +++ b/lib/src/client/client.dart @@ -88,7 +88,7 @@ class JsonApiClient { /// Removes a to-one relationship. This is equivalent to calling [replaceToOne] /// with id = null. - Future> removeToOne(Uri uri, {Map headers}) => + Future> deleteToOne(Uri uri, {Map headers}) => replaceToOne(uri, null, headers: headers); /// Replaces a to-many relationship with the given set of [ids]. diff --git a/test/browser_compat_test.dart b/test/browser_compat_test.dart index 8dddb2d..653cc54 100644 --- a/test/browser_compat_test.dart +++ b/test/browser_compat_test.dart @@ -8,7 +8,6 @@ void main() async { final channel = spawnHybridUri('test_server.dart'); final client = JsonApiClient(factory: () => BrowserClient()); final port = await channel.stream.first; - print('Port: $port'); final r = await client .fetchCollection(Uri.parse('http://localhost:$port/companies')); expect(r.status, 200); diff --git a/test/functional/update_test.dart b/test/functional/update_test.dart index 0054512..7a82c68 100644 --- a/test/functional/update_test.dart +++ b/test/functional/update_test.dart @@ -183,7 +183,7 @@ void main() async { final original = r0.document.data.toIdentifier(); expect(original.id, '2'); - final r1 = await client.removeToOne(url); + final r1 = await client.deleteToOne(url); expect(r1.status, 204); final r2 = await client.fetchToOne(url);