Skip to content

Commit 576e676

Browse files
authored
Merge pull request #12 from greymind/issue-9-add-call-cached-support
Add support for callCached on GET methods.
2 parents 8725010 + 63c4e40 commit 576e676

File tree

7 files changed

+109
-20
lines changed

7 files changed

+109
-20
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ angular.module('framework').service('AngularEndpointsService', Framework.Endpoin
6464
6565
"GenerateEndpoints": "boolean",
6666
"EndpointsOutputDirectory": "string",
67+
"EndpointsSupportCaching": "boolean",
6768
"EndpointsFileName": "string",
6869
"EndpointsNamespace": "string",
6970

src/WebApiTestApplication/Scripts/Endpoints/Endpoints.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ namespace Endpoints {
5252

5353
export interface IGetWithCall extends IGet, IEndpoint {
5454
call<TView>(): ng.IPromise<TView>;
55+
callCached<TView>(): ng.IPromise<TView>;
5556
}
5657

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

7576
export interface IGet1WithCall extends IGet1, IEndpoint {
7677
call<TView>(): ng.IPromise<TView>;
78+
callCached<TView>(): ng.IPromise<TView>;
7779
}
7880

7981
export class Get1 implements IGet1, IEndpoint {
@@ -110,6 +112,7 @@ namespace Endpoints {
110112

111113
export interface IGetSomethingWithCall extends IGetSomething, IEndpoint {
112114
call<TView>(): ng.IPromise<TView>;
115+
callCached<TView>(): ng.IPromise<TView>;
113116
}
114117

115118
export class GetSomething implements IGetSomething, IEndpoint {
@@ -148,6 +151,7 @@ namespace Endpoints {
148151

149152
export interface IGetSomethingElseWithCall extends IGetSomethingElse, IEndpoint {
150153
call<TView>(): ng.IPromise<TView>;
154+
callCached<TView>(): ng.IPromise<TView>;
151155
}
152156

153157
export class GetSomethingElse implements IGetSomethingElse, IEndpoint {
@@ -315,6 +319,7 @@ namespace Endpoints {
315319

316320
export interface IGetAllWithCall extends IGetAll, IEndpoint {
317321
call<TView>(): ng.IPromise<TView>;
322+
callCached<TView>(): ng.IPromise<TView>;
318323
}
319324

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

337342
export interface IGetWithCall extends IGet, IEndpoint {
338343
call<TView>(): ng.IPromise<TView>;
344+
callCached<TView>(): ng.IPromise<TView>;
339345
}
340346

341347
export class Get implements IGet, IEndpoint {
@@ -374,6 +380,7 @@ namespace Endpoints {
374380

375381
export interface IGettyWithCall extends IGetty, IEndpoint {
376382
call<TView>(): ng.IPromise<TView>;
383+
callCached<TView>(): ng.IPromise<TView>;
377384
}
378385

379386
export class Getty implements IGetty, IEndpoint {

src/WebApiTestApplication/Scripts/Endpoints/Service.ts

Lines changed: 54 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
11
namespace Endpoints {
22
export class AngularEndpointsService {
3-
static $inject = ['$http'];
3+
static $inject = ['$http', '$q'];
44
static $http: ng.IHttpService;
5+
static $q: ng.IQService;
6+
static endpointCache = {};
57

6-
constructor($http: ng.IHttpService) {
8+
constructor($http: ng.IHttpService, $q: ng.IQService) {
79
AngularEndpointsService.$http = $http;
10+
AngularEndpointsService.$q = $q;
811
}
912

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

23+
static callCached<TView>(endpoint: IEndpoint, data) {
24+
var cacheKey = endpoint.toString();
25+
26+
if (this.endpointCache[cacheKey] == null) {
27+
return this.call<TView>(endpoint, data).then(result => {
28+
this.endpointCache[cacheKey] = result;
29+
return this.endpointCache[cacheKey];
30+
});
31+
}
32+
33+
const deferred = this.$q.defer();
34+
deferred.resolve(this.endpointCache[cacheKey]);
35+
return deferred.promise;
36+
}
37+
2038
public Test: Endpoints.Test.ITestService = {
2139
Get: (args: Endpoints.Test.IGet): Endpoints.Test.IGetWithCall => {
2240
var endpoint = new Endpoints.Test.Get(args);
2341
return _.extendOwn(endpoint, {
2442
call<TView>() {
2543
return AngularEndpointsService.call<TView>(this, null);
44+
},
45+
46+
callCached<TView>() {
47+
return AngularEndpointsService.callCached<TView>(this, null);
2648
}
2749
});
2850
},
@@ -32,6 +54,10 @@ namespace Endpoints {
3254
return _.extendOwn(endpoint, {
3355
call<TView>() {
3456
return AngularEndpointsService.call<TView>(this, null);
57+
},
58+
59+
callCached<TView>() {
60+
return AngularEndpointsService.callCached<TView>(this, null);
3561
}
3662
});
3763
},
@@ -41,6 +67,10 @@ namespace Endpoints {
4167
return _.extendOwn(endpoint, {
4268
call<TView>() {
4369
return AngularEndpointsService.call<TView>(this, null);
70+
},
71+
72+
callCached<TView>() {
73+
return AngularEndpointsService.callCached<TView>(this, null);
4474
}
4575
});
4676
},
@@ -50,6 +80,10 @@ namespace Endpoints {
5080
return _.extendOwn(endpoint, {
5181
call<TView>() {
5282
return AngularEndpointsService.call<TView>(this, null);
83+
},
84+
85+
callCached<TView>() {
86+
return AngularEndpointsService.callCached<TView>(this, null);
5387
}
5488
});
5589
},
@@ -59,7 +93,7 @@ namespace Endpoints {
5993
return _.extendOwn(endpoint, {
6094
call<TView>(value: Interfaces.IDummyClass) {
6195
return AngularEndpointsService.call<TView>(this, value != null ? value : null);
62-
}
96+
},
6397
});
6498
},
6599

@@ -68,7 +102,7 @@ namespace Endpoints {
68102
return _.extendOwn(endpoint, {
69103
call<TView>(value: Interfaces.IDerivedClassWithShadowedProperty) {
70104
return AngularEndpointsService.call<TView>(this, value != null ? value : null);
71-
}
105+
},
72106
});
73107
},
74108

@@ -77,7 +111,7 @@ namespace Endpoints {
77111
return _.extendOwn(endpoint, {
78112
call<TView>(value: Interfaces.IDerivedClassWithAnotherShadowedProperty) {
79113
return AngularEndpointsService.call<TView>(this, value != null ? value : null);
80-
}
114+
},
81115
});
82116
},
83117

@@ -86,7 +120,7 @@ namespace Endpoints {
86120
return _.extendOwn(endpoint, {
87121
call<TView>(value: string) {
88122
return AngularEndpointsService.call<TView>(this, value != null ? `"${value}"` : null);
89-
}
123+
},
90124
});
91125
},
92126

@@ -95,7 +129,7 @@ namespace Endpoints {
95129
return _.extendOwn(endpoint, {
96130
call<TView>() {
97131
return AngularEndpointsService.call<TView>(this, null);
98-
}
132+
},
99133
});
100134
}
101135
}
@@ -106,6 +140,10 @@ namespace Endpoints {
106140
return _.extendOwn(endpoint, {
107141
call<TView>() {
108142
return AngularEndpointsService.call<TView>(this, null);
143+
},
144+
145+
callCached<TView>() {
146+
return AngularEndpointsService.callCached<TView>(this, null);
109147
}
110148
});
111149
},
@@ -115,6 +153,10 @@ namespace Endpoints {
115153
return _.extendOwn(endpoint, {
116154
call<TView>() {
117155
return AngularEndpointsService.call<TView>(this, null);
156+
},
157+
158+
callCached<TView>() {
159+
return AngularEndpointsService.callCached<TView>(this, null);
118160
}
119161
});
120162
},
@@ -124,6 +166,10 @@ namespace Endpoints {
124166
return _.extendOwn(endpoint, {
125167
call<TView>() {
126168
return AngularEndpointsService.call<TView>(this, null);
169+
},
170+
171+
callCached<TView>() {
172+
return AngularEndpointsService.callCached<TView>(this, null);
127173
}
128174
});
129175
},
@@ -133,7 +179,7 @@ namespace Endpoints {
133179
return _.extendOwn(endpoint, {
134180
call<TView>(value: Interfaces.IMegaClass) {
135181
return AngularEndpointsService.call<TView>(this, value != null ? value : null);
136-
}
182+
},
137183
});
138184
}
139185
}

src/WebApiTestApplication/Watts.config.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
"WebApiModuleFileName": "./bin/WebApiTestApplication.dll",
33

44
"EndpointsOutputDirectory": "./Scripts/Endpoints",
5+
"EndpointsSupportCaching": true,
56
"EndpointsFileName": "Endpoints.ts",
67
"EndpointsNamespace": "Endpoints",
78

src/WebApiToTypeScript/Config/Config.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@ public class Config
1212
public string EndpointsOutputDirectory { get; set; }
1313
= "Endpoints";
1414

15+
public bool EndpointsSupportCaching { get; set; }
16+
= false;
17+
1518
public string EndpointsFileName { get; set; }
1619
= "Endpoints.ts";
1720

src/WebApiToTypeScript/Endpoints/AngularEndpointsService.cs

Lines changed: 37 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
using System.Linq;
1+
using System;
2+
using System.Linq;
23
using WebApiToTypeScript.Block;
34
using WebApiToTypeScript.WebApi;
45

@@ -8,22 +9,43 @@ public class AngularEndpointsService : ServiceAware
89
{
910
public TypeScriptBlock CreateServiceBlock()
1011
{
11-
return new TypeScriptBlock($"{Config.NamespaceOrModuleName} {Config.ServiceNamespace}")
12+
var serviceBlock = new TypeScriptBlock($"{Config.NamespaceOrModuleName} {Config.ServiceNamespace}")
1213
.AddAndUseBlock($"export class {Config.ServiceName}")
13-
.AddStatement("static $inject = ['$http'];")
14+
.AddStatement("static $inject = ['$http', '$q'];")
1415
.AddStatement("static $http: ng.IHttpService;")
15-
.AddAndUseBlock("constructor($http: ng.IHttpService)")
16+
.AddStatement("static $q: ng.IQService;")
17+
.AddStatement("static endpointCache = {};")
18+
.AddAndUseBlock("constructor($http: ng.IHttpService, $q: ng.IQService)")
1619
.AddStatement($"{Config.ServiceName}.$http = $http;")
20+
.AddStatement($"{Config.ServiceName}.$q = $q;")
1721
.Parent
1822
.AddAndUseBlock("static call<TView>(endpoint: IEndpoint, data)")
1923
.AddAndUseBlock($"var call = {Config.ServiceName}.$http<TView>(", isFunctionBlock: true, terminationString: ";")
2024
.AddStatement("method: endpoint._verb,")
2125
.AddStatement("url: endpoint.toString(),")
2226
.AddStatement("data: data")
2327
.Parent
24-
.AddStatement("return call.then(response => response.data);")
25-
.Parent
26-
.Parent;
28+
.AddStatement("return call.then(response => response.data);");
29+
30+
if (Config.EndpointsSupportCaching)
31+
serviceBlock
32+
.Parent
33+
.AddAndUseBlock("static callCached<TView>(endpoint: IEndpoint, data)")
34+
.AddStatement("var cacheKey = endpoint.toString();")
35+
.AddAndUseBlock("if (this.endpointCache[cacheKey] == null)")
36+
.AddAndUseBlock("return this.call<TView>(endpoint, data).then(result =>", isFunctionBlock: true,
37+
terminationString: ";")
38+
.AddStatement("this.endpointCache[cacheKey] = result;")
39+
.AddStatement("return this.endpointCache[cacheKey];")
40+
.Parent
41+
.Parent
42+
.AddStatement("const deferred = this.$q.defer();")
43+
.AddStatement("deferred.resolve(this.endpointCache[cacheKey]);")
44+
.AddStatement("return deferred.promise;");
45+
46+
return serviceBlock
47+
.Parent
48+
.Parent;
2749
}
2850

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

75-
controllerBlock
97+
var endpointExtendBlock = controllerBlock
7698
.AddAndUseBlock
7799
(
78100
outer: $"{actionName}: (args{optionalString}: {interfaceFullName}): {interfaceWithCallFullName} =>",
@@ -81,8 +103,13 @@ public void WriteServiceObjectToBlock(TypeScriptBlock serviceBlock, WebApiContro
81103
)
82104
.AddStatement($"var endpoint = new {endpointFullName}(args);")
83105
.AddAndUseBlock("return _.extendOwn(endpoint,", isFunctionBlock: true, terminationString: ";")
84-
.AddAndUseBlock($"call<TView>({callArgumentDefinition})")
85-
.AddStatement($"return {Config.ServiceName}.call<TView>(this, {callArgumentValue});");
106+
.AddAndUseBlock($"call<TView>({callArgumentDefinition})", isFunctionBlock: false, terminationString: ",")
107+
.AddStatement($"return {Config.ServiceName}.call<TView>(this, {callArgumentValue});")
108+
.Parent;
109+
110+
if (Config.EndpointsSupportCaching && verb == WebApiHttpVerb.Get)
111+
endpointExtendBlock.AddAndUseBlock($"callCached<TView>({callArgumentDefinition})")
112+
.AddStatement($"return {Config.ServiceName}.callCached<TView>(this, {callArgumentValue});");
86113
}
87114
}
88115
}

src/WebApiToTypeScript/Endpoints/EndpointsService.cs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ public void WriteEndpointClassToBlock(TypeScriptBlock endpointBlock, WebApiContr
7171
var interfaceWithCallBlock = controllerBlock
7272
.AddAndUseBlock($"export interface I{actionName}WithCall extends I{actionName}, {IEndpoint}");
7373

74-
WriteInterfaceWithCallToBlock(interfaceWithCallBlock, action);
74+
WriteInterfaceWithCallToBlock(interfaceWithCallBlock, action, verb);
7575

7676
serviceBlock
7777
.AddStatement($"{actionName}: (args?: I{actionName}) => I{actionName}WithCall");
@@ -107,7 +107,7 @@ private void WriteInterfaceToBlock(TypeScriptBlock interfaceBlock, WebApiAction
107107
}
108108
}
109109

110-
private void WriteInterfaceWithCallToBlock(TypeScriptBlock interfaceWithCallBlock, WebApiAction action)
110+
private void WriteInterfaceWithCallToBlock(TypeScriptBlock interfaceWithCallBlock, WebApiAction action, WebApiHttpVerb verb)
111111
{
112112
var callArguments = action.BodyParameters;
113113

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

120120
interfaceWithCallBlock
121121
.AddStatement($"call<TView>({callArgumentsList}): ng.IPromise<TView>;");
122+
123+
if (Config.EndpointsSupportCaching && verb == WebApiHttpVerb.Get)
124+
interfaceWithCallBlock
125+
.AddStatement($"callCached<TView>({callArgumentsList}): ng.IPromise<TView>;");
122126
}
123127

124128
private void WriteToStringToBlock(TypeScriptBlock classBlock, WebApiAction action)

0 commit comments

Comments
 (0)