Skip to content

Add support for callCached on GET methods. #12

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Jan 10, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ angular.module('framework').service('AngularEndpointsService', Framework.Endpoin

"GenerateEndpoints": "boolean",
"EndpointsOutputDirectory": "string",
"EndpointsSupportCaching": "boolean",
"EndpointsFileName": "string",
"EndpointsNamespace": "string",

Expand Down
7 changes: 7 additions & 0 deletions src/WebApiTestApplication/Scripts/Endpoints/Endpoints.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ namespace Endpoints {

export interface IGetWithCall extends IGet, IEndpoint {
call<TView>(): ng.IPromise<TView>;
callCached<TView>(): ng.IPromise<TView>;
}

export class Get implements IGet, IEndpoint {
Expand All @@ -74,6 +75,7 @@ namespace Endpoints {

export interface IGet1WithCall extends IGet1, IEndpoint {
call<TView>(): ng.IPromise<TView>;
callCached<TView>(): ng.IPromise<TView>;
}

export class Get1 implements IGet1, IEndpoint {
Expand Down Expand Up @@ -110,6 +112,7 @@ namespace Endpoints {

export interface IGetSomethingWithCall extends IGetSomething, IEndpoint {
call<TView>(): ng.IPromise<TView>;
callCached<TView>(): ng.IPromise<TView>;
}

export class GetSomething implements IGetSomething, IEndpoint {
Expand Down Expand Up @@ -148,6 +151,7 @@ namespace Endpoints {

export interface IGetSomethingElseWithCall extends IGetSomethingElse, IEndpoint {
call<TView>(): ng.IPromise<TView>;
callCached<TView>(): ng.IPromise<TView>;
}

export class GetSomethingElse implements IGetSomethingElse, IEndpoint {
Expand Down Expand Up @@ -315,6 +319,7 @@ namespace Endpoints {

export interface IGetAllWithCall extends IGetAll, IEndpoint {
call<TView>(): ng.IPromise<TView>;
callCached<TView>(): ng.IPromise<TView>;
}

export class GetAll implements IGetAll, IEndpoint {
Expand All @@ -336,6 +341,7 @@ namespace Endpoints {

export interface IGetWithCall extends IGet, IEndpoint {
call<TView>(): ng.IPromise<TView>;
callCached<TView>(): ng.IPromise<TView>;
}

export class Get implements IGet, IEndpoint {
Expand Down Expand Up @@ -374,6 +380,7 @@ namespace Endpoints {

export interface IGettyWithCall extends IGetty, IEndpoint {
call<TView>(): ng.IPromise<TView>;
callCached<TView>(): ng.IPromise<TView>;
}

export class Getty implements IGetty, IEndpoint {
Expand Down
62 changes: 54 additions & 8 deletions src/WebApiTestApplication/Scripts/Endpoints/Service.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
namespace Endpoints {
export class AngularEndpointsService {
static $inject = ['$http'];
static $inject = ['$http', '$q'];
static $http: ng.IHttpService;
static $q: ng.IQService;
static endpointCache = {};

constructor($http: ng.IHttpService) {
constructor($http: ng.IHttpService, $q: ng.IQService) {
AngularEndpointsService.$http = $http;
AngularEndpointsService.$q = $q;
}

static call<TView>(endpoint: IEndpoint, data) {
Expand All @@ -17,12 +20,31 @@ namespace Endpoints {
return call.then(response => response.data);
}

static callCached<TView>(endpoint: IEndpoint, data) {
var cacheKey = endpoint.toString();

if (this.endpointCache[cacheKey] == null) {
return this.call<TView>(endpoint, data).then(result => {
this.endpointCache[cacheKey] = result;
return this.endpointCache[cacheKey];
});
}

const deferred = this.$q.defer();
deferred.resolve(this.endpointCache[cacheKey]);
return deferred.promise;
}

public Test: Endpoints.Test.ITestService = {
Get: (args: Endpoints.Test.IGet): Endpoints.Test.IGetWithCall => {
var endpoint = new Endpoints.Test.Get(args);
return _.extendOwn(endpoint, {
call<TView>() {
return AngularEndpointsService.call<TView>(this, null);
},

callCached<TView>() {
return AngularEndpointsService.callCached<TView>(this, null);
}
});
},
Expand All @@ -32,6 +54,10 @@ namespace Endpoints {
return _.extendOwn(endpoint, {
call<TView>() {
return AngularEndpointsService.call<TView>(this, null);
},

callCached<TView>() {
return AngularEndpointsService.callCached<TView>(this, null);
}
});
},
Expand All @@ -41,6 +67,10 @@ namespace Endpoints {
return _.extendOwn(endpoint, {
call<TView>() {
return AngularEndpointsService.call<TView>(this, null);
},

callCached<TView>() {
return AngularEndpointsService.callCached<TView>(this, null);
}
});
},
Expand All @@ -50,6 +80,10 @@ namespace Endpoints {
return _.extendOwn(endpoint, {
call<TView>() {
return AngularEndpointsService.call<TView>(this, null);
},

callCached<TView>() {
return AngularEndpointsService.callCached<TView>(this, null);
}
});
},
Expand All @@ -59,7 +93,7 @@ namespace Endpoints {
return _.extendOwn(endpoint, {
call<TView>(value: Interfaces.IDummyClass) {
return AngularEndpointsService.call<TView>(this, value != null ? value : null);
}
},
});
},

Expand All @@ -68,7 +102,7 @@ namespace Endpoints {
return _.extendOwn(endpoint, {
call<TView>(value: Interfaces.IDerivedClassWithShadowedProperty) {
return AngularEndpointsService.call<TView>(this, value != null ? value : null);
}
},
});
},

Expand All @@ -77,7 +111,7 @@ namespace Endpoints {
return _.extendOwn(endpoint, {
call<TView>(value: Interfaces.IDerivedClassWithAnotherShadowedProperty) {
return AngularEndpointsService.call<TView>(this, value != null ? value : null);
}
},
});
},

Expand All @@ -86,7 +120,7 @@ namespace Endpoints {
return _.extendOwn(endpoint, {
call<TView>(value: string) {
return AngularEndpointsService.call<TView>(this, value != null ? `"${value}"` : null);
}
},
});
},

Expand All @@ -95,7 +129,7 @@ namespace Endpoints {
return _.extendOwn(endpoint, {
call<TView>() {
return AngularEndpointsService.call<TView>(this, null);
}
},
});
}
}
Expand All @@ -106,6 +140,10 @@ namespace Endpoints {
return _.extendOwn(endpoint, {
call<TView>() {
return AngularEndpointsService.call<TView>(this, null);
},

callCached<TView>() {
return AngularEndpointsService.callCached<TView>(this, null);
}
});
},
Expand All @@ -115,6 +153,10 @@ namespace Endpoints {
return _.extendOwn(endpoint, {
call<TView>() {
return AngularEndpointsService.call<TView>(this, null);
},

callCached<TView>() {
return AngularEndpointsService.callCached<TView>(this, null);
}
});
},
Expand All @@ -124,6 +166,10 @@ namespace Endpoints {
return _.extendOwn(endpoint, {
call<TView>() {
return AngularEndpointsService.call<TView>(this, null);
},

callCached<TView>() {
return AngularEndpointsService.callCached<TView>(this, null);
}
});
},
Expand All @@ -133,7 +179,7 @@ namespace Endpoints {
return _.extendOwn(endpoint, {
call<TView>(value: Interfaces.IMegaClass) {
return AngularEndpointsService.call<TView>(this, value != null ? value : null);
}
},
});
}
}
Expand Down
1 change: 1 addition & 0 deletions src/WebApiTestApplication/Watts.config.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
"WebApiModuleFileName": "./bin/WebApiTestApplication.dll",

"EndpointsOutputDirectory": "./Scripts/Endpoints",
"EndpointsSupportCaching": true,
"EndpointsFileName": "Endpoints.ts",
"EndpointsNamespace": "Endpoints",

Expand Down
3 changes: 3 additions & 0 deletions src/WebApiToTypeScript/Config/Config.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ public class Config
public string EndpointsOutputDirectory { get; set; }
= "Endpoints";

public bool EndpointsSupportCaching { get; set; }
= false;

public string EndpointsFileName { get; set; }
= "Endpoints.ts";

Expand Down
47 changes: 37 additions & 10 deletions src/WebApiToTypeScript/Endpoints/AngularEndpointsService.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.Linq;
using System;
using System.Linq;
using WebApiToTypeScript.Block;
using WebApiToTypeScript.WebApi;

Expand All @@ -8,22 +9,43 @@ public class AngularEndpointsService : ServiceAware
{
public TypeScriptBlock CreateServiceBlock()
{
return new TypeScriptBlock($"{Config.NamespaceOrModuleName} {Config.ServiceNamespace}")
var serviceBlock = new TypeScriptBlock($"{Config.NamespaceOrModuleName} {Config.ServiceNamespace}")
.AddAndUseBlock($"export class {Config.ServiceName}")
.AddStatement("static $inject = ['$http'];")
.AddStatement("static $inject = ['$http', '$q'];")
.AddStatement("static $http: ng.IHttpService;")
.AddAndUseBlock("constructor($http: ng.IHttpService)")
.AddStatement("static $q: ng.IQService;")
.AddStatement("static endpointCache = {};")
.AddAndUseBlock("constructor($http: ng.IHttpService, $q: ng.IQService)")
.AddStatement($"{Config.ServiceName}.$http = $http;")
.AddStatement($"{Config.ServiceName}.$q = $q;")
.Parent
.AddAndUseBlock("static call<TView>(endpoint: IEndpoint, data)")
.AddAndUseBlock($"var call = {Config.ServiceName}.$http<TView>(", isFunctionBlock: true, terminationString: ";")
.AddStatement("method: endpoint._verb,")
.AddStatement("url: endpoint.toString(),")
.AddStatement("data: data")
.Parent
.AddStatement("return call.then(response => response.data);")
.Parent
.Parent;
.AddStatement("return call.then(response => response.data);");

if (Config.EndpointsSupportCaching)
serviceBlock
.Parent
.AddAndUseBlock("static callCached<TView>(endpoint: IEndpoint, data)")
.AddStatement("var cacheKey = endpoint.toString();")
.AddAndUseBlock("if (this.endpointCache[cacheKey] == null)")
.AddAndUseBlock("return this.call<TView>(endpoint, data).then(result =>", isFunctionBlock: true,
terminationString: ";")
.AddStatement("this.endpointCache[cacheKey] = result;")
.AddStatement("return this.endpointCache[cacheKey];")
.Parent
.Parent
.AddStatement("const deferred = this.$q.defer();")
.AddStatement("deferred.resolve(this.endpointCache[cacheKey]);")
.AddStatement("return deferred.promise;");

return serviceBlock
.Parent
.Parent;
}

public void WriteServiceObjectToBlock(TypeScriptBlock serviceBlock, WebApiController webApiController)
Expand Down Expand Up @@ -72,7 +94,7 @@ public void WriteServiceObjectToBlock(TypeScriptBlock serviceBlock, WebApiContro
var interfaceWithCallFullName = $"{Config.EndpointsNamespace}.{webApiController.Name}.I{actionName}WithCall";
var endpointFullName = $"{Config.EndpointsNamespace}.{webApiController.Name}.{actionName}";

controllerBlock
var endpointExtendBlock = controllerBlock
.AddAndUseBlock
(
outer: $"{actionName}: (args{optionalString}: {interfaceFullName}): {interfaceWithCallFullName} =>",
Expand All @@ -81,8 +103,13 @@ public void WriteServiceObjectToBlock(TypeScriptBlock serviceBlock, WebApiContro
)
.AddStatement($"var endpoint = new {endpointFullName}(args);")
.AddAndUseBlock("return _.extendOwn(endpoint,", isFunctionBlock: true, terminationString: ";")
.AddAndUseBlock($"call<TView>({callArgumentDefinition})")
.AddStatement($"return {Config.ServiceName}.call<TView>(this, {callArgumentValue});");
.AddAndUseBlock($"call<TView>({callArgumentDefinition})", isFunctionBlock: false, terminationString: ",")
.AddStatement($"return {Config.ServiceName}.call<TView>(this, {callArgumentValue});")
.Parent;

if (Config.EndpointsSupportCaching && verb == WebApiHttpVerb.Get)
endpointExtendBlock.AddAndUseBlock($"callCached<TView>({callArgumentDefinition})")
.AddStatement($"return {Config.ServiceName}.callCached<TView>(this, {callArgumentValue});");
}
}
}
Expand Down
8 changes: 6 additions & 2 deletions src/WebApiToTypeScript/Endpoints/EndpointsService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ public void WriteEndpointClassToBlock(TypeScriptBlock endpointBlock, WebApiContr
var interfaceWithCallBlock = controllerBlock
.AddAndUseBlock($"export interface I{actionName}WithCall extends I{actionName}, {IEndpoint}");

WriteInterfaceWithCallToBlock(interfaceWithCallBlock, action);
WriteInterfaceWithCallToBlock(interfaceWithCallBlock, action, verb);

serviceBlock
.AddStatement($"{actionName}: (args?: I{actionName}) => I{actionName}WithCall");
Expand Down Expand Up @@ -107,7 +107,7 @@ private void WriteInterfaceToBlock(TypeScriptBlock interfaceBlock, WebApiAction
}
}

private void WriteInterfaceWithCallToBlock(TypeScriptBlock interfaceWithCallBlock, WebApiAction action)
private void WriteInterfaceWithCallToBlock(TypeScriptBlock interfaceWithCallBlock, WebApiAction action, WebApiHttpVerb verb)
{
var callArguments = action.BodyParameters;

Expand All @@ -119,6 +119,10 @@ private void WriteInterfaceWithCallToBlock(TypeScriptBlock interfaceWithCallBloc

interfaceWithCallBlock
.AddStatement($"call<TView>({callArgumentsList}): ng.IPromise<TView>;");

if (Config.EndpointsSupportCaching && verb == WebApiHttpVerb.Get)
interfaceWithCallBlock
.AddStatement($"callCached<TView>({callArgumentsList}): ng.IPromise<TView>;");
}

private void WriteToStringToBlock(TypeScriptBlock classBlock, WebApiAction action)
Expand Down