Skip to content

Commit f150f12

Browse files
author
Balakrishnan Ranganathan
committed
Separate endpoints and angular endpoints generation into services
1 parent 05a63ef commit f150f12

8 files changed

Lines changed: 283 additions & 239 deletions

File tree

src/WebApiToTypeScript/Config/Config.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,9 @@ public class Config
2929
public string ServiceNamespace { get; set; }
3030
= "Endpoints";
3131

32+
public string ServiceName { get; set; }
33+
= "AngularEndpointsService";
34+
3235

3336
public bool GenerateEnums { get; set; }
3437
= true;
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
using WebApiToTypeScript.Block;
2+
using WebApiToTypeScript.Interfaces;
3+
using WebApiToTypeScript.WebApi;
4+
5+
namespace WebApiToTypeScript.Endpoints
6+
{
7+
public class AngularEndpointsService : ServiceAware
8+
{
9+
public TypeScriptBlock CreateServiceBlock()
10+
{
11+
return new TypeScriptBlock($"{Config.NamespaceOrModuleName} {Config.ServiceNamespace}")
12+
.AddAndUseBlock($"export class {Config.ServiceName}")
13+
.AddStatement("static $inject = ['$http'];")
14+
.AddStatement("static $http: ng.IHttpService;")
15+
.AddAndUseBlock("constructor($http: ng.IHttpService)")
16+
.AddStatement($"{Config.ServiceName}.$http = $http;")
17+
.Parent
18+
.AddAndUseBlock("static call(endpoint: IEndpoint, data)")
19+
.AddAndUseBlock($"return {Config.ServiceName}.$http(", isFunctionBlock: true, terminationString: ";")
20+
.AddStatement("method: endpoint.verb,")
21+
.AddStatement("url: endpoint.toString(),")
22+
.AddStatement("data: data")
23+
.Parent
24+
.Parent
25+
.Parent;
26+
}
27+
28+
public void WriteServiceObjectToBlock(TypeScriptBlock serviceBlock, WebApiController webApiController)
29+
{
30+
var controllerBlock = serviceBlock
31+
.AddAndUseBlock($"public {webApiController.Name} =");
32+
33+
var actions = webApiController.Actions;
34+
35+
for (var a = 0; a < actions.Count; a++)
36+
{
37+
var action = actions[a];
38+
39+
for (var v = 0; v < action.Verbs.Count; v++)
40+
{
41+
var verb = action.Verbs[v];
42+
43+
var actionName = action.GetActionNameForVerb(verb);
44+
45+
var isLastActionAndVerb = a == actions.Count - 1
46+
&& v == action.Verbs.Count - 1;
47+
48+
var constructorParametersList = action.GetConstructorParametersList();
49+
var constructorParameterNamesList = action.GetConstructorParameterNamesList();
50+
51+
var callArgumentDefinition = action.GetCallArgumentDefinition(verb);
52+
var callArgumentValue = action.GetCallArgumentValue(verb);
53+
54+
var interfaceFullName = $"{Config.EndpointsNamespace}.{webApiController.Name}.I{actionName}";
55+
var endpointFullName = $"{Config.EndpointsNamespace}.{webApiController.Name}.{actionName}";
56+
57+
controllerBlock
58+
.AddAndUseBlock
59+
(
60+
outer: $"{actionName}: ({constructorParametersList}): {interfaceFullName} =>",
61+
isFunctionBlock: false,
62+
terminationString: !isLastActionAndVerb ? "," : string.Empty
63+
)
64+
.AddStatement($"var endpoint = new {endpointFullName}({constructorParameterNamesList});")
65+
.AddAndUseBlock("var callHook =")
66+
.AddAndUseBlock($"call({callArgumentDefinition})")
67+
.AddStatement($"return {Config.ServiceName}.call(this, {callArgumentValue});")
68+
.Parent
69+
.Parent
70+
.AddStatement("return _.extend(endpoint, callHook);");
71+
}
72+
}
73+
}
74+
}
75+
}
Lines changed: 164 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,164 @@
1+
using System.Linq;
2+
using WebApiToTypeScript.Block;
3+
using WebApiToTypeScript.Interfaces;
4+
using WebApiToTypeScript.WebApi;
5+
6+
namespace WebApiToTypeScript.Endpoints
7+
{
8+
public class EndpointsService : ServiceAware
9+
{
10+
public TypeScriptBlock CreateEndpointBlock()
11+
{
12+
return new TypeScriptBlock($"{Config.NamespaceOrModuleName} {Config.EndpointsNamespace}")
13+
.AddAndUseBlock($"export interface {IEndpoint}")
14+
.AddStatement("verb: string")
15+
.AddStatement("toString(): string")
16+
.Parent
17+
.AddAndUseBlock($"export interface {IHaveQueryParams}")
18+
.AddStatement("getQueryParams(): Object")
19+
.Parent;
20+
}
21+
22+
public void WriteEndpointClassToBlock(TypeScriptBlock endpointBlock, WebApiController webApiController)
23+
{
24+
var controllerBlock = endpointBlock
25+
.AddAndUseBlock($"export {Config.NamespaceOrModuleName} {webApiController.Name}");
26+
27+
var actions = webApiController.Actions;
28+
29+
foreach (var action in actions)
30+
{
31+
foreach (var verb in action.Verbs)
32+
{
33+
var actionName = action.GetActionNameForVerb(verb);
34+
35+
var interfaceBlock = controllerBlock
36+
.AddAndUseBlock($"export interface I{actionName} extends {IEndpoint}");
37+
38+
WriteInterfaceToBlock(interfaceBlock, action);
39+
40+
var classBlock = controllerBlock
41+
.AddAndUseBlock($"export class {actionName} implements {IEndpoint}")
42+
.AddStatement($"verb = '{verb.VerbMethod}';");
43+
44+
WriteConstructorToBlock(classBlock, action);
45+
46+
WriteGetQueryStringToBlock(classBlock, action);
47+
48+
WriteToStringToBlock(classBlock, action);
49+
}
50+
}
51+
}
52+
53+
private void WriteInterfaceToBlock(TypeScriptBlock interfaceBlock, WebApiAction action)
54+
{
55+
var constructorParameterMappings = action.GetConstructorParameterMappings();
56+
foreach (var constructorParameterMapping in constructorParameterMappings)
57+
{
58+
interfaceBlock
59+
.AddStatement($"{constructorParameterMapping.String};");
60+
}
61+
62+
var callArguments = action.BodyParameters;
63+
64+
var callArgumentStrings = callArguments
65+
.Select(a => a.GetParameterString(false))
66+
.ToList();
67+
68+
var callArgumentsList = string.Join(", ", callArgumentStrings);
69+
70+
interfaceBlock
71+
.AddStatement($"call({callArgumentsList});");
72+
}
73+
74+
private void WriteToStringToBlock(TypeScriptBlock classBlock, WebApiAction action)
75+
{
76+
var toStringBlock = classBlock
77+
.AddAndUseBlock("toString = (): string =>");
78+
79+
var queryString = action.QueryStringParameters.Any()
80+
? " + this.getQueryString()"
81+
: string.Empty;
82+
83+
toStringBlock
84+
.AddStatement($"return `{action.Controller.BaseEndpoint}{action.Endpoint}`{queryString};");
85+
}
86+
87+
private void WriteGetQueryStringToBlock(TypeScriptBlock classBlock, WebApiAction action)
88+
{
89+
var queryStringParameters = action.QueryStringParameters;
90+
91+
if (!queryStringParameters.Any())
92+
return;
93+
94+
var queryStringBlock = classBlock
95+
.AddAndUseBlock("private getQueryString = (): string =>")
96+
.AddStatement("var parameters: string[] = [];");
97+
98+
foreach (var routePart in queryStringParameters)
99+
{
100+
var argumentName = routePart.Name;
101+
102+
var block = queryStringBlock
103+
.AddAndUseBlock($"if (this.{argumentName} != null)");
104+
105+
var argumentType = routePart.GetTypeScriptType();
106+
107+
if (argumentType.IsPrimitive || argumentType.IsEnum)
108+
{
109+
if (argumentType.IsCollection)
110+
{
111+
block
112+
.AddStatement($"parameters.push(`{argumentName}=${{this.{argumentName}.join(',')}}`);");
113+
}
114+
else
115+
{
116+
block
117+
.AddStatement($"parameters.push(`{argumentName}=${{encodeURIComponent(this.{argumentName}.toString())}}`);");
118+
}
119+
}
120+
else
121+
{
122+
block
123+
.AddStatement($"var {argumentName}Params = this.{argumentName}.getQueryParams();")
124+
.AddAndUseBlock($"Object.keys({argumentName}Params).forEach((key) =>", isFunctionBlock: true, terminationString: ";")
125+
.AddAndUseBlock($"if ({argumentName}Params[key] != null)")
126+
.AddStatement($"parameters.push(`${{key}}=${{encodeURIComponent({argumentName}Params[key].toString())}}`);");
127+
}
128+
}
129+
130+
queryStringBlock
131+
.AddAndUseBlock("if (parameters.length > 0)")
132+
.AddStatement("return '?' + parameters.join('&');")
133+
.Parent
134+
.AddStatement("return '';");
135+
}
136+
137+
private void WriteConstructorToBlock(TypeScriptBlock classBlock, WebApiAction action)
138+
{
139+
var constructorParameterMappings = action.GetConstructorParameterMappings();
140+
141+
if (!constructorParameterMappings.Any())
142+
return;
143+
144+
var constructorParameterStrings = constructorParameterMappings
145+
.Select(p => $"public {p.String}");
146+
147+
var constructorParametersList =
148+
string.Join(", ", constructorParameterStrings);
149+
150+
var constructorBlock = classBlock
151+
.AddAndUseBlock($"constructor({constructorParametersList})");
152+
153+
foreach (var mapping in constructorParameterMappings)
154+
{
155+
if (mapping.TypeMapping?.AutoInitialize ?? false)
156+
{
157+
constructorBlock
158+
.AddAndUseBlock($"if (this.{mapping.Name} == null)")
159+
.AddStatement($"this.{mapping.Name} = new {mapping.TypeMapping.TypeScriptTypeName}();");
160+
}
161+
}
162+
}
163+
}
164+
}

src/WebApiToTypeScript/Enums/EnumsService.cs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,22 @@
22
using System.Collections.Generic;
33
using System.Linq;
44
using WebApiToTypeScript.Block;
5+
using WebApiToTypeScript.Interfaces;
56

67
namespace WebApiToTypeScript.Enums
78
{
8-
public class EnumsService
9+
public class EnumsService : ServiceAware
910
{
1011
private List<TypeDefinition> Enums { get; }
1112
= new List<TypeDefinition>();
1213

14+
public TypeScriptBlock CreateEnumsBlock()
15+
{
16+
return Config.GenerateEnums
17+
? new TypeScriptBlock($"{Config.NamespaceOrModuleName} {Config.EnumsNamespace}")
18+
: new TypeScriptBlock();
19+
}
20+
1321
public void AddEnum(TypeDefinition thingType)
1422
{
1523
if (Enums.All(e => e.FullName != thingType.FullName))

src/WebApiToTypeScript/Interfaces/InterfaceService.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,11 @@ public class InterfaceService : ServiceAware
1111
private InterfaceNode InterfaceNode { get; }
1212
= new InterfaceNode();
1313

14+
public TypeScriptBlock CreateInterfacesBlock()
15+
{
16+
return new TypeScriptBlock($"{Config.NamespaceOrModuleName} {Config.InterfacesNamespace}");
17+
}
18+
1419
public TypeScriptBlock WriteInterfacesToBlock(TypeScriptBlock interfacesBlock)
1520
{
1621
WriteInterfaces(interfacesBlock, InterfaceNode);

src/WebApiToTypeScript/Interfaces/ServiceAware.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@ namespace WebApiToTypeScript.Interfaces
55
{
66
public abstract class ServiceAware
77
{
8+
protected string IHaveQueryParams = WebApiToTypeScript.IHaveQueryParams;
9+
protected string IEndpoint = WebApiToTypeScript.IEndpoint;
10+
811
protected TypeService TypeService
912
=> WebApiToTypeScript.TypeService;
1013

0 commit comments

Comments
 (0)