Skip to content

Commit c002030

Browse files
authored
Resource deletion (#27)
1 parent 869ce1a commit c002030

27 files changed

+447
-275
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
88
### Added
99
- Improved ResourceController error handling
1010
- Resource creation
11+
- Resource deletion
1112

1213
## 0.1.0 - 2019-02-27
1314
### Added

README.md

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,37 @@
11
# Implementation of [JSON:API v1.0](http://jsonapi.org) in Dart
22

3-
#### Feature roadmap
4-
##### Client
3+
### Feature roadmap
4+
#### Client
55
- [x] Fetching single resources and resource collections
66
- [x] Fetching relationships and related resources and collections
77
- [x] Fetching single resources
88
- [x] Creating resources
9+
- [x] Deleting resources
910
- [ ] Updating resource's attributes
1011
- [ ] Updating resource's relationships
1112
- [ ] Updating relationships
12-
- [ ] Deleting resources
1313
- [ ] Asynchronous processing
1414
- [ ] Optional check for `Content-Type` header in incoming responses
1515

16-
##### Server (The Server API is not stable yet!)
16+
#### Server (The Server API is not stable yet!)
1717
- [x] Fetching single resources and resource collections
1818
- [x] Fetching relationships and related resources and collections
1919
- [x] Fetching single resources
2020
- [x] Creating resources
21+
- [x] Deleting resources
2122
- [ ] Updating resource's attributes
2223
- [ ] Updating resource's relationships
2324
- [ ] Updating relationships
24-
- [ ] Deleting resources
2525
- [ ] Inclusion of related resources
2626
- [ ] Sparse fieldsets
2727
- [ ] Sorting, pagination, filtering
2828
- [ ] Asynchronous processing
2929
- [ ] Optional check for `Content-Type` header in incoming requests
3030
- [ ] Support annotations in resource mappers (?)
3131

32-
##### Document
33-
- [ ] Support `meta` and `jsonapi` members
32+
#### Document (The Document API is not stable yet!)
33+
- [ ] Support `meta` members
34+
- [ ] Support `jsonapi` members
3435
- [ ] Structure Validation including compound documents
3536
- [ ] Support relationship objects lacking the `data` member
3637
- [ ] Naming Validation

example/cars_server/controller.dart

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
import 'dart:async';
22

3-
import 'package:json_api/src/identifier.dart';
4-
import 'package:json_api/src/resource.dart';
3+
import 'package:json_api/src/document/identifier.dart';
4+
import 'package:json_api/src/document/resource.dart';
55
import 'package:json_api/src/server/numbered_page.dart';
6+
import 'package:json_api/src/server/request.dart';
67
import 'package:json_api/src/server/resource_controller.dart';
78
import 'package:uuid/uuid.dart';
89

@@ -17,9 +18,9 @@ class CarsController implements ResourceController {
1718
bool supports(String type) => dao.containsKey(type);
1819

1920
Future<Collection<Resource>> fetchCollection(
20-
String type, Map<String, String> params) async {
21-
final page =
22-
NumberedPage.fromQueryParameters(params, total: dao[type].length);
21+
String type, JsonApiHttpRequest request) async {
22+
final page = NumberedPage.fromQueryParameters(request.uri.queryParameters,
23+
total: dao[type].length);
2324
return Collection(
2425
dao[type]
2526
.fetchCollection(offset: page.number - 1)
@@ -40,7 +41,7 @@ class CarsController implements ResourceController {
4041

4142
@override
4243
Future<Resource> createResource(
43-
String type, Resource resource, Map<String, String> params) async {
44+
String type, Resource resource, JsonApiHttpRequest request) async {
4445
if (type != resource.type) {
4546
throw ResourceControllerException(409, detail: 'Incompatible type');
4647
}
@@ -57,4 +58,17 @@ class CarsController implements ResourceController {
5758
dao[type].insert(obj);
5859
return dao[type].toResource(obj);
5960
}
61+
62+
@override
63+
Future<Map<String, Object>> deleteResource(
64+
String type, String id, JsonApiHttpRequest request) async {
65+
if (dao[type].fetchById(id) == null) {
66+
throw ResourceControllerException(404, detail: 'Resource not found');
67+
}
68+
final deps = dao[type].deleteById(id);
69+
if (deps > 0) {
70+
return {'deps': deps};
71+
}
72+
return null;
73+
}
6074
}

example/cars_server/dao.dart

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
import 'package:json_api/src/identifier.dart';
2-
import 'package:json_api/src/resource.dart';
1+
import 'package:json_api/src/document/identifier.dart';
2+
import 'package:json_api/src/document/resource.dart';
33

44
import 'model.dart';
55

@@ -18,6 +18,12 @@ abstract class DAO<T> {
1818

1919
Iterable<T> fetchCollection({int offset = 0, int limit = 1}) =>
2020
_collection.values.skip(offset).take(limit);
21+
22+
/// Returns the number of depending objects the entity had
23+
int deleteById(String id) {
24+
_collection.remove(id);
25+
return 0;
26+
}
2127
}
2228

2329
class ModelDAO extends DAO<Model> {
@@ -59,4 +65,13 @@ class CompanyDAO extends DAO<Company> {
5965
Company create(Resource r) {
6066
return Company(r.id, r.attributes['name']);
6167
}
68+
69+
@override
70+
int deleteById(String id) {
71+
final company = fetchById(id);
72+
int deps = company.headquarters == null ? 0 : 1;
73+
deps += company.models.length;
74+
_collection.remove(id);
75+
return deps;
76+
}
6277
}

lib/client.dart

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,2 @@
11
export 'package:json_api/src/client/client.dart';
2-
export 'package:json_api/src/identifier.dart';
3-
export 'package:json_api/src/resource.dart';
2+
export 'package:json_api/src/document.dart';

lib/src/client/client.dart

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,12 @@ import 'package:json_api/src/client/status_code.dart';
77
import 'package:json_api/src/document/collection_document.dart';
88
import 'package:json_api/src/document/document.dart';
99
import 'package:json_api/src/document/error_document.dart';
10+
import 'package:json_api/src/document/meta_document.dart';
1011
import 'package:json_api/src/document/relationship.dart';
12+
import 'package:json_api/src/document/resource.dart';
1113
import 'package:json_api/src/document/resource_document.dart';
1214
import 'package:json_api/src/document/resource_object.dart';
1315
import 'package:json_api/src/nullable.dart';
14-
import 'package:json_api/src/resource.dart';
1516

1617
typedef D ResponseParser<D extends Document>(Object j);
1718

@@ -65,6 +66,11 @@ class JsonApiClient {
6566
_post(ResourceDocument.fromJson, uri,
6667
ResourceDocument(ResourceObject.fromResource(resource)), headers);
6768

69+
/// Deletes the resource.
70+
Future<Response<MetaDocument>> deleteResource(Uri uri,
71+
{Map<String, String> headers}) =>
72+
_delete(MetaDocument.fromJson, uri, headers);
73+
6874
// /// Adds the [identifiers] to a to-many relationship identified by [uri]
6975
// Future<Response<ToMany>> addToMany(Uri uri, Iterable<Identifier> identifiers,
7076
// {Map<String, String> headers}) =>
@@ -89,6 +95,15 @@ class JsonApiClient {
8995
..addAll(headers ?? {})
9096
..addAll({'Accept': contentType})));
9197

98+
Future<Response<D>> _delete<D extends Document>(
99+
ResponseParser<D> parse, uri, Map<String, String> headers) =>
100+
_call(
101+
parse,
102+
(_) => _.delete(uri,
103+
headers: {}
104+
..addAll(headers ?? {})
105+
..addAll({'Accept': contentType})));
106+
92107
Future<Response<D>> _post<D extends Document>(ResponseParser<D> parse, uri,
93108
Document document, Map<String, String> headers) =>
94109
_call(

lib/src/document.dart

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
export 'package:json_api/src/document/collection_document.dart';
2+
export 'package:json_api/src/document/document.dart';
3+
export 'package:json_api/src/document/error_document.dart';
4+
export 'package:json_api/src/document/error_object.dart';
5+
export 'package:json_api/src/document/identifier.dart';
6+
export 'package:json_api/src/document/identifier_object.dart';
7+
export 'package:json_api/src/document/link.dart';
8+
export 'package:json_api/src/document/meta_document.dart';
9+
export 'package:json_api/src/document/relationship.dart';
10+
export 'package:json_api/src/document/resource.dart';
11+
export 'package:json_api/src/document/resource_document.dart';
12+
export 'package:json_api/src/document/resource_object.dart';

lib/src/document/collection_document.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import 'package:json_api/src/document/document.dart';
22
import 'package:json_api/src/document/link.dart';
33
import 'package:json_api/src/document/resource_object.dart';
44

5-
class CollectionDocument implements Document {
5+
class CollectionDocument extends Document {
66
final List<ResourceObject> collection;
77
final List<ResourceObject> included;
88

lib/src/document/document.dart

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,7 @@
1-
abstract class Document {}
1+
class Document {
2+
final meta = <String, Object>{};
3+
4+
Document({Map<String, Object> meta}) {
5+
this.meta.addAll(meta ?? {});
6+
}
7+
}

lib/src/document/error_document.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import 'package:json_api/src/document/document.dart';
22
import 'package:json_api/src/document/error_object.dart';
33

4-
class ErrorDocument implements Document {
4+
class ErrorDocument extends Document {
55
final errors = <ErrorObject>[];
66

77
ErrorDocument(Iterable<ErrorObject> errors) {

0 commit comments

Comments
 (0)