diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000..a2eb533 Binary files /dev/null and b/.DS_Store differ diff --git a/lib/angel_client.dart b/lib/angel_client.dart index ac8a8d3..9ecc152 100644 --- a/lib/angel_client.dart +++ b/lib/angel_client.dart @@ -2,11 +2,6 @@ library angel_client; import 'dart:async'; -import 'dart:convert' show JSON; -import 'package:http/http.dart'; -import 'package:json_god/json_god.dart' as god; - -part 'rest.dart'; /// A function that configures an [Angel] client in some way. typedef Future AngelConfigurer(Angel app); @@ -47,4 +42,4 @@ abstract class Service { /// Removes the given resource. Future remove(id, [Map params]); -} \ No newline at end of file +} diff --git a/lib/browser.dart b/lib/browser.dart index 86ffa0e..79307dd 100644 --- a/lib/browser.dart +++ b/lib/browser.dart @@ -4,7 +4,8 @@ library angel_client.browser; import 'dart:async'; import 'dart:convert' show JSON; import 'dart:html'; -import 'shared.dart'; +import 'angel_client.dart'; +export 'angel_client.dart'; _buildQuery(Map params) { if (params == null || params == {}) @@ -21,7 +22,7 @@ class Rest extends Angel { @override RestService service(String path, {Type type}) { String uri = path.replaceAll(new RegExp(r"(^\/)|(\/+$)"), ""); - return new RestService._base("$basePath/$uri") + return new RestService("$basePath/$uri") ..app = this; } } @@ -30,7 +31,7 @@ class Rest extends Angel { class RestService extends Service { String basePath; - RestService._base(Pattern path) { + RestService(Pattern path) { this.basePath = (path is RegExp) ? path.pattern : path; } @@ -38,7 +39,7 @@ class RestService extends Service { return JSON.encode(data); } - HttpRequest _buildRequest(String url, + HttpRequest buildRequest(String url, {String method: "POST", bool write: true}) { HttpRequest request = new HttpRequest(); request.open(method, url, async: false); @@ -63,30 +64,29 @@ class RestService extends Service { @override Future create(data, [Map params]) async { - var request = _buildRequest("$basePath/${_buildQuery(params)}"); + var request = buildRequest("$basePath/${_buildQuery(params)}"); request.send(_makeBody(data)); return request.response; } @override Future modify(id, data, [Map params]) async { - var request = _buildRequest("$basePath/$id${_buildQuery(params)}", method: "PATCH"); + var request = buildRequest("$basePath/$id${_buildQuery(params)}", method: "PATCH"); request.send(_makeBody(data)); return request.response; } @override Future update(id, data, [Map params]) async { - var request = _buildRequest("$basePath/$id${_buildQuery(params)}"); + var request = buildRequest("$basePath/$id${_buildQuery(params)}"); request.send(_makeBody(data)); return request.response; } @override Future remove(id, [Map params]) async { - var request = _buildRequest("$basePath/$id${_buildQuery(params)}", method: "DELETE"); + var request = buildRequest("$basePath/$id${_buildQuery(params)}", method: "DELETE"); request.send(); return request.response; } } - diff --git a/lib/cli.dart b/lib/cli.dart index 837c70a..cf72778 100644 --- a/lib/cli.dart +++ b/lib/cli.dart @@ -5,7 +5,8 @@ import 'dart:async'; import 'dart:convert' show JSON; import 'package:http/http.dart'; import 'package:json_god/json_god.dart' as god; -import 'shared.dart'; +import 'angel_client.dart'; +export 'angel_client.dart'; _buildQuery(Map params) { if (params == null || params == {}) @@ -107,4 +108,3 @@ class RestService extends Service { return god.deserialize(response.body, outputType: outputType); } } - diff --git a/lib/rest.dart b/lib/rest.dart deleted file mode 100644 index 072fda4..0000000 --- a/lib/rest.dart +++ /dev/null @@ -1,101 +0,0 @@ -part of angel_client; - -_buildQuery(Map params) { - if (params == null || params == {}) - return ""; - - String result = ""; - return result; -} - -const Map _readHeaders = const { - "Accept": "application/json" -}; - -const Map _writeHeaders = const { - "Accept": "application/json", - "Content-Type": "application/json" -}; - -class Rest extends Angel { - BaseClient client; - - Rest(String path, BaseClient this.client) :super(path); - - @override - RestService service(String path, {Type type}) { - String uri = path.replaceAll(new RegExp(r"(^\/)|(\/+$)"), ""); - return new RestService._base("$basePath/$uri", client, type) - ..app = this; - } -} - -/// Queries an Angel service via REST. -class RestService extends Service { - String basePath; - BaseClient client; - Type outputType; - - RestService._base(Pattern path, BaseClient this.client, - Type this.outputType) { - this.basePath = (path is RegExp) ? path.pattern : path; - } - - _makeBody(data) { - if (outputType == null) - return JSON.encode(data); - else return god.serialize(data); - } - - @override - Future index([Map params]) async { - var response = await client.get( - "$basePath/${_buildQuery(params)}", headers: _readHeaders); - - if (outputType == null) - return god.deserialize(response.body); - - else { - return JSON.decode(response.body).map((x) => - god.deserializeDatum(x, outputType: outputType)).toList(); - } - } - - @override - Future read(id, [Map params]) async { - var response = await client.get( - "$basePath/$id${_buildQuery(params)}", headers: _readHeaders); - return god.deserialize(response.body, outputType: outputType); - } - - @override - Future create(data, [Map params]) async { - var response = await client.post( - "$basePath/${_buildQuery(params)}", body: _makeBody(data), - headers: _writeHeaders); - return god.deserialize(response.body, outputType: outputType); - } - - @override - Future modify(id, data, [Map params]) async { - var response = await client.patch( - "$basePath/$id${_buildQuery(params)}", body: _makeBody(data), - headers: _writeHeaders); - return god.deserialize(response.body, outputType: outputType); - } - - @override - Future update(id, data, [Map params]) async { - var response = await client.patch( - "$basePath/$id${_buildQuery(params)}", body: _makeBody(data), - headers: _writeHeaders); - return god.deserialize(response.body, outputType: outputType); - } - - @override - Future remove(id, [Map params]) async { - var response = await client.delete( - "$basePath/$id${_buildQuery(params)}", headers: _readHeaders); - return god.deserialize(response.body, outputType: outputType); - } -} diff --git a/lib/shared.dart b/lib/shared.dart deleted file mode 100644 index 654b316..0000000 --- a/lib/shared.dart +++ /dev/null @@ -1,44 +0,0 @@ -import 'dart:async'; - -/// A function that configures an [Angel] client in some way. -typedef Future AngelConfigurer(Angel app); - -/// Represents an Angel server that we are querying. -abstract class Angel { - /// The URL of the server. - String basePath; - - Angel(String this.basePath); - - /// Applies an [AngelConfigurer] to this instance. - Future configure(AngelConfigurer configurer) async { - await configurer(this); - } - - /// Returns a representation of a service on the server. - Service service(Pattern path, {Type type}); -} - -/// Queries a service on an Angel server, with the same API. -abstract class Service { - /// The Angel instance powering this service. - Angel app; - - /// Retrieves all resources. - Future index([Map params]); - - /// Retrieves the desired resource. - Future read(id, [Map params]); - - /// Creates a resource. - Future create(data, [Map params]); - - /// Modifies a resource. - Future modify(id, data, [Map params]); - - /// Overwrites a resource. - Future update(id, data, [Map params]); - - /// Removes the given resource. - Future remove(id, [Map params]); -} \ No newline at end of file diff --git a/pubspec.yaml b/pubspec.yaml index 61969cd..a51c40b 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,5 +1,5 @@ name: angel_client -version: 1.0.0-dev+1 +version: 1.0.0-dev+6 description: Client library for the Angel framework. author: Tobe O homepage: https://github.com/angel-dart/angel_client @@ -9,4 +9,4 @@ dependencies: merge_map: ">=1.0.0 <2.0.0" dev_dependencies: angel_framework: ">=1.0.0-dev <2.0.0" - test: ">= 0.12.13 < 0.13.0" \ No newline at end of file + test: ">= 0.12.13 < 0.13.0" diff --git a/test/.DS_Store b/test/.DS_Store new file mode 100644 index 0000000..f17ada4 Binary files /dev/null and b/test/.DS_Store differ diff --git a/test/browser.dart b/test/browser.dart index a5b5295..5eb50ac 100644 --- a/test/browser.dart +++ b/test/browser.dart @@ -1,10 +1,11 @@ -import 'package:angel_client/shared.dart'; import 'package:angel_client/browser.dart'; import 'package:test/test.dart'; main() async { - Angel app = new Rest("http://localhost:3000"); - Service Todos = app.service("todos"); + test("list todos", () async { + Angel app = new Rest("http://localhost:3001"); + Service Todos = app.service("todos"); - print(await Todos.index()); -} \ No newline at end of file + print(await Todos.index()); + }); +} diff --git a/test/cli.dart b/test/cli.dart index f10192d..f632ca6 100644 --- a/test/cli.dart +++ b/test/cli.dart @@ -1,5 +1,4 @@ import 'dart:io'; -import 'package:angel_client/shared.dart' as clientLib; import 'package:angel_client/cli.dart' as client; import 'package:angel_framework/angel_framework.dart' as server; import 'package:http/http.dart' as http; @@ -11,18 +10,19 @@ main() { group("rest", () { server.Angel serverApp = new server.Angel(); server.HookedService serverPostcards; - clientLib.Angel clientApp; - clientLib.Service clientPostcards; - clientLib.Service clientTypedPostcards; + client.Angel clientApp; + client.Service clientPostcards; + client.Service clientTypedPostcards; HttpServer httpServer; + String url; setUp(() async { - httpServer = - await serverApp.startServer(InternetAddress.LOOPBACK_IP_V4, 3000); + httpServer = await serverApp.startServer(InternetAddress.LOOPBACK_IP_V4, 0); + url = "http://localhost:${httpServer.port}"; serverApp.use("/postcards", new server.MemoryService()); serverPostcards = serverApp.service("postcards"); - clientApp = new client.Rest("http://localhost:3000", new http.Client()); + clientApp = new client.Rest(url, new http.Client()); clientPostcards = clientApp.service("postcards"); clientTypedPostcards = clientApp.service("postcards", type: Postcard); }); @@ -131,4 +131,4 @@ main() { expect(removed2, equals(remove2)); }); }); -} \ No newline at end of file +} diff --git a/test/for_browser_tests.dart b/test/for_browser_tests.dart index ea5253c..072f1d5 100644 --- a/test/for_browser_tests.dart +++ b/test/for_browser_tests.dart @@ -1,5 +1,6 @@ import 'dart:io'; -import 'package:angel_framework/angel_framework.dart'; +import "package:angel_framework/angel_framework.dart"; +import "package:angel_framework/defs.dart"; main() async { Angel app = new Angel(); @@ -9,12 +10,12 @@ main() async { app.use("/todos", new MemoryService()); - await app.startServer(InternetAddress.LOOPBACK_IP_V4, 3000); - print("Server up on localhost:3000"); + await app.startServer(InternetAddress.LOOPBACK_IP_V4, 3001); + print("Server up on localhost:3001"); } class Todo extends MemoryModel { String hello; Todo({String this.hello}); -} \ No newline at end of file +} diff --git a/test/rest.dart b/test/rest.dart deleted file mode 100644 index 0bcdb6b..0000000 --- a/test/rest.dart +++ /dev/null @@ -1,133 +0,0 @@ -import 'dart:io'; -import 'package:angel_client/angel_client.dart' as client; -import 'package:angel_framework/angel_framework.dart' as server; -import 'package:http/http.dart' as http; -import 'package:json_god/json_god.dart' as god; -import 'package:test/test.dart'; -import 'shared.dart'; - -main() { - group("rest", () { - server.Angel serverApp = new server.Angel(); - server.HookedService serverPostcards; - client.Angel clientApp; - client.Service clientPostcards; - client.Service clientTypedPostcards; - HttpServer httpServer; - - setUp(() async { - httpServer = - await serverApp.startServer(InternetAddress.LOOPBACK_IP_V4, 3000); - serverApp.use("/postcards", new server.MemoryService()); - serverPostcards = serverApp.service("postcards"); - - clientApp = new client.Rest("http://localhost:3000", new http.Client()); - clientPostcards = clientApp.service("postcards"); - clientTypedPostcards = clientApp.service("postcards", type: Postcard); - }); - - tearDown(() async { - await httpServer.close(force: true); - }); - - test("index", () async { - Postcard niagaraFalls = await serverPostcards.create( - new Postcard(location: "Niagara Falls", message: "Missing you!")); - List indexed = await clientPostcards.index(); - print(indexed); - - expect(indexed.length, equals(1)); - expect(indexed[0].keys.length, equals(3)); - expect(indexed[0]['id'], equals(niagaraFalls.id)); - expect(indexed[0]['location'], equals(niagaraFalls.location)); - expect(indexed[0]['message'], equals(niagaraFalls.message)); - - Postcard louvre = await serverPostcards.create(new Postcard( - location: "The Louvre", message: "The Mona Lisa was watching me!")); - print(god.serialize(louvre)); - List typedIndexed = await clientTypedPostcards.index(); - expect(typedIndexed.length, equals(2)); - expect(typedIndexed[1], equals(louvre)); - }); - - test("create/read", () async { - Map opry = {"location": "Grand Ole Opry", "message": "Yeehaw!"}; - var created = await clientPostcards.create(opry); - print(created); - - expect(created['id'] == null, equals(false)); - expect(created["location"], equals(opry["location"])); - expect(created["message"], equals(opry["message"])); - - var read = await clientPostcards.read(created['id']); - print(read); - expect(read['id'], equals(created['id'])); - expect(read['location'], equals(created['location'])); - expect(read['message'], equals(created['message'])); - - Postcard canyon = new Postcard(location: "Grand Canyon", - message: "But did you REALLY experience it???"); - created = await clientTypedPostcards.create(canyon); - print(god.serialize(created)); - - expect(created.location, equals(canyon.location)); - expect(created.message, equals(canyon.message)); - - read = await clientTypedPostcards.read(created.id); - print(god.serialize(read)); - expect(read.id, equals(created.id)); - expect(read.location, equals(created.location)); - expect(read.message, equals(created.message)); - }); - - test("modify/update", () async { - server.MemoryService innerPostcards = serverPostcards.inner; - print(innerPostcards.items); - Postcard mecca = await clientTypedPostcards.create( - new Postcard(location: "Mecca", message: "Pilgrimage")); - print(god.serialize(mecca)); - - // I'm too lazy to write the tests twice, because I know it works - // So I'll modify using the type-based client, and update using the - // map-based one - - print("Postcards on server: " + - god.serialize(await serverPostcards.index())); - print("Postcards on client: " + - god.serialize(await clientPostcards.index())); - - Postcard modified = await clientTypedPostcards.modify( - mecca.id, {"location": "Saudi Arabia"}); - print(god.serialize(modified)); - expect(modified.id, equals(mecca.id)); - expect(modified.location, equals("Saudi Arabia")); - expect(modified.message, equals(mecca.message)); - - Map updated = await clientPostcards.update( - mecca.id, {"location": "Full", "message": "Overwrite"}); - print(updated); - - expect(updated.keys.length, equals(3)); - expect(updated['id'], equals(mecca.id)); - expect(updated['location'], equals("Full")); - expect(updated['message'], equals("Overwrite")); - }); - - test("remove", () async { - Postcard remove1 = await clientTypedPostcards.create( - {"location": "remove", "message": "#1"}); - Postcard remove2 = await clientTypedPostcards.create( - {"location": "remove", "message": "#2"}); - print(god.serialize([remove1, remove2])); - - Map removed1 = await clientPostcards.remove(remove1.id); - expect(removed1.keys.length, equals(3)); - expect(removed1['id'], equals(remove1.id)); - expect(removed1['location'], equals(remove1.location)); - expect(removed1['message'], equals(remove1.message)); - - Postcard removed2 = await clientTypedPostcards.remove(remove2.id); - expect(removed2, equals(remove2)); - }); - }); -} \ No newline at end of file diff --git a/test/shared.dart b/test/shared.dart index 4b6621a..a7f4e66 100644 --- a/test/shared.dart +++ b/test/shared.dart @@ -1,4 +1,4 @@ -import 'package:angel_framework/angel_framework.dart'; +import "package:angel_framework/defs.dart"; class Postcard extends MemoryModel { int id;