Skip to content
This repository has been archived by the owner on Feb 17, 2020. It is now read-only.

Commit

Permalink
Browser
Browse files Browse the repository at this point in the history
  • Loading branch information
thosakwe committed Jun 25, 2016
1 parent 2a1f0ec commit 6f7321a
Show file tree
Hide file tree
Showing 9 changed files with 427 additions and 4 deletions.
10 changes: 6 additions & 4 deletions README.md
Expand Up @@ -2,15 +2,17 @@
Client library for the Angel framework.

# Isomorphic
The REST client depends on `http`, because it can run in the browser or on the command-line.
Depending on your environment, you must pass an instance of `BaseClient` to the constructor.
The REST client can run in the browser or on the command-line.

# Usage
This library provides the same API as an Angel server.

```dart
import 'package:angel_client/angel_client.dart';
import 'package:http/browser_client.dart';
// Import this file to import symbols "Angel" and "Service"
import 'package:angel_cli/shared.dart';
// Choose one or the other, depending on platform
import 'package:angel_client/cli.dart';
import 'package:angel_client/browser.dart';
main() async {
Angel app = new Rest("http://localhost:3000", new BrowserClient());
Expand Down
92 changes: 92 additions & 0 deletions lib/browser.dart
@@ -0,0 +1,92 @@
/// Browser library for the Angel framework.
library angel_client.browser;

import 'dart:async';
import 'dart:convert' show JSON;
import 'dart:html';
import 'shared.dart';

_buildQuery(Map params) {
if (params == null || params == {})
return "";

String result = "";
return result;
}

/// Queries an Angel server via REST.
class Rest extends Angel {
Rest(String basePath) :super(basePath);

@override
RestService service(String path, {Type type}) {
String uri = path.replaceAll(new RegExp(r"(^\/)|(\/+$)"), "");
return new RestService._base("$basePath/$uri")
..app = this;
}
}

/// Queries an Angel service via REST.
class RestService extends Service {
String basePath;

RestService._base(Pattern path) {
this.basePath = (path is RegExp) ? path.pattern : path;
}

_makeBody(data) {
return JSON.encode(data);
}

HttpRequest _buildRequest(String url,
{String method: "POST", bool write: true}) {
HttpRequest request = new HttpRequest();
request.open(method, url, async: false);
request.responseType = "json";
request.setRequestHeader("Accept", "application/json");
if (write)
request.setRequestHeader("Content-Type", "application/json");
return request;
}

@override
Future<List> index([Map params]) async {
return JSON.decode(
await HttpRequest.getString("$basePath/${_buildQuery(params)}"));
}

@override
Future read(id, [Map params]) async {
return JSON.decode(
await HttpRequest.getString("$basePath/$id${_buildQuery(params)}"));
}

@override
Future create(data, [Map params]) async {
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");
request.send(_makeBody(data));
return request.response;
}

@override
Future update(id, data, [Map params]) async {
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");
request.send();
return request.response;
}
}

110 changes: 110 additions & 0 deletions lib/cli.dart
@@ -0,0 +1,110 @@
/// Command-line client library for the Angel framework.
library angel_client.cli;

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

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

/// Queries an Angel server via REST.
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<List> 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);
}
}

44 changes: 44 additions & 0 deletions lib/shared.dart
@@ -0,0 +1,44 @@
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<List> 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]);
}
10 changes: 10 additions & 0 deletions test/browser.dart
@@ -0,0 +1,10 @@
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");

print(await Todos.index());
}

0 comments on commit 6f7321a

Please sign in to comment.