diff --git a/restful.js/restful.js-tests.ts b/restful.js/restful.js-tests.ts
new file mode 100644
index 000000000..80f3bd187
--- /dev/null
+++ b/restful.js/restful.js-tests.ts
@@ -0,0 +1,198 @@
+///
+
+import restful, {
+ Api, MemberResponse, CollectionResponse, ResponseBody, CollectionEndpoint, MemberEndpoint,
+} from 'restful.js';
+
+class Article {
+ title: string;
+ body: string;
+}
+class Comment {
+ body: string;
+}
+class Author {
+ name: string;
+}
+
+var api: Api;
+
+api = restful('api.example.com');
+
+//
+// Usage
+//
+
+api = restful('api.example.com')
+ .header('AuthToken', 'test') // set global header
+ .prefixUrl('v1')
+ .protocol('https')
+ .port(8080);
+// resource now targets `https://api.example.com:8080/v1`
+
+
+var articlesCollection = api.all('articles'); // http://api.example.com/articles
+var articleMember = api.one('articles', 1); // http://api.example.com/articles/1
+var articleMember = api.one('articles', 1); // http://api.example.com/articles/1
+var commentsCollection = articleMember.all('comments'); // http://api.example.com/articles/1/comments
+
+var articleMember = api.oneUrl('articles', 'http://custom.url/article?id=1'); // http://custom.url/article?id=1
+var articlesCollection = api.allUrl('articles', 'http://custom.url/article/list'); // http://custom.url/article/list
+
+articleMember = api.one('articles', 1); // http://api.example.com/articles/1
+articleMember.get().then((response: MemberResponse) => {
+ var articleEntity = response.body();
+
+ var article = articleEntity.data();
+ console.log(article.title); // hello, world!
+});
+
+commentsCollection = articleMember.all('comments'); // http://api.example.com/articles/1/comments
+commentsCollection.getAll().then((response: CollectionResponse) => {
+ var commentEntities = response.body();
+
+ commentEntities.forEach((commentEntity: ResponseBody) => {
+ var comment = commentEntity.data();
+ console.log(comment.body);
+ })
+});
+
+// fetch http://api.example.com/articles/1/comments/4
+articleMember = api.one('articles', 1);
+let commentMember = articleMember.one('comments', 4);
+commentMember.get().then((response) => {
+ //
+});
+// equivalent to
+commentsCollection = articleMember.all('comments');
+commentsCollection.get(4).then((response) => {
+ //
+});
+
+//
+// Entity Data
+//
+
+var articleCollection = api.all('articles'); // http://api.example.com/articles
+
+// http://api.example.com/articles/1
+api.one('articles', 1).get().then((response: MemberResponse) => {
+ var articleEntity = response.body();
+
+ // if the server response was { id: 1, title: 'test', body: 'hello' }
+ var article = articleEntity.data();
+ article.title; // returns `test`
+ article.body; // returns `hello`
+ // You can also edit it
+ article.title = 'test2';
+ // Finally you can easily update it or delete it
+ articleEntity.save(); // will perform a PUT request
+ articleEntity.remove(); // will perform a DELETE request
+}, (response: any) => {
+ // The reponse code is not >= 200 and < 400
+ throw new Error('Invalid response');
+});
+
+articleMember = api.one('articles', 1); // http://api.example.com/articles/1
+commentMember = articleMember.one('comments', 3); // http://api.example.com/articles/1/comments/3
+commentMember.get()
+ .then((response: MemberResponse) => {
+ var commentEntity = response.body();
+
+ // You can also call `all` and `one` on an entity
+ return commentEntity.all('authors').getAll(); // http://api.example.com/articles/1/comments/3/authors
+}).then((response: CollectionResponse) => {
+ var authorEntities = response.body();
+
+ authorEntities.forEach((authorEntity: ResponseBody) => {
+ var author = authorEntity.data();
+ console.log(author.name);
+ });
+});
+
+// configure the api
+api.header('AuthToken', 'test');
+
+articlesCollection = api.all('articles');
+articlesCollection.get(1); // will send the `AuthToken` header
+// You can configure articlesCollection, too
+articlesCollection.header('foo', 'bar');
+
+//TODO: The line below was written in README.md but actually incorrect invocation, hence commented out
+//articlesCollection.one('comments', 1).get(); // will send both the AuthToken and foo headers
+
+
+// http://api.example.com/articles/1/comments/2/authors
+let authorsCollection = api.one('articles', 1).one('comments', 2).all('authors');
+authorsCollection.getAll().then(function(authorEntities) { /* */ });
+authorsCollection.get(1).then(function(authorEntity) { /* */ });
+
+
+//
+// Interceptors
+//
+
+var resource: Api;
+
+resource.addRequestInterceptor((data: any, headers: any, method: string, url: string) => {
+ // to edit the headers, just edit the headers object
+
+ // You always must return the data object
+ return data;
+});
+
+resource.addFullRequestInterceptor(function(params, headers, data, method, url) {
+ //...
+
+ // all args had been modified
+ return {
+ params: params,
+ headers: headers,
+ data: data,
+ method: method,
+ url: url
+ };
+
+ // just return modified arguments
+ return {
+ headers: headers,
+ data: data
+ };
+});
+
+resource.addFullResponseInterceptor(function(data, headers, method, url) {
+ // all args had been modified (method and url is read only)
+ return {
+ headers: headers,
+ data: data
+ };
+
+ // just return modified arguments
+ return {
+ headers: headers
+ };
+});
+
+//
+// Response methods
+//
+
+// http://api.example.com/articles/1/comments/2
+commentMember = api.one('articles', 1).one('comments', 2);
+commentMember.get().then(function(response) {
+ let commentEntity = response.body();
+ commentEntity.save();
+ commentEntity.remove();
+});
+
+//
+// Error Handling
+//
+
+commentMember = resource.one('articles', 1).one('comments', 2);
+commentMember
+ .get()
+ .then(function(commentEntity) { /* */ })
+ .catch(function(err) {
+ // deal with the error
+});
diff --git a/restful.js/restful.js.d.ts b/restful.js/restful.js.d.ts
new file mode 100644
index 000000000..2d62f113c
--- /dev/null
+++ b/restful.js/restful.js.d.ts
@@ -0,0 +1,245 @@
+// Type definitions for restful.js 0.6.2
+// Project: https://github.com/marmelab/restful.js
+// Definitions by: Qubo
+// Definitions: https://github.com/borisyankov/DefinitelyTyped
+
+///
+
+declare module "restful.js" {
+ export interface Headers {
+ [key: string]: any
+ }
+
+ export interface Api extends Endpoint {
+ all(name: string): CollectionEndpoint;
+ allUrl(name: string, url: string): CollectionEndpoint;
+ one(name: string, id: any): MemberEndpoint;
+ oneUrl(name: string, url: string): MemberEndpoint;
+ protocol(protocol: string): Api;
+ protocol(): string;
+ baseUrl(protocol: string): Api;
+ baseUrl(): string;
+ port(port: number): Api;
+ port(): number;
+ prefixUrl(prefix: string): Api;
+ prefixUrl(): string;
+ customUrl(url: string): Api;
+ customUrl(): string;
+ }
+
+ export interface MemberEndpoint extends Endpoint {
+ /**
+ * Target a child collection name.
+ * @param name
+ */
+ all(name: string): CollectionEndpoint;
+ allUrl(name: string, url: string): CollectionEndpoint;
+ /**
+ * Target a child member in a collection name.
+ * @param name
+ * @param id
+ */
+ one(name: string, id: any): MemberEndpoint;
+ oneUrl(name: string, url: string): MemberEndpoint;
+ /**
+ * Get a member. Returns a promise with an entity.
+ * @param params
+ * @param headers
+ */
+ get(params?: any, headers?: Headers): Promise>;
+ /**
+ * Update a member. Returns a promise with the response.
+ * @param data
+ * @param headers
+ */
+ put(data: any, headers?: Headers): Promise>;
+ /**
+ * Delete a member. Returns a promise with the response.
+ * @param data
+ * @param headers
+ */
+ delete(data?: any, headers?: Headers): Promise>;
+ /**
+ * Patch a member. Returns a promise with the response.
+ * @param data
+ * @param headers
+ */
+ patch(data: any, headers?: Headers): Promise>;
+ /**
+ * Perform a HEAD request on a member. Returns a promise with the response.
+ * @param headers
+ */
+ head(headers?: any): Promise>;
+ customUrl(url: string): MemberEndpoint;
+ customUrl(): string;
+ }
+
+ export interface CollectionEndpoint extends Endpoint {
+ /**
+ * Get a member in a collection. Returns a promise with an entity.
+ * @param id
+ */
+ get(id: any, params?: any, headers?: Headers): Promise>;
+ /**
+ * Get a full collection. Returns a promise with an array of entities.
+ */
+ getAll(params?: any, headers?: Headers): Promise>;
+ /**
+ * Create a member in a collection. Returns a promise with the response.
+ */
+ post(data: any, headers?: Headers): Promise>;
+ /**
+ * Update a member in a collection. Returns a promise with the response.
+ * @param id
+ * @param data
+ * @param headers
+ */
+ put(id: any, data: any, headers?: Headers): Promise>;
+ /**
+ * Delete a member in a collection. Returns a promise with the response.
+ * @param id
+ * @param data
+ * @param headers
+ */
+ delete(id: any, data?: any, headers?: Headers): Promise>;
+ /**
+ * Patch a member in a collection. Returns a promise with the response.
+ * @param id
+ * @param data
+ * @param headers
+ */
+ patch(id: any, data: any, headers?: Headers): Promise>;
+ /**
+ * Perform a HEAD request on a member in a collection. Returns a promise with the response.
+ * @param id
+ * @param headers
+ */
+ head(id: any, headers?: Headers): Promise>;
+ }
+
+ export interface Endpoint {
+ /**
+ * Get the url.
+ */
+ url(): string;
+ /**
+ * Add a response interceptor. You can only alter data and headers.
+ */
+ addResponseInterceptor(interceptor: ResponseInterceptor): Self;
+ responseInterceptors(): ResponseInterceptor[];
+ /**
+ * Add a request interceptor.
+ */
+ addRequestInterceptor(interceptor: RequestInterceptor): Self;
+ requestInterceptors(): RequestInterceptor[];
+ /**
+ * Add a full response interceptor. You can alter data and headers.
+ */
+ addFullResponseInterceptor(interceptor: ResponseInterceptor): Self;
+ fullResponseInterceptors(): ResponseInterceptor[];
+ /**
+ * Add a full request interceptor. You can alter params, headers, data, method and url.
+ */
+ addFullRequestInterceptor(interceptor: FullRequestInterceptor): Self;
+ fullRequestInterceptors(): FullRequestInterceptor[];
+ /**
+ * Add a header.
+ * @param name
+ * @param value
+ */
+ header(name: string, value: any): Self;
+ headers(): Headers;
+ }
+
+ export interface MemberResponse extends ResponseBase {
+ (): {
+ data: T;
+ headers: Headers;
+ status: number;
+ statusText: string;
+ }
+ body(): ResponseBody;
+ }
+
+ export interface CollectionResponse extends ResponseBase {
+ (): {
+ data: T[];
+ headers: Headers;
+ status: number;
+ statusText: string;
+ }
+ body(): ResponseBody[];
+ }
+
+ export interface ResponseBase {
+ status(): number;
+ headers(): Headers;
+ config(): any;
+ }
+
+ export interface ResponseBody {
+ /**
+ * Get the JS object unserialized from the response body (which must be in JSON)
+ */
+ data(): T;
+ (): T;
+ /**
+ * Query a collection child of the entity.
+ * @param entity
+ */
+ all(entity: string): CollectionEndpoint;
+ /**
+ * Query a member child of the entity.
+ * @param entity
+ * @param id
+ */
+ one(entity: string, id: any): MemberEndpoint;
+ /**
+ * Update the member link to the entity. Returns a promise with the response.
+ * @param headers
+ */
+ save(headers?: Headers): void;
+ /**
+ * Delete the member link to the entity. Returns a promise with the response.
+ */
+ remove(headers?: Headers): void;
+ /**
+ * Get the entity url.
+ */
+ url(): string;
+ /**
+ * Get the id of the entity.
+ */
+ id(): any;
+ }
+
+ export interface RequestInterceptor {
+ (data: any, headers: Headers, method: string, url: string): any;
+ }
+
+ export interface FullRequestInterceptor {
+ (params: any, headers: Headers, data: any, method: string, url: string): FullRequestInterceptorReturnValue;
+ }
+
+ export interface FullRequestInterceptorReturnValue {
+ params?: any;
+ headers?: Headers;
+ data?: any;
+ method?: string;
+ url?: string;
+ }
+
+ export interface ResponseInterceptor {
+ (data: any, headers: Headers, method: string, url: string): ResponseInterceptorReturnValue;
+ }
+
+ export interface ResponseInterceptorReturnValue {
+ headers?: Headers;
+ data?: any;
+ method?: string;
+ url?: string;
+ }
+
+ export default function restful(endpoint: string): Api;
+}
+