diff --git a/angular-odata-resources/angular-odata-resources-tests.ts b/angular-odata-resources/angular-odata-resources-tests.ts
new file mode 100644
index 0000000000..4a1d4dbc50
--- /dev/null
+++ b/angular-odata-resources/angular-odata-resources-tests.ts
@@ -0,0 +1,188 @@
+///
+
+interface IMyResource extends OData.IResource { };
+interface IMyResourceClass extends OData.IResourceClass { };
+
+///////////////////////////////////////
+// IActionDescriptor
+///////////////////////////////////////
+var actionDescriptor: OData.IActionDescriptor;
+
+actionDescriptor.url = '/api/test-url/'
+actionDescriptor.headers = { header: 'value' };
+actionDescriptor.isArray = true;
+actionDescriptor.method = 'method action';
+actionDescriptor.params = { key: 'value' };
+
+///////////////////////////////////////
+// IResourceClass
+///////////////////////////////////////
+var resourceClass: IMyResourceClass;
+var resource: IMyResource;
+var resourceArray: OData.IResourceArray;
+
+resource = resourceClass.delete();
+resource = resourceClass.delete({ key: 'value' });
+resource = resourceClass.delete({ key: 'value' }, function() { });
+resource = resourceClass.delete(function() { });
+resource = resourceClass.delete(function() { }, function() { });
+resource = resourceClass.delete({ key: 'value' }, { key: 'value' });
+resource = resourceClass.delete({ key: 'value' }, { key: 'value' }, function() { });
+resource = resourceClass.delete({ key: 'value' }, { key: 'value' }, function() { }, function() { });
+resource.$promise.then(function(data: IMyResource) { });
+
+resource = resourceClass.get();
+resource = resourceClass.get({ key: 'value' });
+resource = resourceClass.get({ key: 'value' }, function() { });
+resource = resourceClass.get(function() { });
+resource = resourceClass.get(function() { }, function() { });
+resource = resourceClass.get({ key: 'value' }, { key: 'value' });
+resource = resourceClass.get({ key: 'value' }, { key: 'value' }, function() { });
+resource = resourceClass.get({ key: 'value' }, { key: 'value' }, function() { }, function() { });
+
+resourceArray = resourceClass.query();
+resourceArray = resourceClass.query({ key: 'value' });
+resourceArray = resourceClass.query({ key: 'value' }, function() { });
+resourceArray = resourceClass.query(function() { });
+resourceArray = resourceClass.query(function() { }, function() { });
+resourceArray = resourceClass.query({ key: 'value' }, { key: 'value' });
+resourceArray = resourceClass.query({ key: 'value' }, { key: 'value' }, function() { });
+resourceArray = resourceClass.query({ key: 'value' }, { key: 'value' }, function() { }, function() { });
+resourceArray.push(resource);
+resourceArray.$promise.then(function(data: OData.IResourceArray) { });
+
+resource = resourceClass.remove();
+resource = resourceClass.remove({ key: 'value' });
+resource = resourceClass.remove({ key: 'value' }, function() { });
+resource = resourceClass.remove(function() { });
+resource = resourceClass.remove(function() { }, function() { });
+resource = resourceClass.remove({ key: 'value' }, { key: 'value' });
+resource = resourceClass.remove({ key: 'value' }, { key: 'value' }, function() { });
+resource = resourceClass.remove({ key: 'value' }, { key: 'value' }, function() { }, function() { });
+
+resource = resourceClass.save();
+resource = resourceClass.save({ key: 'value' });
+resource = resourceClass.save({ key: 'value' }, function() { });
+resource = resourceClass.save(function() { });
+resource = resourceClass.save(function() { }, function() { });
+resource = resourceClass.save({ key: 'value' }, { key: 'value' });
+resource = resourceClass.save({ key: 'value' }, { key: 'value' }, function() { });
+resource = resourceClass.save({ key: 'value' }, { key: 'value' }, function() { }, function() { });
+
+///////////////////////////////////////
+// IResource
+///////////////////////////////////////
+
+var promise: angular.IPromise;
+var arrayPromise: angular.IPromise;
+
+promise = resource.$delete();
+promise = resource.$delete({ key: 'value' });
+promise = resource.$delete({ key: 'value' }, function() { });
+promise = resource.$delete(function() { });
+promise = resource.$delete(function() { }, function() { });
+promise = resource.$delete({ key: 'value' }, function() { }, function() { });
+promise.then(function(data: IMyResource) { });
+
+promise = resource.$get();
+promise = resource.$get({ key: 'value' });
+promise = resource.$get({ key: 'value' }, function() { });
+promise = resource.$get(function() { });
+promise = resource.$get(function() { }, function() { });
+promise = resource.$get({ key: 'value' }, function() { }, function() { });
+
+arrayPromise = resourceArray[0].$query();
+arrayPromise = resourceArray[0].$query({ key: 'value' });
+arrayPromise = resourceArray[0].$query({ key: 'value' }, function() { });
+arrayPromise = resourceArray[0].$query(function() { });
+arrayPromise = resourceArray[0].$query(function() { }, function() { });
+arrayPromise = resourceArray[0].$query({ key: 'value' }, function() { }, function() { });
+arrayPromise.then(function(data: OData.IResourceArray) { });
+
+promise = resource.$remove();
+promise = resource.$remove({ key: 'value' });
+promise = resource.$remove({ key: 'value' }, function() { });
+promise = resource.$remove(function() { });
+promise = resource.$remove(function() { }, function() { });
+promise = resource.$remove({ key: 'value' }, function() { }, function() { });
+
+promise = resource.$save();
+promise = resource.$save({ key: 'value' });
+promise = resource.$save({ key: 'value' }, function() { });
+promise = resource.$save(function() { });
+promise = resource.$save(function() { }, function() { });
+promise = resource.$save({ key: 'value' }, function() { }, function() { });
+
+///////////////////////////////////////
+// IResourceService
+///////////////////////////////////////
+var resourceService: OData.IResourceService;
+resourceClass = resourceService('test');
+resourceClass = resourceService('test');
+resourceClass = resourceService('test');
+
+///////////////////////////////////////
+// IModule
+///////////////////////////////////////
+var mod: ng.IModule;
+var resourceServiceFactoryFunction: OData.IResourceServiceFactoryFunction;
+var resourceService: OData.IResourceService;
+
+resourceClass = resourceServiceFactoryFunction(resourceService);
+
+resourceServiceFactoryFunction = function(resourceService: OData.IResourceService) { return resourceClass; };
+mod = mod.factory('factory name', resourceServiceFactoryFunction);
+
+///////////////////////////////////////
+// IResource
+///////////////////////////////////////
+
+
+///////////////////////////////////////
+// IResourceServiceProvider
+///////////////////////////////////////
+var resourceServiceProvider: OData.IResourceServiceProvider;
+resourceServiceProvider.defaults.stripTrailingSlashes = false;
+
+
+
+///////////////////////////////////////
+// OData
+///////////////////////////////////////
+
+interface User extends OData.IResource {
+ name: string;
+}
+
+var resourceService: OData.IResourceService;
+var odataResourceClass = resourceService("my/url", {}, {}, { odata: { method: 'POST' } });
+
+var Value: OData.ValueFactory;
+var Property: OData.PropertyFactory;
+var Predicate: OData.PredicateFactory;
+
+var users = odataResourceClass.odata().query();
+
+users[0].name;
+users[0].$save;
+
+var user = odataResourceClass.odata()
+ .filter(new Value("1", OData.ValueTypes.Int32), new Property("abc"))
+ .filter("Name", "John")
+ .filter("Age", ">", 20)
+ .skip(10)
+ .take(20)
+ .orderBy("Name", "desc")
+ .single();
+user.$save();
+
+var predicate1 = new Predicate("a", "b");
+var predicate2 = new Predicate("c", "d");
+var predicate3 = new Predicate("Age", '>', 10);
+
+var combination1 = Predicate.or([predicate1, predicate2]);
+var combination2 = Predicate.and([combination1, predicate2]);
+
+var predicate = new Predicate("FirstName", "John")
+ .or(new Predicate("LastName", '!=', "Doe"))
+ .and(new Predicate("Age", '>', 10));
\ No newline at end of file
diff --git a/angular-odata-resources/angular-odata-resources.d.ts b/angular-odata-resources/angular-odata-resources.d.ts
new file mode 100644
index 0000000000..8023290935
--- /dev/null
+++ b/angular-odata-resources/angular-odata-resources.d.ts
@@ -0,0 +1,304 @@
+// Type definitions for OData Angular Resources
+// Project: https://github.com/devnixs/ODataAngularResources
+// Definitions by: Raphael ATALLAH
+// Definitions: https://github.com/borisyankov/DefinitelyTyped
+
+///
+
+declare module OData {
+
+ /**
+ * Currently supported options for the $resource factory options argument.
+ */
+ interface IResourceOptions {
+ /**
+ * If true then the trailing slashes from any calculated URL will be stripped (defaults to true)
+ */
+ stripTrailingSlashes?: boolean;
+ odata?: {
+ url?: string;
+ method?: string;
+ };
+ }
+
+
+ ///////////////////////////////////////////////////////////////////////////
+ // ResourceService
+ // see http://docs.angularjs.org/api/ngResource.$resource
+ // Most part of the following definitions were achieved by analyzing the
+ // actual implementation, since the documentation doesn't seem to cover
+ // that deeply.
+ ///////////////////////////////////////////////////////////////////////////
+ interface IResourceService {
+ (url: string, paramDefaults?: any,
+ /** example: {update: { method: 'PUT' }, delete: deleteDescriptor }
+ where deleteDescriptor : IActionDescriptor */
+ actions?: any, options?: IResourceOptions): IResourceClass>;
+ (url: string, paramDefaults?: any,
+ /** example: {update: { method: 'PUT' }, delete: deleteDescriptor }
+ where deleteDescriptor : IActionDescriptor */
+ actions?: any, options?: IResourceOptions): U;
+ (url: string, paramDefaults?: any,
+ /** example: {update: { method: 'PUT' }, delete: deleteDescriptor }
+ where deleteDescriptor : IActionDescriptor */
+ actions?: any, options?: IResourceOptions): IResourceClass;
+ }
+
+ // Just a reference to facilitate describing new actions
+ interface IActionDescriptor {
+ url?: string;
+ method: string;
+ isArray?: boolean;
+ params?: any;
+ headers?: any;
+ }
+
+ // Baseclass for everyresource with default actions.
+ // If you define your new actions for the resource, you will need
+ // to extend this interface and typecast the ResourceClass to it.
+ //
+ // In case of passing the first argument as anything but a function,
+ // it's gonna be considered data if the action method is POST, PUT or
+ // PATCH (in other words, methods with body). Otherwise, it's going
+ // to be considered as parameters to the request.
+ // https://github.com/angular/angular.js/blob/v1.2.0/src/ngResource/resource.js#L461-L465
+ //
+ // Only those methods with an HTTP body do have 'data' as first parameter:
+ // https://github.com/angular/angular.js/blob/v1.2.0/src/ngResource/resource.js#L463
+ // More specifically, those methods are POST, PUT and PATCH:
+ // https://github.com/angular/angular.js/blob/v1.2.0/src/ngResource/resource.js#L432
+ //
+ // Also, static calls always return the IResource (or IResourceArray) retrieved
+ // https://github.com/angular/angular.js/blob/v1.2.0/src/ngResource/resource.js#L538-L549
+ interface IResourceClass {
+ new(dataOrParams? : any) : IResource;
+ get(): IResource;
+ get(params: Object): IResource;
+ get(success: Function, error?: Function): IResource;
+ get(params: Object, success: Function, error?: Function): IResource;
+ get(params: Object, data: Object, success?: Function, error?: Function): IResource;
+
+ query(): IResourceArray;
+ query(params: Object): IResourceArray;
+ query(success: Function, error?: Function): IResourceArray;
+ query(params: Object, success: Function, error?: Function): IResourceArray;
+ query(params: Object, data: Object, success?: Function, error?: Function): IResourceArray;
+
+ save(): IResource;
+ save(data: Object): IResource;
+ save(success: Function, error?: Function): IResource;
+ save(data: Object, success: Function, error?: Function): IResource;
+ save(params: Object, data: Object, success?: Function, error?: Function): IResource;
+
+ remove(): IResource;
+ remove(params: Object): IResource;
+ remove(success: Function, error?: Function): IResource;
+ remove(params: Object, success: Function, error?: Function): IResource;
+ remove(params: Object, data: Object, success?: Function, error?: Function): IResource;
+
+ delete(): IResource;
+ delete(params: Object): IResource;
+ delete(success: Function, error?: Function): IResource;
+ delete(params: Object, success: Function, error?: Function): IResource;
+ delete(params: Object, data: Object, success?: Function, error?: Function): IResource;
+
+ odata(): OData.Provider;
+ }
+
+ // Instance calls always return the the promise of the request which retrieved the object
+ // https://github.com/angular/angular.js/blob/v1.2.0/src/ngResource/resource.js#L538-L546
+ interface IResource {
+ $get(): angular.IPromise;
+ $get(params?: Object, success?: Function, error?: Function): angular.IPromise;
+ $get(success: Function, error?: Function): angular.IPromise;
+
+ $query(): angular.IPromise>;
+ $query(params?: Object, success?: Function, error?: Function): angular.IPromise>;
+ $query(success: Function, error?: Function): angular.IPromise>;
+
+ $save(): angular.IPromise;
+ $save(params?: Object, success?: Function, error?: Function): angular.IPromise;
+ $save(success: Function, error?: Function): angular.IPromise;
+
+ $remove(): angular.IPromise;
+ $remove(params?: Object, success?: Function, error?: Function): angular.IPromise;
+ $remove(success: Function, error?: Function): angular.IPromise;
+
+ $delete(): angular.IPromise;
+ $delete(params?: Object, success?: Function, error?: Function): angular.IPromise;
+ $delete(success: Function, error?: Function): angular.IPromise;
+
+ /** the promise of the original server interaction that created this instance. **/
+ $promise: angular.IPromise;
+ $resolved: boolean;
+ }
+
+ /**
+ * Really just a regular Array object with $promise and $resolve attached to it
+ */
+ interface IResourceArray extends Array {
+ /** the promise of the original server interaction that created this collection. **/
+ $promise: angular.IPromise>;
+ $resolved: boolean;
+ }
+
+ /** when creating a resource factory via IModule.factory */
+ interface IResourceServiceFactoryFunction {
+ ($resource: OData.IResourceService): IResourceClass;
+ >($resource: OData.IResourceService): U;
+ }
+
+ // IResourceServiceProvider used to configure global settings
+ interface IResourceServiceProvider extends angular.IServiceProvider {
+
+ defaults: IResourceOptions;
+ }
+
+
+ interface IExecutable {
+ execute(noParenthesis?: any): string;
+ }
+ class Global {
+ static $inject: string[];
+ constructor(ODataBinaryOperation: any, ODataProvider: any, ODataValue: any, ODataProperty: any, ODataMethodCall: any, ODataPredicate: any, ODataOrderByStatement: any);
+ Provider: Provider;
+ BinaryOperation: typeof BinaryOperation;
+ Value: typeof Value;
+ Property: typeof Property;
+ Func: typeof MethodCall;
+ Predicate: typeof Predicate;
+ OrderBy: typeof OrderByStatement;
+ }
+
+ interface BinaryOperationFactory {
+ new (propertyOrPredicate: any, valueOrOperator?: any, value?: any): BinaryOperation;
+ }
+ class BinaryOperation implements IExecutable {
+ private operandA;
+ private operandB;
+ private filterOperator;
+ constructor(propertyOrPredicate: any, valueOrOperator?: any, value?: any);
+ execute(noParenthesis?: any): string;
+ or(propertyOrPredicate: any, operatorOrValue?: any, value?: any): BinaryOperation;
+ and(propertyOrPredicate: any, operatorOrValue?: any, value?: any): BinaryOperation;
+ }
+
+ interface MethodCallFactory {
+ new (methodName: string, ...args: any[]): MethodCall;
+ }
+ class MethodCall implements IExecutable {
+ private methodName;
+ private params;
+ execute(): string;
+ constructor(methodName: string, ...args: any[]);
+ }
+
+ class Operators {
+ operators: {
+ 'eq': string[];
+ 'ne': string[];
+ 'gt': string[];
+ 'ge': string[];
+ 'lt': string[];
+ 'le': string[];
+ 'and': string[];
+ 'or': string[];
+ 'not': string[];
+ 'add': string[];
+ 'sub': string[];
+ 'mul': string[];
+ 'div': string[];
+ 'mod': string[];
+ };
+ private rtrim;
+ private trim(value);
+ convert(from: string): any;
+ }
+
+ interface OrderByStatementFactory {
+ new (propertyName: string, sortOrder?: string): OrderByStatement;
+ }
+ class OrderByStatement implements IExecutable {
+ private propertyName;
+ private direction;
+ execute(): string;
+ constructor(propertyName: string, sortOrder?: string);
+ }
+
+ interface PredicateFactory {
+ new (propertyOrValueOrPredicate: any, valueOrOperator?: any, value?: any): Predicate;
+ or(orStatements: any[]): IExecutable;
+ create(propertyOrPredicate: any, operatorOrValue?: any, value?: any): IExecutable;
+ and(andStatements: any): IExecutable;
+ }
+ class Predicate extends BinaryOperation {
+ constructor(propertyOrValueOrPredicate: any, valueOrOperator?: any, value?: any);
+ static or(orStatements: any[]): IExecutable;
+ static create(propertyOrPredicate: any, operatorOrValue?: any, value?: any): IExecutable;
+ static and(andStatements: any): IExecutable;
+ }
+
+ interface PropertyFactory {
+ new (value: string): Property;
+ }
+ class Property implements IExecutable {
+ private value;
+ constructor(value: string);
+ execute(): string;
+ }
+
+ interface ProviderFactory {
+ new (callback: ProviderCallback): Provider;
+ }
+ interface ProviderCallback {
+ (queryString: string, success: () => any, error: () => any): T[];
+ (queryString: string, success: () => any, error: () => any, isSingleElement?: boolean, forceSingleElement?: boolean): T;
+ }
+ class Provider {
+ private callback;
+ private filters;
+ private sortOrders;
+ private takeAmount;
+ private skipAmount;
+ private expandables;
+ constructor(callback: ProviderCallback);
+ filter(operand1: any, operand2?: any, operand3?: any): Provider;
+ orderBy(arg1: any, arg2?: any): Provider;
+ take(amount: number): Provider;
+ skip(amount: number): Provider;
+ private execute();
+ query(success?: any, error?: any): T[];
+ single(success?: any, error?: any): T;
+ get(data: any, success?: any, error?: any): T;
+ expand(params: any, otherParam1?: any, otherParam2?: any, otherParam3?: any, otherParam4?: any, otherParam5?: any, otherParam6?: any, otherParam7?: any): Provider;
+ }
+
+ interface ValueFactory {
+ new (value: any, type?: string): Value;
+ }
+ class ValueTypes {
+ static Boolean: string;
+ static Byte: string;
+ static DateTime: string;
+ static Decimal: string;
+ static Double: string;
+ static Single: string;
+ static Guid: string;
+ static Int32: string;
+ static String: string;
+ }
+ class Value {
+ private value;
+ private type;
+ private illegalChars;
+ private escapeIllegalChars(haystack);
+ private generateDate(date);
+ executeWithUndefinedType(): any;
+ executeWithType(): any;
+ execute(): string;
+ constructor(value: any, type?: string);
+ }
+
+
+
+}