Beispiel #1
0
 public string Apply(string value)
 {
     if (value[0] >= 'A' && value[0] <= 'Z')
     {
         value = CodeGenUtility.ToCamelCase(value);
     }
     return(value);
 }
Beispiel #2
0
        private static ServiceTypeInfo TryCreateMethodResponseBodyType(HttpMethodInfo httpMethodInfo, HttpResponseInfo httpResponseInfo)
        {
            if (httpResponseInfo.NormalFields == null || httpResponseInfo.NormalFields.Count == 0)
            {
                return(null);
            }

            return(ServiceTypeInfo.CreateDto(new ServiceDtoInfo(
                                                 name: $"{CodeGenUtility.ToPascalCase(httpMethodInfo.ServiceMethod.Name)}Response",
                                                 fields: httpResponseInfo.NormalFields.Select(x => x.ServiceField))));
        }
        private void Convert(SwaggerParserContext context)
        {
            if (m_swaggerService.Swagger == null)
            {
                m_errors.Add(context.CreateError("swagger field is missing."));
            }
            else if (m_swaggerService.Swagger != SwaggerUtility.SwaggerVersion)
            {
                m_errors.Add(context.CreateError($"swagger should be '{SwaggerUtility.SwaggerVersion}'.", "swagger"));
            }

            if (m_swaggerService.Info == null)
            {
                m_errors.Add(context.CreateError("info is missing."));
            }

            var name = m_serviceName;

            if (name != null && !ServiceDefinitionUtility.IsValidName(name))
            {
                m_errors.Add(context.CreateError("ServiceName generator option is not a valid service name."));
            }
            if (name == null)
            {
                name = m_swaggerService.Info?.Identifier;
            }
            if (name != null && !ServiceDefinitionUtility.IsValidName(name))
            {
                m_errors.Add(context.CreateError("info/x-identifier is not a valid service name.", "info/x-identifier"));
            }
            if (name == null && m_swaggerService.Info?.Title is string title)
            {
                name = CodeGenUtility.ToPascalCase(title);
            }
            if (name == null)
            {
                m_errors.Add(context.CreateError("info/title is missing.", "info"));
            }
            if (name != null && !ServiceDefinitionUtility.IsValidName(name))
            {
                m_errors.Add(context.CreateError("info/title is not a valid service name.", "info/title"));
            }

            var attributes = new List <ServiceAttributeInfo>();

            var version = m_swaggerService.Info?.Version;

            if (!string.IsNullOrWhiteSpace(version))
            {
                attributes.Add(new ServiceAttributeInfo("info",
                                                        new[] { new ServiceAttributeParameterInfo("version", version !, context.CreatePart("info/version") !) },
Beispiel #4
0
        /// <summary>
        /// Generates the ASP.NET controller.
        /// </summary>
        public override CodeGenOutput GenerateOutput(ServiceInfo serviceInfo)
        {
            string serviceName      = serviceInfo.Name;
            string apiNamespaceName = ApiNamespaceName ?? CSharpUtility.GetNamespaceName(serviceInfo);
            string namespaceName    = NamespaceName ?? $"{apiNamespaceName}.Controllers";
            string controllerName   = $"{CodeGenUtility.Capitalize(serviceName)}Controller";
            var    httpServiceInfo  = HttpServiceInfo.Create(serviceInfo);

            return(new CodeGenOutput(CreateFile($"{controllerName}{CSharpUtility.FileExtension}", code =>
            {
                CSharpUtility.WriteFileHeader(code, GeneratorName);

                List <string> usings = new List <string>
                {
                    "System",
                    "System.Net.Http",
                    "System.Threading",
                    "System.Threading.Tasks",
                    "Facility.Core",
                    TargetFramework == AspNetFramework.WebApi ? "System.Web.Http" : "Microsoft.AspNetCore.Mvc",
                    apiNamespaceName
                };
                CSharpUtility.WriteUsings(code, usings, namespaceName);

                code.WriteLine("#pragma warning disable 1591 // missing XML comment");
                code.WriteLine();

                code.WriteLine($"namespace {namespaceName}");
                using (code.Block())
                {
                    CSharpUtility.WriteCodeGenAttribute(code, GeneratorName);
                    code.WriteLine($"public partial class {controllerName}");
                    using (code.Block())
                    {
                        foreach (var httpMethodInfo in httpServiceInfo.Methods)
                        {
                            var methodInfo = httpMethodInfo.ServiceMethod;
                            string methodName = CodeGenUtility.Capitalize(methodInfo.Name);

                            code.WriteLineSkipOnce();
                            CSharpUtility.WriteObsoleteAttribute(code, methodInfo);
                            code.WriteLine($"[{GetHttpMethodAttribute(httpMethodInfo)}, Route(\"{httpMethodInfo.Path.Substring(1)}\")]");
                            code.WriteLine($"public Task<HttpResponseMessage> {methodName}(HttpRequestMessage httpRequest, CancellationToken cancellationToken = default(CancellationToken))");
                            using (code.Block())
                                code.WriteLine($"return GetServiceHttpHandler().TryHandle{methodName}Async(httpRequest, cancellationToken);");
                        }
                    }
                }
            })));
        }
Beispiel #5
0
 private static string GetHttpMethodAttribute(HttpMethodInfo httpMethodInfo)
 {
     if (httpMethodInfo.Method == HttpMethod.Delete || httpMethodInfo.Method == HttpMethod.Get ||
         httpMethodInfo.Method == HttpMethod.Head || httpMethodInfo.Method == HttpMethod.Options ||
         httpMethodInfo.Method == new HttpMethod("PATCH") ||
         httpMethodInfo.Method == HttpMethod.Post || httpMethodInfo.Method == HttpMethod.Put)
     {
         return("Http" + CodeGenUtility.Capitalize(httpMethodInfo.Method.ToString().ToLowerInvariant()));
     }
     else
     {
         return($"AcceptVerbs(\"{httpMethodInfo.Method}\")");
     }
 }
Beispiel #6
0
 private void WriteDto(CodeWriter code, ServiceDtoInfo dtoInfo, ServiceInfo service)
 {
     code.WriteLine();
     WriteJsDoc(code, dtoInfo);
     using (code.Block($"export interface I{CodeGenUtility.Capitalize(dtoInfo.Name)} {{", "}"))
     {
         foreach (var fieldInfo in dtoInfo.Fields)
         {
             code.WriteLineSkipOnce();
             WriteJsDoc(code, fieldInfo);
             code.WriteLine($"{fieldInfo.Name}?: {RenderFieldType(service.GetFieldType(fieldInfo))};");
         }
     }
 }
Beispiel #7
0
        private static string GetBodyFieldNameForStatusCode(string statusCode)
        {
            int statusCodeNumber;

            if (int.TryParse(statusCode, out statusCodeNumber))
            {
                string name = ((HttpStatusCode)statusCodeNumber).ToString();
                if (name != statusCode)
                {
                    return(CodeGenUtility.ToCamelCase(name));
                }
            }

            return(CodeGenUtility.ToCamelCase($"status {statusCode}"));
        }
Beispiel #8
0
        private string RenderFieldType(ServiceTypeInfo fieldType)
        {
            switch (fieldType.Kind)
            {
            case ServiceTypeKind.String:
            case ServiceTypeKind.Bytes:
            case ServiceTypeKind.Enum:
                return("string");

            case ServiceTypeKind.Boolean:
                return("boolean");

            case ServiceTypeKind.Double:
            case ServiceTypeKind.Int32:
            case ServiceTypeKind.Int64:
            case ServiceTypeKind.Decimal:
                return("number");

            case ServiceTypeKind.Object:
                return("{ [name: string]: any }");

            case ServiceTypeKind.Error:
                return("IServiceError");

            case ServiceTypeKind.Dto:
                return($"I{CodeGenUtility.Capitalize(fieldType.Dto.Name)}");

            case ServiceTypeKind.Result:
                return($"IServiceResult<{RenderFieldType(fieldType.ValueType)}>");

            case ServiceTypeKind.Array:
                return($"{RenderFieldType(fieldType.ValueType)}[]");

            case ServiceTypeKind.Map:
                return($"{{ [name: string]: {RenderFieldType(fieldType.ValueType)} }}");

            default:
                throw new NotSupportedException("Unknown field type " + fieldType.Kind);
            }
        }
Beispiel #9
0
        private void AddResponseFields(IList <ServiceFieldInfo> responseFields, string statusCode, SwaggerResponse swaggerResponse, string serviceMethodName, IList <ServiceAttributeParameterInfo> httpAttributeValues, bool isOnlyResponse, SwaggerService swaggerService, NamedTextPosition position)
        {
            var bodySchema = default(KeyValuePair <string, SwaggerSchema>);

            if (swaggerResponse.Schema != null)
            {
                bodySchema = swaggerService.ResolveDefinition(swaggerResponse.Schema, position);
            }

            if (bodySchema.Value != null && (bodySchema.Value.Type ?? SwaggerSchemaType.Object) == SwaggerSchemaType.Object &&
                (bodySchema.Key == null || bodySchema.Key.Equals(serviceMethodName + "Response", StringComparison.OrdinalIgnoreCase)))
            {
                httpAttributeValues.Add(new ServiceAttributeParameterInfo("code", statusCode, position));
                AddFieldsFromSchema(responseFields, swaggerService, position, bodySchema);
            }
            else if (swaggerResponse.Identifier == null && isOnlyResponse && swaggerResponse.Schema == null)
            {
                httpAttributeValues.Add(new ServiceAttributeParameterInfo("code", statusCode, position));
            }
            else
            {
                responseFields.Add(new ServiceFieldInfo(
                                       swaggerResponse.Identifier ?? CodeGenUtility.ToCamelCase(bodySchema.Key) ?? GetBodyFieldNameForStatusCode(statusCode),
                                       typeName: bodySchema.Key ?? (bodySchema.Value != null ? SwaggerUtility.FilterBodyTypeName(swaggerService.TryGetFacilityTypeName(bodySchema.Value, position)) : null) ?? "boolean",
                                       attributes: new[]
                {
                    new ServiceAttributeInfo("http",
                                             new[]
                    {
                        new ServiceAttributeParameterInfo("from", "body", position),
                        new ServiceAttributeParameterInfo("code", statusCode, position),
                    })
                },
                                       summary: PrepareSummary(swaggerResponse.Description),
                                       position: position));
            }
        }
Beispiel #10
0
 private static string GetHttpMethodAttribute(HttpMethodInfo httpMethodInfo)
 {
     return("Http" + CodeGenUtility.Capitalize(httpMethodInfo.Method.ToLowerInvariant()));
 }
Beispiel #11
0
 public static string GetEnumValueName(ServiceEnumValueInfo enumValue) => CodeGenUtility.Capitalize(enumValue.Name);
Beispiel #12
0
 public static string GetResponseDtoName(ServiceMethodInfo methodInfo) => CodeGenUtility.Capitalize(methodInfo.Name) + "ResponseDto";
Beispiel #13
0
 public static string GetMethodName(ServiceMethodInfo methodInfo) => CodeGenUtility.Capitalize(methodInfo.Name);
 public CodeTemplateGlobals(PythonGenerator generator, ServiceInfo serviceInfo, HttpServiceInfo?httpServiceInfo)
 {
     Service            = serviceInfo;
     HttpService        = httpServiceInfo;
     CodeGenCommentText = CodeGenUtility.GetCodeGenComment(generator.GeneratorName ?? "");
 }
Beispiel #15
0
        /// <summary>
        /// Generates the Python.
        /// </summary>
        public override CodeGenOutput GenerateOutput(ServiceInfo serviceInfo)
        {
            var outputFiles = new List <CodeGenFile>();

            var httpServiceInfo = HttpServiceInfo.Create(serviceInfo);

            var templateText = GetEmbeddedResourceText("Facility.CodeGen.Python.template.scriban-txt");
            var outputText   = CodeTemplateUtility.Render(templateText, new CodeTemplateGlobals(this, serviceInfo, httpServiceInfo));

            using var stringReader = new StringReader(outputText);

            var fileStart = "";

            string?line;

            while ((line = stringReader.ReadLine()) != null)
            {
                var match = Regex.Match(line, @"^==+>");
                if (match.Success)
                {
                    fileStart = match.Value;
                    break;
                }
            }

            while (line != null)
            {
                var fileName = line.Substring(fileStart.Length);

                var fileLines = new List <string>();
                while ((line = stringReader.ReadLine()) != null && !line.StartsWith(fileStart, StringComparison.Ordinal))
                {
                    fileLines.Add(line);
                }

                // skip exactly one blank line to allow file start to stand out
                if (fileLines.Count != 0 && string.IsNullOrWhiteSpace(fileLines[0]))
                {
                    fileLines.RemoveAt(0);
                }

                // remove all blank lines at the end
                while (fileLines.Count != 0 && string.IsNullOrWhiteSpace(fileLines[fileLines.Count - 1]))
                {
                    fileLines.RemoveAt(fileLines.Count - 1);
                }

                outputFiles.Add(CreateFile(fileName.Trim(), code =>
                {
                    foreach (var fileLine in fileLines)
                    {
                        code.WriteLine(fileLine);
                    }
                }));
            }

            var codeGenComment  = CodeGenUtility.GetCodeGenComment(GeneratorName ?? "");
            var patternsToClean = new[]
            {
                new CodeGenPattern("*.py", codeGenComment),
            };

            return(new CodeGenOutput(outputFiles, patternsToClean));
        }
Beispiel #16
0
        private void AddRequestFields(IList <ServiceFieldInfo> requestFields, SwaggerParameter swaggerParameter, string serviceMethodName, string httpMethod, SwaggerService swaggerService, NamedTextPosition position)
        {
            string kind = swaggerParameter.In;

            if (kind == SwaggerParameterKind.Path || kind == SwaggerParameterKind.Query || kind == SwaggerParameterKind.Header)
            {
                string typeName = swaggerService.TryGetFacilityTypeName(swaggerParameter, position);
                if (typeName != null)
                {
                    if (typeName.EndsWith("[]", StringComparison.Ordinal))
                    {
                        typeName = "string";
                    }

                    var attributes = new List <ServiceAttributeInfo>();

                    if (swaggerParameter.Obsolete.GetValueOrDefault())
                    {
                        attributes.Add(new ServiceAttributeInfo("obsolete"));
                    }

                    string fieldName = swaggerParameter.Identifier ?? swaggerParameter.Name;
                    if (!ServiceDefinitionUtility.IsValidName(fieldName))
                    {
                        fieldName = CodeGenUtility.ToCamelCase(fieldName);
                    }

                    if (kind == SwaggerParameterKind.Query)
                    {
                        var parameters = new List <ServiceAttributeParameterInfo>();
                        if (httpMethod != "GET")
                        {
                            parameters.Add(new ServiceAttributeParameterInfo("from", "query"));
                        }
                        if (fieldName != swaggerParameter.Name)
                        {
                            parameters.Add(new ServiceAttributeParameterInfo("name", swaggerParameter.Name));
                        }
                        if (parameters.Count != 0)
                        {
                            attributes.Add(new ServiceAttributeInfo("http", parameters));
                        }
                    }
                    else if (kind == SwaggerParameterKind.Header)
                    {
                        attributes.Add(new ServiceAttributeInfo("http",
                                                                new[]
                        {
                            new ServiceAttributeParameterInfo("from", "header"),
                            new ServiceAttributeParameterInfo("name", swaggerParameter.Name),
                        }));
                    }

                    requestFields.Add(new ServiceFieldInfo(
                                          fieldName,
                                          typeName: typeName,
                                          attributes: attributes,
                                          summary: PrepareSummary(swaggerParameter.Description),
                                          position: position));
                }
            }
            else if (kind == SwaggerParameterKind.Body)
            {
                var bodySchema = swaggerService.ResolveDefinition(swaggerParameter.Schema, position);
                if ((bodySchema.Value.Type ?? SwaggerSchemaType.Object) == SwaggerSchemaType.Object &&
                    (bodySchema.Key == null || bodySchema.Key.Equals(serviceMethodName + "Request", StringComparison.OrdinalIgnoreCase)))
                {
                    AddFieldsFromSchema(requestFields, swaggerService, position, bodySchema);
                }
                else
                {
                    string typeName = bodySchema.Key ?? SwaggerUtility.FilterBodyTypeName(swaggerService.TryGetFacilityTypeName(bodySchema.Value, position));
                    if (typeName != null)
                    {
                        requestFields.Add(new ServiceFieldInfo(
                                              bodySchema.Value.Identifier ?? "body",
                                              typeName: typeName,
                                              attributes: new[] { new ServiceAttributeInfo("http", new[] { new ServiceAttributeParameterInfo("from", "body", position) }) },
                                              summary: PrepareSummary(swaggerParameter.Description),
                                              position: position));
                    }
                }
            }
        }
Beispiel #17
0
        private void AddServiceMethod(IList <IServiceMemberInfo> members, string method, string path, SwaggerOperation swaggerOperation, IList <SwaggerParameter> swaggerOperationsParameters, SwaggerService swaggerService, SwaggerParserContext context)
        {
            if (swaggerOperation == null)
            {
                return;
            }

            var position = context.CreatePosition();

            path = s_pathParameter.Replace(path, match =>
            {
                string paramName = match.ToString().Substring(1, match.Length - 2);
                if (!ServiceDefinitionUtility.IsValidName(paramName))
                {
                    paramName = CodeGenUtility.ToCamelCase(paramName);
                }
                return($"{{{paramName}}}");
            });

            string name = CodeGenUtility.ToCamelCase(swaggerOperation.OperationId);

            if (!ServiceDefinitionUtility.IsValidName(name))
            {
                name = CodeGenUtility.ToCamelCase($"{method} {path}");
            }

            var httpAttributeValues = new List <ServiceAttributeParameterInfo>
            {
                new ServiceAttributeParameterInfo("method", method),
                new ServiceAttributeParameterInfo("path", path),
            };

            var requestFields = new List <ServiceFieldInfo>();

            foreach (var swaggerParameter in swaggerOperationsParameters.EmptyIfNull().Concat(swaggerOperation.Parameters.EmptyIfNull()))
            {
                AddRequestFields(requestFields, swaggerService.ResolveParameter(swaggerParameter, position), name, method, swaggerService, position);
            }

            var responseFields       = new List <ServiceFieldInfo>();
            var swaggerResponsePairs = swaggerOperation.Responses.EmptyIfNull()
                                       .Where(x => x.Key[0] == '2' || x.Key[0] == '3' || !string.IsNullOrEmpty(x.Value.Identifier)).ToList();

            foreach (var swaggerResponsePair in swaggerResponsePairs)
            {
                AddResponseFields(responseFields, swaggerResponsePair.Key, swaggerService.ResolveResponse(swaggerResponsePair.Value, position),
                                  name, httpAttributeValues, swaggerOperation.Responses.Count == 1, swaggerService, position);
            }

            var attributes = new List <ServiceAttributeInfo> {
                new ServiceAttributeInfo("http", httpAttributeValues)
            };

            if (swaggerOperation.Deprecated.GetValueOrDefault())
            {
                attributes.Add(new ServiceAttributeInfo("obsolete"));
            }

            members.Add(new ServiceMethodInfo(
                            name: name,
                            requestFields: requestFields,
                            responseFields: responseFields,
                            attributes: attributes,
                            summary: PrepareSummary(swaggerOperation.Summary),
                            remarks: SplitRemarks(swaggerOperation.Description),
                            position: position));
        }
Beispiel #18
0
        private ServiceInfo ConvertSwaggerService(SwaggerService swaggerService, SwaggerParserContext context)
        {
            if (swaggerService.Swagger == null)
            {
                throw context.CreateException("swagger field is missing.");
            }
            if (swaggerService.Swagger != SwaggerUtility.SwaggerVersion)
            {
                throw context.CreateException($"swagger should be '{SwaggerUtility.SwaggerVersion}'.", "swagger");
            }

            if (swaggerService.Info == null)
            {
                throw context.CreateException("info is missing.");
            }

            string name = ServiceName;

            if (name != null && !ServiceDefinitionUtility.IsValidName(name))
            {
                throw context.CreateException("ServiceName generator option is not a valid service name.");
            }
            if (name == null)
            {
                name = swaggerService.Info?.Identifier;
            }
            if (name != null && !ServiceDefinitionUtility.IsValidName(name))
            {
                throw context.CreateException("info/x-identifier is not a valid service name.", "info/x-identifier");
            }
            if (name == null)
            {
                name = CodeGenUtility.ToPascalCase(swaggerService.Info?.Title);
            }
            if (name == null)
            {
                throw context.CreateException("info/title is missing.", "info");
            }
            if (name != null && !ServiceDefinitionUtility.IsValidName(name))
            {
                throw context.CreateException("info/title is not a valid service name.", "info/title");
            }

            var attributes = new List <ServiceAttributeInfo>();

            string version = swaggerService.Info?.Version;

            if (!string.IsNullOrWhiteSpace(version))
            {
                attributes.Add(new ServiceAttributeInfo("info",
                                                        new[] { new ServiceAttributeParameterInfo("version", version, context.CreatePosition("info/version")) },
                                                        context.CreatePosition("info")));
            }

            string scheme   = GetBestScheme(swaggerService.Schemes);
            string host     = swaggerService.Host;
            string basePath = swaggerService.BasePath ?? "";

            if (!string.IsNullOrWhiteSpace(host) && !string.IsNullOrWhiteSpace(scheme))
            {
                string url = new UriBuilder(scheme, host)
                {
                    Path = basePath
                }.Uri.AbsoluteUri;
                attributes.Add(new ServiceAttributeInfo("http",
                                                        new[] { new ServiceAttributeParameterInfo("url", url, context.CreatePosition()) },
                                                        context.CreatePosition()));
            }

            var position = context.CreatePosition();

            var members = new List <IServiceMemberInfo>();

            foreach (var swaggerPath in swaggerService.Paths.EmptyIfNull())
            {
                var swaggerOperations = swaggerPath.Value;
                var operationsContext = context.CreateContext("paths/swaggerPath");
                swaggerService.ResolveOperations(ref swaggerOperations, ref operationsContext);
                AddServiceMethod(members, "GET", swaggerPath.Key, swaggerOperations.Get, swaggerOperations.Parameters, swaggerService, operationsContext.CreateContext("get"));
                AddServiceMethod(members, "POST", swaggerPath.Key, swaggerOperations.Post, swaggerOperations.Parameters, swaggerService, operationsContext.CreateContext("post"));
                AddServiceMethod(members, "PUT", swaggerPath.Key, swaggerOperations.Put, swaggerOperations.Parameters, swaggerService, operationsContext.CreateContext("put"));
                AddServiceMethod(members, "DELETE", swaggerPath.Key, swaggerOperations.Delete, swaggerOperations.Parameters, swaggerService, operationsContext.CreateContext("delete"));
                AddServiceMethod(members, "OPTIONS", swaggerPath.Key, swaggerOperations.Options, swaggerOperations.Parameters, swaggerService, operationsContext.CreateContext("options"));
                AddServiceMethod(members, "HEAD", swaggerPath.Key, swaggerOperations.Head, swaggerOperations.Parameters, swaggerService, operationsContext.CreateContext("head"));
                AddServiceMethod(members, "PATCH", swaggerPath.Key, swaggerOperations.Patch, swaggerOperations.Parameters, swaggerService, operationsContext.CreateContext("patch"));
            }

            foreach (var swaggerDefinition in swaggerService.Definitions.EmptyIfNull())
            {
                if ((swaggerDefinition.Value.Type ?? SwaggerSchemaType.Object) == SwaggerSchemaType.Object &&
                    !members.OfType <ServiceMethodInfo>().Any(x => swaggerDefinition.Key.Equals(x.Name + "Request", StringComparison.OrdinalIgnoreCase)) &&
                    !members.OfType <ServiceMethodInfo>().Any(x => swaggerDefinition.Key.Equals(x.Name + "Response", StringComparison.OrdinalIgnoreCase)) &&
                    !swaggerService.IsFacilityError(swaggerDefinition) &&
                    swaggerService.TryGetFacilityResultOfType(swaggerDefinition, position) == null)
                {
                    AddServiceDto(members, swaggerDefinition.Key, swaggerDefinition.Value, swaggerService, context.CreatePosition("definitions/" + swaggerDefinition.Key));
                }
            }

            return(new ServiceInfo(name, members: members, attributes: attributes,
                                   summary: PrepareSummary(swaggerService.Info?.Title),
                                   remarks: SplitRemarks(swaggerService.Info?.Description),
                                   position: context.CreatePosition()));
        }
Beispiel #19
0
 public static void WriteFileHeader(CodeWriter code, string generatorName)
 {
     code.WriteLine("// <auto-generated>");
     code.WriteLine("// " + CodeGenUtility.GetCodeGenComment(generatorName));
     code.WriteLine("// </auto-generated>");
 }
 public void Uncapitalize(string before, string after)
 {
     CodeGenUtility.Uncapitalize(before).Should().Be(after);
 }
Beispiel #21
0
 public static string GetInterfaceName(ServiceInfo serviceInfo) => $"I{CodeGenUtility.Capitalize(serviceInfo.Name)}";
 public void PascalCase(string before, string after)
 {
     CodeGenUtility.ToPascalCase(before).Should().Be(after);
 }
Beispiel #23
0
 public static string GetDtoName(ServiceDtoInfo dtoInfo) => CodeGenUtility.Capitalize(dtoInfo.Name) + "Dto";
Beispiel #24
0
        /// <summary>
        /// Generates Swagger (OpenAPI 2.0) for a service definition.
        /// </summary>
        public SwaggerService GenerateSwaggerService(ServiceInfo service)
        {
            var httpServiceInfo = HttpServiceInfo.Create(service);

            var swaggerService = new SwaggerService
            {
                Swagger = SwaggerUtility.SwaggerVersion,
                Info    = new SwaggerInfo
                {
                    Identifier  = service.Name,
                    Title       = GetSummaryOrNull(service) ?? service.Name,
                    Description = GetRemarksOrNull(service),
                    Version     = service.TryGetAttribute("info")?.TryGetParameterValue("version") ?? "0.0.0",
                    CodeGen     = CodeGenUtility.GetCodeGenComment(GeneratorName ?? ""),
                },
            };

            var defaultBaseUri = httpServiceInfo.Url;

            if (defaultBaseUri != null)
            {
                var baseUri = new Uri(defaultBaseUri);
                swaggerService.Host    = baseUri.Host;
                swaggerService.Schemes = new[] { baseUri.Scheme };

                string basePath = baseUri.PathAndQuery;
                if (!string.IsNullOrEmpty(basePath) && basePath != "/")
                {
                    swaggerService.BasePath = baseUri.PathAndQuery;
                }
            }

            var paths = new OurDictionary <string, SwaggerOperations>();

            foreach (var httpMethodInfo in httpServiceInfo.Methods)
            {
                AddMethodToPaths(paths, service, httpMethodInfo);
            }
            swaggerService.Paths = paths;

            var dtoInfos = new OurDictionary <string, ServiceDtoInfo>();

            foreach (var httpMethodInfo in httpServiceInfo.Methods)
            {
                if (httpMethodInfo.RequestBodyField != null)
                {
                    AddDtos(dtoInfos, GetDtosForType(service.GetFieldType(httpMethodInfo.RequestBodyField.ServiceField) !));
                }

                AddDto(dtoInfos, TryCreateMethodRequestBodyType(httpMethodInfo)?.Dto);

                foreach (var httpResponseInfo in httpMethodInfo.ValidResponses)
                {
                    if (httpResponseInfo.BodyField != null)
                    {
                        AddDtos(dtoInfos, GetDtosForType(service.GetFieldType(httpResponseInfo.BodyField.ServiceField) !));
                    }

                    AddDto(dtoInfos, TryCreateMethodResponseBodyType(httpMethodInfo, httpResponseInfo)?.Dto);
                }
            }

            while (true)
            {
                var dtoCount = dtoInfos.Count;
                foreach (var field in dtoInfos.Values.SelectMany(x => x.Fields).ToList())
                {
                    AddDtos(dtoInfos, GetDtosForType(service.GetFieldType(field) !));
                }
                if (dtoCount == dtoInfos.Count)
                {
                    break;
                }
            }

            var definitions = new OurDictionary <string, SwaggerSchema>();

            foreach (var dtoInfo in dtoInfos.Values)
            {
                definitions[dtoInfo.Name] = GetDtoSchema(service, dtoInfo);
            }
            swaggerService.Definitions = definitions.Count == 0 ? null : definitions;

            return(swaggerService);
        }
Beispiel #25
0
 public static string GetEnumName(ServiceEnumInfo enumInfo) => CodeGenUtility.Capitalize(enumInfo.Name);
    /// <summary>
    /// Generates the Markdown.
    /// </summary>
    public override CodeGenOutput GenerateOutput(ServiceInfo service)
    {
        var httpServiceInfo = NoHttp ? null : HttpServiceInfo.Create(service);

        var template = CodeGenTemplate.Parse(TemplateText ?? GetEmbeddedResourceText("Facility.CodeGen.Markdown.template.scriban-txt"));
        var globals  = CodeGenGlobals.Create(new MarkdownGeneratorGlobals(this, service, httpServiceInfo));
        var files    = template.Generate(globals, new CodeGenSettings {
            NewLine = NewLine, IndentText = IndentText
        });

        return(new CodeGenOutput(
                   files: files.Select(x => new CodeGenFile(x.Name, x.Text)).ToList(),
                   patternsToClean: new[] { new CodeGenPattern($"{service.Name}/*.md", CodeGenUtility.GetCodeGenComment(GeneratorName ?? "")) }));
    }
Beispiel #27
0
 public static string GetErrorName(ServiceErrorInfo errorInfo) => CodeGenUtility.Capitalize(errorInfo.Name);
Beispiel #28
0
        /// <summary>
        /// Generates the C# output.
        /// </summary>
        protected override CodeGenOutput GenerateOutputCore(ServiceInfo service)
        {
            var httpServiceInfo = HttpServiceInfo.Create(service);

            string moduleName     = ModuleName ?? service.Name;
            string capModuleName  = CodeGenUtility.Capitalize(moduleName);
            string typesFileName  = Uncapitalize(moduleName) + "Types" + (TypeScript ? ".ts" : ".js");
            string clientFileName = Uncapitalize(moduleName) + (TypeScript ? ".ts" : ".js");
            string serverFileName = Uncapitalize(moduleName) + "Server" + (TypeScript ? ".ts" : ".js");

            var namedTexts = new List <CodeGenFile>();
            var typeNames  = new List <string>();

            if (TypeScript)
            {
                namedTexts.Add(CreateFile(typesFileName, code =>
                {
                    code.WriteLine($"// DO NOT EDIT: generated by {GeneratorName}");

                    code.WriteLine();
                    code.WriteLine("import { IServiceResult, IServiceError } from 'facility-core';");

                    code.WriteLine();
                    WriteJsDoc(code, service);
                    typeNames.Add($"I{capModuleName}");
                    using (code.Block($"export interface I{capModuleName} {{", "}"))
                    {
                        foreach (var httpMethodInfo in httpServiceInfo.Methods)
                        {
                            string methodName    = httpMethodInfo.ServiceMethod.Name;
                            string capMethodName = CodeGenUtility.Capitalize(methodName);
                            code.WriteLineSkipOnce();
                            WriteJsDoc(code, httpMethodInfo.ServiceMethod);
                            code.WriteLine($"{methodName}(request: I{capMethodName}Request): Promise<IServiceResult<I{capMethodName}Response>>;");
                        }
                    }

                    foreach (var methodInfo in service.Methods)
                    {
                        var requestDtoName = $"{CodeGenUtility.Capitalize(methodInfo.Name)}Request";
                        typeNames.Add($"I{requestDtoName}");
                        WriteDto(code, new ServiceDtoInfo(
                                     name: requestDtoName,
                                     fields: methodInfo.RequestFields,
                                     summary: $"Request for {CodeGenUtility.Capitalize(methodInfo.Name)}."), service);

                        var responseDtoName = $"{CodeGenUtility.Capitalize(methodInfo.Name)}Response";
                        typeNames.Add($"I{responseDtoName}");
                        WriteDto(code, new ServiceDtoInfo(
                                     name: responseDtoName,
                                     fields: methodInfo.ResponseFields,
                                     summary: $"Response for {CodeGenUtility.Capitalize(methodInfo.Name)}."), service);
                    }

                    foreach (var dtoInfo in service.Dtos)
                    {
                        typeNames.Add($"I{dtoInfo.Name}");
                        WriteDto(code, dtoInfo, service);
                    }
                    code.WriteLine();
                }));
            }


            namedTexts.Add(CreateFile(clientFileName, code =>
            {
                code.WriteLine($"// DO NOT EDIT: generated by {GeneratorName}");

                if (!TypeScript)
                {
                    code.WriteLine("'use strict';");
                }

                code.WriteLine();
                code.WriteLine("import { HttpClientUtility" + IfTypeScript(", IServiceResult, IServiceError, IHttpClientOptions") + " } from 'facility-core';");
                if (TypeScript)
                {
                    code.WriteLine($"import {{ {string.Join(", ", typeNames)} }} from './{Uncapitalize(moduleName)}Types';");
                    code.WriteLine($"export * from './{Uncapitalize(moduleName)}Types';");
                }

                code.WriteLine();
                WriteJsDoc(code, $"Provides access to {capModuleName} over HTTP via fetch.");
                using (code.Block("export function createHttpClient({ fetch, baseUri }" + IfTypeScript(": IHttpClientOptions") + ")" + IfTypeScript($": I{capModuleName}") + " {", "}"))
                    code.WriteLine($"return new {capModuleName}HttpClient(fetch, baseUri);");

                code.WriteLine();
                code.WriteLine("const { fetchResponse, createResponseError, createRequiredRequestFieldError } = HttpClientUtility;");
                if (TypeScript)
                {
                    code.WriteLine("type IFetch = HttpClientUtility.IFetch;");
                    code.WriteLine("type IFetchRequest = HttpClientUtility.IFetchRequest;");
                }

                code.WriteLine();
                using (code.Block($"class {capModuleName}HttpClient" + IfTypeScript($" implements I{capModuleName}") + " {", "}"))
                {
                    using (code.Block("constructor(fetch" + IfTypeScript(": IFetch") + ", baseUri" + IfTypeScript("?: string") + ") {", "}"))
                    {
                        using (code.Block("if (typeof fetch !== 'function') {", "}"))
                            code.WriteLine("throw new TypeError('fetch must be a function.');");
                        using (code.Block("if (typeof baseUri === 'undefined') {", "}"))
                            code.WriteLine($"baseUri = '{httpServiceInfo.Url ?? ""}';");
                        using (code.Block(@"if (/[^\/]$/.test(baseUri)) {", "}"))
                            code.WriteLine("baseUri += '/';");

                        code.WriteLine("this._fetch = fetch;");
                        code.WriteLine("this._baseUri = baseUri;");
                    }

                    foreach (var httpMethodInfo in httpServiceInfo.Methods)
                    {
                        string methodName    = httpMethodInfo.ServiceMethod.Name;
                        string capMethodName = CodeGenUtility.Capitalize(methodName);

                        code.WriteLine();
                        WriteJsDoc(code, httpMethodInfo.ServiceMethod);
                        using (code.Block(IfTypeScript("public ") + $"{methodName}(request" + IfTypeScript($": I{capMethodName}Request") + ")" + IfTypeScript($": Promise<IServiceResult<I{capMethodName}Response>>") + " {", "}"))
                        {
                            bool hasPathFields = httpMethodInfo.PathFields.Count != 0;
                            string jsUriDelim  = hasPathFields ? "`" : "'";
                            string jsUri       = jsUriDelim + httpMethodInfo.Path.Substring(1) + jsUriDelim;
                            if (hasPathFields)
                            {
                                foreach (var httpPathField in httpMethodInfo.PathFields)
                                {
                                    code.WriteLine($"const uriPart{CodeGenUtility.Capitalize(httpPathField.ServiceField.Name)} = request.{httpPathField.ServiceField.Name} != null && {RenderUriComponent(httpPathField.ServiceField, service)};");
                                    using (code.Block($"if (!uriPart{CodeGenUtility.Capitalize(httpPathField.ServiceField.Name)}) {{", "}"))
                                        code.WriteLine($"return Promise.resolve(createRequiredRequestFieldError('{httpPathField.ServiceField.Name}'));");
                                }
                                foreach (var httpPathField in httpMethodInfo.PathFields)
                                {
                                    jsUri = jsUri.Replace("{" + httpPathField.Name + "}", $"${{uriPart{CodeGenUtility.Capitalize(httpPathField.ServiceField.Name)}}}");
                                }
                            }

                            bool hasQueryFields = httpMethodInfo.QueryFields.Count != 0;
                            code.WriteLine((hasQueryFields ? "let" : "const") + $" uri = {jsUri};");
                            if (hasQueryFields)
                            {
                                code.WriteLine("const query" + IfTypeScript(": string[]") + " = [];");
                                foreach (var httpQueryField in httpMethodInfo.QueryFields)
                                {
                                    code.WriteLine($"request.{httpQueryField.ServiceField.Name} == null || query.push('{httpQueryField.Name}=' + {RenderUriComponent(httpQueryField.ServiceField, service)});");
                                }
                                using (code.Block("if (query.length) {", "}"))
                                    code.WriteLine("uri = uri + '?' + query.join('&');");
                            }

                            using (code.Block("const fetchRequest" + IfTypeScript(": IFetchRequest") + " = {", "};"))
                            {
                                if (httpMethodInfo.RequestBodyField == null && httpMethodInfo.RequestNormalFields.Count == 0)
                                {
                                    code.WriteLine($"method: '{httpMethodInfo.Method}',");
                                    if (httpMethodInfo.RequestHeaderFields.Count != 0)
                                    {
                                        code.WriteLine("headers: {},");
                                    }
                                }
                                else
                                {
                                    code.WriteLine($"method: '{httpMethodInfo.Method}',");
                                    code.WriteLine("headers: { 'Content-Type': 'application/json' },");

                                    if (httpMethodInfo.RequestBodyField != null)
                                    {
                                        code.WriteLine($"body: JSON.stringify(request.{httpMethodInfo.RequestBodyField.ServiceField.Name})");
                                    }
                                    else if (httpMethodInfo.ServiceMethod.RequestFields.Count == httpMethodInfo.RequestNormalFields.Count)
                                    {
                                        code.WriteLine("body: JSON.stringify(request)");
                                    }
                                    else
                                    {
                                        using (code.Block("body: JSON.stringify({", "})"))
                                        {
                                            for (int httpFieldIndex = 0; httpFieldIndex < httpMethodInfo.RequestNormalFields.Count; httpFieldIndex++)
                                            {
                                                var httpFieldInfo = httpMethodInfo.RequestNormalFields[httpFieldIndex];
                                                bool isLastField  = httpFieldIndex == httpMethodInfo.RequestNormalFields.Count - 1;
                                                string fieldName  = httpFieldInfo.ServiceField.Name;
                                                code.WriteLine(fieldName + ": request." + fieldName + (isLastField ? "" : ","));
                                            }
                                        }
                                    }
                                }
                            }

                            if (httpMethodInfo.RequestHeaderFields.Count != 0)
                            {
                                foreach (var httpHeaderField in httpMethodInfo.RequestHeaderFields)
                                {
                                    using (code.Block($"if (request.{httpHeaderField.ServiceField.Name} != null) {{", "}"))
                                        code.WriteLine($"fetchRequest.headers['{httpHeaderField.Name}'] = request.{httpHeaderField.ServiceField.Name};");
                                }
                            }

                            code.WriteLine("return fetchResponse(this._fetch, this._baseUri + uri, fetchRequest)");
                            using (code.Indent())
                                using (code.Block(".then(result => {", "});"))
                                {
                                    code.WriteLine("const status = result.response.status;");
                                    code.WriteLine("let value" + IfTypeScript($": I{capMethodName}Response | null") + " = null;");
                                    using (code.Block("if (result.json) {", "}"))
                                    {
                                        var validResponses = httpMethodInfo.ValidResponses;
                                        string elsePrefix  = "";
                                        foreach (var validResponse in validResponses)
                                        {
                                            string statusCodeAsString = ((int)validResponse.StatusCode).ToString(CultureInfo.InvariantCulture);
                                            code.WriteLine($"{elsePrefix}if (status === {statusCodeAsString}) {{");
                                            elsePrefix = "else ";

                                            using (code.Indent())
                                            {
                                                var bodyField = validResponse.BodyField;
                                                if (bodyField != null)
                                                {
                                                    string responseBodyFieldName = bodyField.ServiceField.Name;

                                                    var bodyFieldType = service.GetFieldType(bodyField.ServiceField);
                                                    if (bodyFieldType.Kind == ServiceTypeKind.Boolean)
                                                    {
                                                        code.WriteLine($"value = {{ {responseBodyFieldName}: true }};");
                                                    }
                                                    else
                                                    {
                                                        code.WriteLine($"value = {{ {responseBodyFieldName}: result.json }};");
                                                    }
                                                }
                                                else
                                                {
                                                    if (validResponse.NormalFields.Count == 0)
                                                    {
                                                        code.WriteLine("value = {};");
                                                    }
                                                    else
                                                    {
                                                        code.WriteLine("value = result.json;");
                                                    }
                                                }
                                            }
                                            code.WriteLine("}");
                                        }
                                    }

                                    using (code.Block("if (!value) {", "}"))
                                        code.WriteLine("return createResponseError(status, result.json)" + IfTypeScript($" as IServiceResult<I{capMethodName}Response>") + ";");

                                    if (httpMethodInfo.ResponseHeaderFields.Count != 0)
                                    {
                                        code.WriteLine("let headerValue" + IfTypeScript(": string | null | undefined") + ";");
                                        foreach (var httpHeaderField in httpMethodInfo.ResponseHeaderFields)
                                        {
                                            code.WriteLine($"headerValue = result.response.headers.get('{httpHeaderField.Name}');");
                                            using (code.Block("if (headerValue != null) {", "}"))
                                                code.WriteLine($"value.{httpHeaderField.Name} = headerValue;");
                                        }
                                    }

                                    code.WriteLine("return { value: value };");
                                }
                        }
                    }

                    if (TypeScript)
                    {
                        code.WriteLine();
                        code.WriteLine("private _fetch: IFetch;");
                        code.WriteLine("private _baseUri: string;");
                    }
                }
            }));

            if (Express)
            {
                namedTexts.Add(CreateFile(serverFileName, code =>
                {
                    code.WriteLine($"// DO NOT EDIT: generated by {GeneratorName}");

                    if (!TypeScript)
                    {
                        code.WriteLine("'use strict';");
                    }

                    code.WriteLine();
                    code.WriteLine("import * as bodyParser from 'body-parser';");
                    code.WriteLine("import * as express from 'express';");
                    code.WriteLine("import {" + IfTypeScript(" IServiceResult, IServiceError") + " } from 'facility-core';");
                    if (TypeScript)
                    {
                        code.WriteLine($"import {{ {string.Join(", ", typeNames)} }} from './{Uncapitalize(moduleName)}Types';");
                        code.WriteLine($"export * from './{Uncapitalize(moduleName)}Types';");
                    }

                    // TODO: export this from facility-core
                    code.WriteLine();
                    using (code.Block("const standardErrorCodes" + IfTypeScript(": { [code: string]: number }") + " = {", "};"))
                    {
                        code.WriteLine("'notModified': 304,");
                        code.WriteLine("'invalidRequest': 400,");
                        code.WriteLine("'notAuthenticated': 401,");
                        code.WriteLine("'notAuthorized': 403,");
                        code.WriteLine("'notFound': 404,");
                        code.WriteLine("'conflict': 409,");
                        code.WriteLine("'requestTooLarge': 413,");
                        code.WriteLine("'tooManyRequests': 429,");
                        code.WriteLine("'internalError': 500,");
                        code.WriteLine("'serviceUnavailable': 503,");
                    }

                    code.WriteLine();
                    using (code.Block("function parseBoolean(value" + IfTypeScript(": string | undefined") + ") {", "}"))
                    {
                        using (code.Block("if (typeof value === 'string') {", "}"))
                        {
                            code.WriteLine("const lowerValue = value.toLowerCase();");
                            using (code.Block("if (lowerValue === 'true') {", "}"))
                                code.WriteLine("return true;");
                            using (code.Block("if (lowerValue === 'false') {", "}"))
                                code.WriteLine("return false;");
                        }
                        code.WriteLine("return undefined;");
                    }

                    code.WriteLine();
                    using (code.Block("export function createApp(service" + IfTypeScript($": I{capModuleName}") + ", middleware" + IfTypeScript(": ((...args: any[]) => void)[]") + ")" + IfTypeScript(": express.Application") + " {", "}"))
                    {
                        code.WriteLine("const app = express();");
                        code.WriteLine("app.use(bodyParser.json());");
                        code.WriteLine("app.use(bodyParser.urlencoded({ extended: true }));");
                        code.WriteLine("middleware.forEach(func => app.use(func));");

                        foreach (var httpMethodInfo in httpServiceInfo.Methods)
                        {
                            string methodName    = httpMethodInfo.ServiceMethod.Name;
                            string capMethodName = CodeGenUtility.Capitalize(methodName);
                            string expressMethod = httpMethodInfo.Method.ToLowerInvariant();
                            string expressPath   = httpMethodInfo.Path;
                            foreach (var httpPathField in httpMethodInfo.PathFields)
                            {
                                expressPath = expressPath.Replace("{" + httpPathField.Name + "}", $":{httpPathField.Name}");
                            }

                            code.WriteLine();
                            WriteJsDoc(code, httpMethodInfo.ServiceMethod);
                            using (code.Block($"app.{expressMethod}('{expressPath}', function (req, res, next) {{", "});"))
                            {
                                code.WriteLine("const request" + IfTypeScript($": I{capMethodName}Request") + " = {};");

                                foreach (var httpPathField in httpMethodInfo.PathFields)
                                {
                                    code.WriteLine($"request.{httpPathField.ServiceField.Name} = {RenderJsConversion(httpPathField.ServiceField, service, $"req.params.{httpPathField.Name}")};");
                                }

                                foreach (var httpQueryField in httpMethodInfo.QueryFields)
                                {
                                    using (code.Block($"if (req.query['{httpQueryField.Name}'] != null) {{", "}"))
                                        code.WriteLine($"request.{httpQueryField.ServiceField.Name} = {RenderJsConversion(httpQueryField.ServiceField, service, $"req.query['{httpQueryField.Name}']")};");
                                }

                                if (httpMethodInfo.RequestBodyField != null)
                                {
                                    code.WriteLine($"request.{httpMethodInfo.RequestBodyField.ServiceField.Name} = req.body;");
                                }
                                else if (httpMethodInfo.RequestNormalFields != null)
                                {
                                    foreach (var field in httpMethodInfo.RequestNormalFields)
                                    {
                                        code.WriteLine($"request.{field.ServiceField.Name} = req.body.{field.ServiceField.Name};");
                                    }
                                }

                                if (httpMethodInfo.RequestHeaderFields != null)
                                {
                                    foreach (var field in httpMethodInfo.RequestHeaderFields)
                                    {
                                        code.WriteLine($"request.{field.ServiceField.Name} = req.header('{field.Name}');");
                                    }
                                }

                                code.WriteLine();
                                code.WriteLine($"return service.{methodName}(request)");

                                using (code.Indent())
                                {
                                    using (code.Block(".then(result => {", "})"))
                                    {
                                        using (code.Block("if (result.error) {", "}"))
                                        {
                                            code.WriteLine("const status = result.error.code && standardErrorCodes[result.error.code] || 500;");
                                            code.WriteLine("res.status(status).send(result.error);");
                                            code.WriteLine("return;");
                                        }
                                        using (code.Block("if (result.value) {", "}"))
                                        {
                                            if (httpMethodInfo.ResponseHeaderFields != null)
                                            {
                                                foreach (var field in httpMethodInfo.ResponseHeaderFields)
                                                {
                                                    using (code.Block($"if (result.value.{field.ServiceField.Name} != null) {{", "}"))
                                                        code.WriteLine($"res.setHeader('{field.Name}', result.value.{field.ServiceField.Name});");
                                                }
                                            }

                                            foreach (var validResponse in httpMethodInfo.ValidResponses.Where(x => x.NormalFields == null || x.NormalFields.Count == 0))
                                            {
                                                var bodyField = validResponse.BodyField;
                                                if (bodyField != null)
                                                {
                                                    string responseBodyFieldName = bodyField.ServiceField.Name;

                                                    using (code.Block($"if (result.value.{responseBodyFieldName}) {{", "}"))
                                                    {
                                                        var bodyFieldType = service.GetFieldType(bodyField.ServiceField);
                                                        if (bodyFieldType.Kind == ServiceTypeKind.Boolean)
                                                        {
                                                            code.WriteLine($"res.sendStatus({(int) validResponse.StatusCode});");
                                                            code.WriteLine("return;");
                                                        }
                                                        else
                                                        {
                                                            code.WriteLine($"res.status({(int) validResponse.StatusCode}).send(result.value.{responseBodyFieldName});");
                                                            code.WriteLine("return;");
                                                        }
                                                    }
                                                }
                                                else
                                                {
                                                    if (validResponse.NormalFields.Count == 0)
                                                    {
                                                        code.WriteLine($"res.sendStatus({(int) validResponse.StatusCode});");
                                                        code.WriteLine("return;");
                                                    }
                                                }
                                            }

                                            foreach (var validResponse in httpMethodInfo.ValidResponses.Where(x => x.NormalFields != null && x.NormalFields.Count != 0))
                                            {
                                                code.WriteLine($"res.status({(int) validResponse.StatusCode}).send({{");
                                                using (code.Indent())
                                                {
                                                    foreach (var field in validResponse.NormalFields)
                                                    {
                                                        code.WriteLine($"{field.ServiceField.Name}: result.value.{field.ServiceField.Name},");
                                                    }
                                                }
                                                code.WriteLine("});");
                                                code.WriteLine("return;");
                                            }
                                        }

                                        code.WriteLine("throw new Error('Result must have an error or value.');");
                                    }
                                    code.WriteLine(".catch(next);");
                                }
                            }
                        }

                        code.WriteLine();
                        code.WriteLine("return app;");
                    }
                }));
            }

            return(new CodeGenOutput(namedTexts, new List <CodeGenPattern>()));
        }
 public void SnakeCase(string before, string after)
 {
     CodeGenUtility.ToSnakeCase(before).Should().Be(after);
 }
 /// <summary>
 /// Gets the property name for the specified field.
 /// </summary>
 public string GetFieldPropertyName(ServiceFieldInfo field) =>
 m_fieldPropertyNames.TryGetValue(field, out var value) ? value : CodeGenUtility.Capitalize(field.Name);