diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/GenerateProxyCommand.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/GenerateProxyCommand.cs index deb4df21af..61cd20b0be 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/GenerateProxyCommand.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/GenerateProxyCommand.cs @@ -18,6 +18,7 @@ using Volo.Abp.DependencyInjection; using Microsoft.CSharp; using System.Collections.Generic; using System.Linq; +using static System.String; namespace Volo.Abp.Cli.Commands { @@ -36,246 +37,259 @@ namespace Volo.Abp.Cli.Commands public async Task ExecuteAsync(CommandLineArgs commandLineArgs) { - try - { - var apiUrl = commandLineArgs.Options.GetOrNull(Options.ApiUrl.Short, Options.ApiUrl.Long); - var uiFramework = commandLineArgs.Options.GetOrNull(Options.UiFramework.Short, Options.UiFramework.Long); - - //WebClient client = new WebClient(); - //string json = client.DownloadString(apiUrl); - StreamReader sr = File.OpenText("api-definition.json"); - string json = sr.ReadToEnd(); + var apiUrl = commandLineArgs.Options.GetOrNull(Options.ApiUrl.Short, Options.ApiUrl.Long); + var uiFramework = GetUiFramework(commandLineArgs); - Logger.LogInformation("Downloading api definition..."); - Logger.LogInformation("Api Url: " + apiUrl); + //WebClient client = new WebClient(); + //string json = client.DownloadString(apiUrl); + var sr = File.OpenText("api-definition.json"); + var json = sr.ReadToEnd(); - JObject data = JObject.Parse(json); + Logger.LogInformation("Downloading api definition..."); + Logger.LogInformation("Api Url: " + apiUrl); - var serviceIndexList = new List(); - var modelIndexList = new List(); + var data = JObject.Parse(json); - var moduleList = new Dictionary(); + Logger.LogInformation("Modules are combining"); + var moduleList = GetCombinedModules(data); + + Logger.LogInformation("Modules and types are creating"); - foreach (var module in data["modules"]) - { - string rootPath = ((string)module.First["rootPath"]).ToLower(); + var serviceIndexList = new List(); + var modelIndexList = new List(); + + foreach (var module in moduleList) + { + var moduleValue = JObject.Parse(module.Value); - if (moduleList.Any(p => p.Key == rootPath)) - { - var value = moduleList[rootPath]; + var rootPath = module.Key; + var controllerName = ""; + var controllerServiceName = ""; - moduleList[rootPath] = value.TrimEnd('}') + "," + module.First["controllers"].ToString().TrimStart('{'); - } - else { - moduleList.Add(rootPath, module.First["controllers"].ToString()); - } - } + Logger.LogInformation($"{rootPath} directory is creating"); + Directory.CreateDirectory($"src/app/{rootPath}/shared/models"); + Directory.CreateDirectory($"src/app/{rootPath}/shared/services"); - foreach (var module in moduleList) - { - JObject moduleValue = JObject.Parse(module.Value); + var serviceFileText = new StringBuilder(); - string rootPath = module.Key; - var controllerName = ""; - var controllerServiceName = ""; + serviceFileText.AppendLine("[firstTypeList]"); + serviceFileText.AppendLine("import { Injectable } from '@angular/core';"); + serviceFileText.AppendLine("import { Observable } from 'rxjs';"); + serviceFileText.AppendLine("[secondTypeList]"); + serviceFileText.AppendLine(""); + serviceFileText.AppendLine("@Injectable()"); + serviceFileText.AppendLine("export class [controllerName]Service {"); + serviceFileText.AppendLine(" constructor(private restService: RestService) {}"); + serviceFileText.AppendLine(""); - Directory.CreateDirectory(string.Format("src/app/{0}/shared/models", rootPath)); - Directory.CreateDirectory(string.Format("src/app/{0}/shared/services", rootPath)); + var firstTypeList = new List(); + var secondTypeList = new List(); - StringBuilder serviceFileText = new StringBuilder(); + foreach (var controller in moduleValue.Root.ToList().Select(item => item.First)) + { + controllerName = (string)controller["controllerName"]; + controllerServiceName = controllerName.PascalToKebabCase() + ".service.ts"; - serviceFileText.AppendLine("firstTypeList"); - serviceFileText.AppendLine("import { Injectable } from '@angular/core';"); - serviceFileText.AppendLine("import { Observable } from 'rxjs';"); - serviceFileText.AppendLine("secondTypeList"); - serviceFileText.AppendLine(""); - serviceFileText.AppendLine("@Injectable()"); - serviceFileText.AppendLine(string.Format("export class {0}Service ", "[ControllerName]") + "{"); - serviceFileText.AppendLine(" constructor(private restService: RestService) {}"); - serviceFileText.AppendLine(""); + foreach (var actionItem in controller["actions"]) + { + var action = actionItem.First; + var actionName = (string)action["uniqueName"]; - var firstTypeList = new List(); - var secondTypeList = new List(); + actionName = (char.ToLower(actionName[0]) + actionName.Substring(1)).Replace("Async", "").Replace("Controller", ""); - foreach (var item in moduleValue.Root.ToList()) - { - var controller = item.First; + var returnValueType = (string)action["returnValue"]["type"]; - controllerName = (string)controller["controllerName"]; - controllerServiceName = controllerName.PascalToKebabCase() + ".service.ts"; + var parameters = action["parameters"]; + var parametersText = new StringBuilder(); + var parametersIndex = 0; + var bodyExtra = ""; + var modelBindingExtra = ""; + var modelBindingExtraList = new List(); - foreach (var actionItem in controller["actions"]) + foreach (var parameter in parameters) { - var action = actionItem.First; - var actionName = (string)action["uniqueName"]; - - actionName = (char.ToLower(actionName[0]) + actionName.Substring(1)).Replace("Async", "").Replace("Controller", ""); + parametersIndex++; - var returnValueType = (string)action["returnValue"]["type"]; + if (parametersIndex > 1) + { + parametersText.Append(", "); + } - var parameters = action["parameters"]; - StringBuilder parametersText = new StringBuilder(); - var parametersIndex = 0; - var bodyExtra = ""; - var modelBindingExtra = ""; - var modelBindingExtraList = new List(); + var bindingSourceId = (string)parameter["bindingSourceId"]; + bindingSourceId = char.ToLower(bindingSourceId[0]) + bindingSourceId.Substring(1); - foreach (var parameter in parameters) + if (bindingSourceId == "body") { - parametersIndex++; + bodyExtra = ", body"; + var typeArray = ((string)parameter["type"]).Split("."); + var type = typeArray[typeArray.Length - 1]; - if (parametersIndex > 1) - parametersText.Append(", "); + parametersText.Append(bindingSourceId + ": " + type); + secondTypeList.Add(type); + } + else if (bindingSourceId == "path") + { + parametersText.Append((string)parameter["name"] + ": " + (string)parameter["typeSimple"]); + } + else if (bindingSourceId == "modelBinding") + { + var typeSimple = ""; + var type = ""; - var bindingSourceId = (string)parameter["bindingSourceId"]; - bindingSourceId = char.ToLower(bindingSourceId[0]) + bindingSourceId.Substring(1); + var parameterNameOnMethod = (string)parameter["nameOnMethod"]; - if (bindingSourceId == "body") + var parametersOnMethod = action["parametersOnMethod"]; + foreach (var parameterOnMethod in parametersOnMethod) { - bodyExtra = ", body"; - var typeArray = ((string)parameter["type"]).Split("."); - var type = typeArray[typeArray.Length - 1]; + var parametersOnMethodName = (string)parameterOnMethod["name"]; + if (parametersOnMethodName == parameterNameOnMethod) + { + typeSimple = (string)parameterOnMethod["typeSimple"]; - parametersText.Append(bindingSourceId + ": " + type); - secondTypeList.Add(type); + var typeArray = ((string)parameterOnMethod["type"]).Split("."); + type = typeArray[typeArray.Length - 1]; + } } - else if (bindingSourceId == "path") + + if (typeSimple == "string" || typeSimple == "boolean" || typeSimple == "number") { parametersText.Append((string)parameter["name"] + ": " + (string)parameter["typeSimple"]); + modelBindingExtraList.Add((string)parameter["name"]); } - else if (bindingSourceId == "modelBinding") + else { - var typeSimple = ""; - var type = ""; - - var parameterNameOnMethod = (string)parameter["nameOnMethod"]; - - var parametersOnMethod = action["parametersOnMethod"]; - foreach (var parameterOnMethod in parametersOnMethod) - { - var parametersOnMethodName = (string)parameterOnMethod["name"]; - if (parametersOnMethodName == parameterNameOnMethod) - { - typeSimple = (string)parameterOnMethod["typeSimple"]; - - var typeArray = ((string)parameterOnMethod["type"]).Split("."); - type = typeArray[typeArray.Length - 1]; - } - } - - if (typeSimple == "string" || typeSimple == "boolean" || typeSimple == "number") - { - parametersText.Append((string)parameter["name"] + ": " + (string)parameter["typeSimple"]); - modelBindingExtraList.Add((string)parameter["name"]); - } - else - { - parametersText.Append(string.Format("params = {{}} as {0}", type)); - modelBindingExtra = ", params"; - secondTypeList.Add(type); - break; - } + parametersText.Append($"params = {{}} as {type}"); + modelBindingExtra = ", params"; + secondTypeList.Add(type); + break; } } + } - if (returnValueType != null) + if (returnValueType != null) + { + if (returnValueType.IndexOf('<') > -1) { - if (returnValueType.IndexOf('<') > -1) - { - var firstTypeArray = returnValueType.Split("<")[0].Split("."); - var firstType = firstTypeArray[firstTypeArray.Length - 1]; - - var secondTypeArray = returnValueType.Split("<")[1].Split("."); - var secondType = secondTypeArray[secondTypeArray.Length - 1].TrimEnd('>'); + var firstTypeArray = returnValueType.Split("<")[0].Split("."); + var firstType = firstTypeArray[firstTypeArray.Length - 1]; - serviceFileText.AppendLine(string.Format(" {0}({1}): Observable<{2}<{3}>> {{", actionName, parametersText.ToString(), firstType, secondType)); + var secondTypeArray = returnValueType.Split("<")[1].Split("."); + var secondType = secondTypeArray[secondTypeArray.Length - 1].TrimEnd('>'); - firstTypeList.Add(firstType); - secondTypeList.Add(secondType); - } - else - { - var typeArray = returnValueType.Split("."); - var type = typeArray[typeArray.Length - 1].TrimEnd('>'); + serviceFileText.AppendLine( + $" {actionName}({parametersText}): Observable<{firstType}<{secondType}>> {{"); - if (type == "Void") - type = "void"; + firstTypeList.Add(firstType); + secondTypeList.Add(secondType); + } + else + { + var typeArray = returnValueType.Split("."); + var type = typeArray[typeArray.Length - 1].TrimEnd('>'); - serviceFileText.AppendLine(string.Format(" {0}({1}): Observable<{2}> {{", actionName, parametersText.ToString(), type)); - secondTypeList.Add(type); + if (type == "Void") + { + type = "void"; } - var modelIndex = CreateType(data, returnValueType, rootPath); - - if (!string.IsNullOrWhiteSpace(modelIndex)) - modelIndexList.Add(modelIndex); + serviceFileText.AppendLine( + $" {actionName}({parametersText}): Observable<{type}> {{"); + secondTypeList.Add(type); } - if (modelBindingExtraList != null && modelBindingExtraList.Count > 0) + var modelIndex = CreateType(data, returnValueType, rootPath); + + if (!IsNullOrWhiteSpace(modelIndex)) { - modelBindingExtra = ", params: { " + String.Join(", ", modelBindingExtraList.ToArray()) + " }"; + modelIndexList.Add(modelIndex); } + } - var url = ((string)action["url"]).Replace("/{", "/${"); - var httpMethod = (string)action["httpMethod"]; - serviceFileText.AppendLine(string.Format(" return this.restService.request({{ url: '/{0}', method: '{1}'{2}{3} }});", url, httpMethod, bodyExtra, modelBindingExtra)); - - serviceFileText.AppendLine(" }"); - } - - serviceIndexList.Add(controllerServiceName.Replace(".ts", "")); - } + if (modelBindingExtraList != null && modelBindingExtraList.Count > 0) + { + modelBindingExtra = ", params: { " + Join(", ", modelBindingExtraList.ToArray()) + " }"; + } - if (firstTypeList != null && firstTypeList.Count > 0) - { - var firstTypeListDistinct = ", " + String.Join(", ", firstTypeList.Where(p => p != "void").Distinct().ToArray()); - serviceFileText.Replace("firstTypeList", string.Format("import {{ RestService {0}}} from '@abp/ng.core';", firstTypeListDistinct)); - } - else - { - serviceFileText.Replace("firstTypeList", ""); - } + var url = ((string)action["url"]).Replace("/{", "/${"); + var httpMethod = (string)action["httpMethod"]; + serviceFileText.AppendLine( + $" return this.restService.request({{ url: '/{url}', method: '{httpMethod}'{bodyExtra}{modelBindingExtra} }});"); - if (secondTypeList != null && secondTypeList.Count > 0) - { - var secondTypeListDistinct = String.Join(", ", secondTypeList.Where(p => p != "void").Distinct().ToArray()); - serviceFileText.Replace("secondTypeList", string.Format("import {{{0}}} from '../models';", secondTypeListDistinct)); - } - else - { - serviceFileText.Replace("secondTypeList", ""); + serviceFileText.AppendLine(" }"); } - serviceFileText.AppendLine("}"); + serviceIndexList.Add(controllerServiceName.Replace(".ts", "")); + } + + if (firstTypeList != null && firstTypeList.Count > 0) + { + var firstTypeListDistinct = ", " + Join(", ", firstTypeList.Where(p => p != "void").Distinct().ToArray()); + serviceFileText.Replace("[firstTypeList]", + $"import {{ RestService {firstTypeListDistinct}}} from '@abp/ng.core';"); + } + else + { + serviceFileText.Replace("[firstTypeList]", ""); + } - serviceFileText.Replace("[ControllerName]", controllerName); - System.IO.File.WriteAllText(string.Format("src/app/{0}/shared/services/{1}", rootPath, controllerServiceName), serviceFileText.ToString()); + if (secondTypeList != null && secondTypeList.Count > 0) + { + var secondTypeListDistinct = Join(", ", secondTypeList.Where(p => p != "void").Distinct().ToArray()); + serviceFileText.Replace("[secondTypeList]", + $"import {{{secondTypeListDistinct}}} from '../models';"); } + else + { + serviceFileText.Replace("[secondTypeList]", ""); + } - //StringBuilder serviceIndexFileText = new StringBuilder(); + serviceFileText.AppendLine("}"); - //foreach (var serviceIndexItem in serviceIndexList) - //{ - // serviceIndexFileText.AppendLine(string.Format("export * from './{0}';", serviceIndexItem)); - //} + serviceFileText.Replace("[controllerName]", controllerName); + File.WriteAllText($"src/app/{rootPath}/shared/services/{controllerServiceName}", serviceFileText.ToString()); - //System.IO.File.WriteAllText(string.Format("src/app/{0}/shared/services/index.ts", rootPath), serviceIndexFileText.ToString()); + var serviceIndexFileText = new StringBuilder(); - //StringBuilder modelIndexFileText = new StringBuilder(); + foreach (var serviceIndexItem in serviceIndexList) + { + serviceIndexFileText.AppendLine($"export * from './{serviceIndexItem}';"); + } + + File.WriteAllText($"src/app/{rootPath}/shared/services/index.ts", serviceIndexFileText.ToString()); - //foreach (var modelIndexItem in modelIndexList) - //{ - // modelIndexFileText.AppendLine(string.Format("export * from './{0}';", modelIndexItem)); - //} + var modelIndexFileText = new StringBuilder(); + + foreach (var modelIndexItem in modelIndexList) + { + modelIndexFileText.AppendLine($"export * from './{modelIndexItem}';"); + } - //System.IO.File.WriteAllText(string.Format("src/app/{0}/shared/models/index.ts", rootPath), modelIndexFileText.ToString()); + File.WriteAllText($"src/app/{rootPath}/shared/models/index.ts", modelIndexFileText.ToString()); } - catch (Exception ex) + } + + private Dictionary GetCombinedModules(JToken data) + { + var moduleList = new Dictionary(); + foreach (var module in data["modules"]) { - throw; + var rootPath = ((string)module.First["rootPath"]).ToLower(); + + if (moduleList.Any(p => p.Key == rootPath)) + { + var value = moduleList[rootPath]; + + moduleList[rootPath] = value.TrimEnd('}') + "," + module.First["controllers"].ToString().TrimStart('{'); + } + else + { + moduleList.Add(rootPath, module.First["controllers"].ToString()); + } } + + return moduleList; } private string CreateType(JObject data, string returnValueType, string rootPath) @@ -290,59 +304,63 @@ namespace Volo.Abp.Cli.Commands || returnValueType.Contains("IStringValueType") || returnValueType.Contains("IValueValidator") ) + { return null; + } var typeNameSplit = returnValueType.Split("."); var typeName = typeNameSplit[typeNameSplit.Length - 1]; var typeModelName = typeName.Replace("<", "").Replace(">", "").PascalToKebabCase() + ".ts"; - var path = string.Format("src/app/{0}/shared/models/{1}", rootPath, typeModelName); + var path = $"src/app/{rootPath}/shared/models/{typeModelName}"; if (File.Exists(path)) + { return null; + } - - StringBuilder modelFileText = new StringBuilder(); - + var modelFileText = new StringBuilder(); var baseType = (string)type["baseType"]; var extends = ""; - if (!string.IsNullOrWhiteSpace(baseType) && baseType != "System.Enum") + if (!IsNullOrWhiteSpace(baseType) && baseType != "System.Enum") { var baseTypeSplit = baseType.Split("."); var baseTypeName = baseTypeSplit[baseTypeSplit.Length - 1].Replace("<", "").Replace(">", ""); var baseTypeKebabCase = "./" + baseTypeName.PascalToKebabCase(); if (baseType.Contains("Volo.Abp.Application.Dtos.EntityDto")) + { baseTypeKebabCase = "@abp/ng.core"; + } if (baseTypeName.Contains("guid") || baseTypeName.Contains("Guid")) + { baseTypeName = "string"; + } - modelFileText.AppendLine(string.Format("import {{ {0} }} from '{1}';", baseTypeName, baseTypeKebabCase)); + modelFileText.AppendLine($"import {{ {baseTypeName} }} from '{baseTypeKebabCase}';"); extends = "extends " + baseTypeName; } if (baseType == "System.Enum" && (string)type.First["isEnum"] == "True") { - modelFileText.AppendLine(string.Format("export enum {0} {{", typeName)); - - var enumDictionary = new Dictionary(); + modelFileText.AppendLine($"export enum {typeName} {{"); var enumNameList = type.First["enumNames"].ToArray(); var enumValueList = type.First["enumValues"].ToArray(); - for (int i = 0; i < enumNameList.Length; i++) + for (var i = 0; i < enumNameList.Length; i++) { - modelFileText.AppendLine(string.Format("{0} = {1},", enumNameList[i], enumValueList[i])); + modelFileText.AppendLine($"{enumNameList[i]} = {enumValueList[i]},"); } modelFileText.AppendLine("}"); } else { - modelFileText.AppendLine(string.Format("export class {0} {1} {{", typeName, extends)); + modelFileText.AppendLine($"export class {typeName} {extends} {{"); foreach (var property in type["properties"]) { @@ -352,7 +370,9 @@ namespace Volo.Abp.Cli.Commands var typeSimple = (string)property["typeSimple"]; if (typeSimple.IndexOf("[") > -1 && typeSimple.IndexOf("]") > -1) + { typeSimple = typeSimple.Replace("[", "").Replace("]", "") + "[]"; + } if (typeSimple.StartsWith("Volo.Abp")) { @@ -382,14 +402,14 @@ namespace Volo.Abp.Cli.Commands typeSimple = "any" + (typeSimple.Contains("[]") ? "[]" : ""); } - modelFileText.AppendLine(string.Format(" {0}: {1};", propertyName, typeSimple)); + modelFileText.AppendLine($" {propertyName}: {typeSimple};"); } modelFileText.AppendLine(""); - modelFileText.AppendLine(string.Format(" constructor(initialValues: Partial<{0}> = {{}}) {{", typeName)); + modelFileText.AppendLine($" constructor(initialValues: Partial<{typeName}> = {{}}) {{"); - if (!string.IsNullOrWhiteSpace(baseType)) + if (!IsNullOrWhiteSpace(baseType)) { modelFileText.AppendLine(" super(initialValues);"); modelFileText.AppendLine(" }"); @@ -410,7 +430,7 @@ namespace Volo.Abp.Cli.Commands modelFileText.AppendLine("}"); } - System.IO.File.WriteAllText(string.Format("src/app/{0}/shared/models/{1}", rootPath, typeModelName), modelFileText.ToString()); + File.WriteAllText($"src/app/{rootPath}/shared/models/{typeModelName}", modelFileText.ToString()); return typeModelName.Replace(".ts", ""); } @@ -478,7 +498,7 @@ namespace Volo.Abp.Cli.Commands { public static string PascalToKebabCase(this string value) { - if (string.IsNullOrEmpty(value)) + if (IsNullOrEmpty(value)) return value; return Regex.Replace(