Skip to content

Commit 5b887ca

Browse files
committed
Add support for callCached on GET methods.
1 parent 8725010 commit 5b887ca

File tree

8 files changed

+134
-20
lines changed

8 files changed

+134
-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: 56 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,33 @@ namespace Endpoints {
1720
return call.then(response => response.data);
1821
}
1922

23+
static callCached<TView>(endpoint: IEndpoint, data) {
24+
if (this.endpointCache[endpoint._verb] == null) {
25+
this.endpointCache[endpoint._verb] = {};
26+
}
27+
28+
if (this.endpointCache[endpoint._verb][data] == null) {
29+
return this.call(endpoint, data).then(result => {
30+
this.endpointCache[endpoint._verb][data] = result;
31+
return this.endpointCache[endpoint._verb][data];
32+
});
33+
}
34+
35+
const deferred = this.$q.defer();
36+
deferred.resolve(this.endpointCache[endpoint._verb][data]);
37+
return deferred.promise;
38+
}
39+
2040
public Test: Endpoints.Test.ITestService = {
2141
Get: (args: Endpoints.Test.IGet): Endpoints.Test.IGetWithCall => {
2242
var endpoint = new Endpoints.Test.Get(args);
2343
return _.extendOwn(endpoint, {
2444
call<TView>() {
2545
return AngularEndpointsService.call<TView>(this, null);
46+
},
47+
48+
callCached<TView>() {
49+
return AngularEndpointsService.callCached<TView>(this, null);
2650
}
2751
});
2852
},
@@ -32,6 +56,10 @@ namespace Endpoints {
3256
return _.extendOwn(endpoint, {
3357
call<TView>() {
3458
return AngularEndpointsService.call<TView>(this, null);
59+
},
60+
61+
callCached<TView>() {
62+
return AngularEndpointsService.callCached<TView>(this, null);
3563
}
3664
});
3765
},
@@ -41,6 +69,10 @@ namespace Endpoints {
4169
return _.extendOwn(endpoint, {
4270
call<TView>() {
4371
return AngularEndpointsService.call<TView>(this, null);
72+
},
73+
74+
callCached<TView>() {
75+
return AngularEndpointsService.callCached<TView>(this, null);
4476
}
4577
});
4678
},
@@ -50,6 +82,10 @@ namespace Endpoints {
5082
return _.extendOwn(endpoint, {
5183
call<TView>() {
5284
return AngularEndpointsService.call<TView>(this, null);
85+
},
86+
87+
callCached<TView>() {
88+
return AngularEndpointsService.callCached<TView>(this, null);
5389
}
5490
});
5591
},
@@ -59,7 +95,7 @@ namespace Endpoints {
5995
return _.extendOwn(endpoint, {
6096
call<TView>(value: Interfaces.IDummyClass) {
6197
return AngularEndpointsService.call<TView>(this, value != null ? value : null);
62-
}
98+
},
6399
});
64100
},
65101

@@ -68,7 +104,7 @@ namespace Endpoints {
68104
return _.extendOwn(endpoint, {
69105
call<TView>(value: Interfaces.IDerivedClassWithShadowedProperty) {
70106
return AngularEndpointsService.call<TView>(this, value != null ? value : null);
71-
}
107+
},
72108
});
73109
},
74110

@@ -77,7 +113,7 @@ namespace Endpoints {
77113
return _.extendOwn(endpoint, {
78114
call<TView>(value: Interfaces.IDerivedClassWithAnotherShadowedProperty) {
79115
return AngularEndpointsService.call<TView>(this, value != null ? value : null);
80-
}
116+
},
81117
});
82118
},
83119

@@ -86,7 +122,7 @@ namespace Endpoints {
86122
return _.extendOwn(endpoint, {
87123
call<TView>(value: string) {
88124
return AngularEndpointsService.call<TView>(this, value != null ? `"${value}"` : null);
89-
}
125+
},
90126
});
91127
},
92128

@@ -95,7 +131,7 @@ namespace Endpoints {
95131
return _.extendOwn(endpoint, {
96132
call<TView>() {
97133
return AngularEndpointsService.call<TView>(this, null);
98-
}
134+
},
99135
});
100136
}
101137
}
@@ -106,6 +142,10 @@ namespace Endpoints {
106142
return _.extendOwn(endpoint, {
107143
call<TView>() {
108144
return AngularEndpointsService.call<TView>(this, null);
145+
},
146+
147+
callCached<TView>() {
148+
return AngularEndpointsService.callCached<TView>(this, null);
109149
}
110150
});
111151
},
@@ -115,6 +155,10 @@ namespace Endpoints {
115155
return _.extendOwn(endpoint, {
116156
call<TView>() {
117157
return AngularEndpointsService.call<TView>(this, null);
158+
},
159+
160+
callCached<TView>() {
161+
return AngularEndpointsService.callCached<TView>(this, null);
118162
}
119163
});
120164
},
@@ -124,6 +168,10 @@ namespace Endpoints {
124168
return _.extendOwn(endpoint, {
125169
call<TView>() {
126170
return AngularEndpointsService.call<TView>(this, null);
171+
},
172+
173+
callCached<TView>() {
174+
return AngularEndpointsService.callCached<TView>(this, null);
127175
}
128176
});
129177
},
@@ -133,7 +181,7 @@ namespace Endpoints {
133181
return _.extendOwn(endpoint, {
134182
call<TView>(value: Interfaces.IMegaClass) {
135183
return AngularEndpointsService.call<TView>(this, value != null ? value : null);
136-
}
184+
},
137185
});
138186
}
139187
}

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/Block/TypeScriptBlock.cs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,14 @@ public TypeScriptBlock(string outer = "")
4545
Outer = outer;
4646
}
4747

48+
public TypeScriptBlock AddBlock(TypeScriptBlock block)
49+
{
50+
if (block != null)
51+
CreateChild(block);
52+
53+
return this;
54+
}
55+
4856
public TypeScriptBlock AddBlock(string outer = null, bool isFunctionBlock = false, string terminationString = "")
4957
{
5058
var child = CreateChild(outer, isFunctionBlock, terminationString);
@@ -59,6 +67,13 @@ public TypeScriptBlock AddAndUseBlock(string outer = null, bool isFunctionBlock
5967
return child;
6068
}
6169

70+
private TypeScriptBlock CreateChild(TypeScriptBlock block)
71+
{
72+
Children.Add(block);
73+
74+
return this;
75+
}
76+
6277
private TypeScriptBlock CreateChild(string outer, bool isFunctionBlock, string terminationString = "")
6378
{
6479
var child = new TypeScriptBlock

src/WebApiToTypeScript/Config/Config.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System.Collections.Generic;
2+
using System.Diagnostics.Eventing.Reader;
23

34
namespace WebApiToTypeScript.Config
45
{
@@ -12,6 +13,9 @@ public class Config
1213
public string EndpointsOutputDirectory { get; set; }
1314
= "Endpoints";
1415

16+
public bool EndpointsSupportCaching { get; set; }
17+
= true;
18+
1519
public string EndpointsFileName { get; set; }
1620
= "Endpoints.ts";
1721

src/WebApiToTypeScript/Endpoints/AngularEndpointsService.cs

Lines changed: 42 additions & 9 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,45 @@ 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+
.AddAndUseBlock($"if (this.endpointCache[endpoint._verb] == null)")
35+
.AddStatement("this.endpointCache[endpoint._verb] = {};")
36+
.Parent
37+
.AddAndUseBlock("if (this.endpointCache[endpoint._verb][data] == null)")
38+
.AddAndUseBlock("return this.call(endpoint, data).then(result =>", isFunctionBlock: true,
39+
terminationString: ";")
40+
.AddStatement("this.endpointCache[endpoint._verb][data] = result;")
41+
.AddStatement("return this.endpointCache[endpoint._verb][data];")
42+
.Parent
43+
.Parent
44+
.AddStatement("const deferred = this.$q.defer();")
45+
.AddStatement("deferred.resolve(this.endpointCache[endpoint._verb][data]);")
46+
.AddStatement("return deferred.promise;");
47+
48+
return serviceBlock
49+
.Parent
50+
.Parent;
2751
}
2852

2953
public void WriteServiceObjectToBlock(TypeScriptBlock serviceBlock, WebApiController webApiController)
@@ -72,6 +96,13 @@ public void WriteServiceObjectToBlock(TypeScriptBlock serviceBlock, WebApiContro
7296
var interfaceWithCallFullName = $"{Config.EndpointsNamespace}.{webApiController.Name}.I{actionName}WithCall";
7397
var endpointFullName = $"{Config.EndpointsNamespace}.{webApiController.Name}.{actionName}";
7498

99+
var cachedBlock = Config.EndpointsSupportCaching &&
100+
string.Equals(verb.Verb, "GET", StringComparison.InvariantCultureIgnoreCase)
101+
? new TypeScriptBlock()
102+
.AddAndUseBlock($"callCached<TView>({callArgumentDefinition})")
103+
.AddStatement($"return {Config.ServiceName}.callCached<TView>(this, {callArgumentValue});")
104+
: null;
105+
75106
controllerBlock
76107
.AddAndUseBlock
77108
(
@@ -81,8 +112,10 @@ public void WriteServiceObjectToBlock(TypeScriptBlock serviceBlock, WebApiContro
81112
)
82113
.AddStatement($"var endpoint = new {endpointFullName}(args);")
83114
.AddAndUseBlock("return _.extendOwn(endpoint,", isFunctionBlock: true, terminationString: ";")
84-
.AddAndUseBlock($"call<TView>({callArgumentDefinition})")
85-
.AddStatement($"return {Config.ServiceName}.call<TView>(this, {callArgumentValue});");
115+
.AddAndUseBlock($"call<TView>({callArgumentDefinition})", isFunctionBlock: false, terminationString: ",")
116+
.AddStatement($"return {Config.ServiceName}.call<TView>(this, {callArgumentValue});")
117+
.Parent
118+
.AddBlock(cachedBlock);
86119
}
87120
}
88121
}

0 commit comments

Comments
 (0)