public OpenApiOutputModel Compile(OpenApiConfiguration configuration, IReadOnlyCollection <AbstractFunctionDefinition> abstractFunctionDefinitions, string outputBinaryFolder) { if (configuration == null) { return(null); } string apiPrefix = GetApiPrefix(outputBinaryFolder); if (!configuration.IsValid) { throw new ConfigurationException("Open API implementation is partially complete, a title and a version must be specified"); } if (!configuration.IsOpenApiOutputEnabled) { return(null); } HttpFunctionDefinition[] functionDefinitions = abstractFunctionDefinitions.OfType <HttpFunctionDefinition>().ToArray(); if (functionDefinitions.Length == 0) { return(null); } OpenApiDocument openApiDocument = new OpenApiDocument { Info = new OpenApiInfo { Version = configuration.Version, Title = configuration.Title }, Servers = configuration.Servers?.Select(x => new OpenApiServer { Url = x }).ToArray(), Paths = new OpenApiPaths(), Components = new OpenApiComponents { Schemas = new Dictionary <string, OpenApiSchema>() } }; var compilerConfiguration = new OpenApiCompilerConfiguration(configuration); SchemaReferenceRegistry registry = new SchemaReferenceRegistry(compilerConfiguration); CreateTags(functionDefinitions, openApiDocument); CreateSchemas(functionDefinitions, openApiDocument, registry); CreateOperationsFromRoutes(functionDefinitions, openApiDocument, registry, apiPrefix, compilerConfiguration); FilterDocument(compilerConfiguration, openApiDocument); if (openApiDocument.Paths.Count == 0) { return(null); } string yaml = openApiDocument.Serialize(OpenApiSpecVersion.OpenApi3_0, OpenApiFormat.Yaml); OpenApiOutputModel result = new OpenApiOutputModel { OpenApiSpecification = new OpenApiFileReference { Content = yaml, Filename = "openapi.yaml" } }; if (!string.IsNullOrWhiteSpace(configuration.UserInterfaceRoute)) { result.SwaggerUserInterface = CopySwaggerUserInterfaceFilesToWebFolder(); } if (!string.IsNullOrWhiteSpace(configuration.OutputPath)) { if (Directory.Exists(configuration.OutputPath)) { string pathAndFilename = Path.Combine(configuration.OutputPath, "openapi.yaml"); if (File.Exists(pathAndFilename)) { File.Delete(pathAndFilename); } File.WriteAllText(pathAndFilename, yaml, Encoding.UTF8); } } return(result); }
public OpenApiOutputModel Compile(OpenApiConfiguration configuration, IReadOnlyCollection <AbstractFunctionDefinition> abstractFunctionDefinitions, string outputBinaryFolder) { if (configuration == null) { return(null); } string apiPrefix = GetApiPrefix(outputBinaryFolder); if (!configuration.IsValid) { throw new ConfigurationException("Open API implementation is partially complete, a title and a version must be specified"); } if (!configuration.IsOpenApiOutputEnabled) { return(null); } var functionDefinitions = abstractFunctionDefinitions.OfType <HttpFunctionDefinition>().ToList(); if (functionDefinitions.Count() == 0) { return(null); } IDictionary <string, OpenApiDocumentsSpec> openApiDocumentsSpec = new Dictionary <string, OpenApiDocumentsSpec>(); IDictionary <string, OpenApiDocumentsSpec> reDocDocumentsSpec = new Dictionary <string, OpenApiDocumentsSpec>(); OpenApiOutputModel outputModel = new OpenApiOutputModel(); foreach (var keyValuePair in configuration.OpenApiDocumentInfos) { OpenApiDocument openApiDocument = new OpenApiDocument { Info = keyValuePair.Value.OpenApiInfo, Servers = configuration.Servers?.Select(x => new OpenApiServer { Url = x }).ToArray(), Paths = new OpenApiPaths(), Components = new OpenApiComponents { Schemas = new Dictionary <string, OpenApiSchema>(), } }; var functionFilter = keyValuePair.Value.HttpFunctionFilter; if (functionFilter == null) { functionFilter = new OpenApiHttpFunctionFilterDummy(); } var compilerConfiguration = new OpenApiCompilerConfiguration(configuration); SchemaReferenceRegistry registry = new SchemaReferenceRegistry(compilerConfiguration); CreateTags(functionDefinitions, functionFilter, openApiDocument); CreateSchemas(functionDefinitions, functionFilter, openApiDocument, registry); CreateOperationsFromRoutes(functionDefinitions, functionFilter, openApiDocument, registry, apiPrefix, compilerConfiguration); CreateSecuritySchemes(openApiDocument, configuration); FilterDocument(compilerConfiguration.DocumentFilters, openApiDocument, keyValuePair.Value.DocumentRoute); if (openApiDocument.Paths.Count == 0) { continue; } // TODO: FIXME: // Hack: Empty OpenApiSecurityRequirement lists are not serialized by the standard Microsoft // implementation. Therefore we add a null object to the list and fix it here by hand. var yaml = openApiDocument.Serialize(OpenApiSpecVersion.OpenApi3_0, OpenApiFormat.Yaml); yaml = Regex.Replace(yaml, $"security:\n.*?- \n", "security: []\n"); outputModel.OpenApiFileReferences.Add( new OpenApiFileReference { Filename = $"OpenApi.{keyValuePair.Value.DocumentRoute.Replace('/', '.')}", Content = Encoding.UTF8.GetBytes(yaml) } ); openApiDocumentsSpec.Add(openApiDocument.Info.Title, new OpenApiDocumentsSpec { Title = keyValuePair.Value.OpenApiInfo.Title, Selected = keyValuePair.Value.Selected, Path = $"/{configuration.UserInterfaceRoute ?? "openapi"}/{keyValuePair.Value.DocumentRoute}" }); // Create reDoc YAML if (!string.IsNullOrWhiteSpace(configuration.ReDocUserInterfaceRoute)) { FilterDocument(compilerConfiguration.ReDocDocumentFilters, openApiDocument, keyValuePair.Value.DocumentRoute); // TODO: FIXME: // Hack: Empty OpenApiSecurityRequirement lists are not serialized by the standard Microsoft // implementation. Therefore we add a null object to the list and fix it here by hand. var reDocYaml = openApiDocument.Serialize(OpenApiSpecVersion.OpenApi3_0, OpenApiFormat.Yaml); reDocYaml = Regex.Replace(reDocYaml, $"security:\n.*?- \n", "security: []\n"); outputModel.OpenApiFileReferences.Add( new OpenApiFileReference { Filename = $"ReDoc.{keyValuePair.Value.DocumentRoute.Replace('/', '.')}", Content = Encoding.UTF8.GetBytes(reDocYaml) } ); reDocDocumentsSpec.Add(openApiDocument.Info.Title, new OpenApiDocumentsSpec { Title = keyValuePair.Value.OpenApiInfo.Title, Selected = keyValuePair.Value.Selected, Path = $"/{configuration.ReDocUserInterfaceRoute ?? "redoc"}/{keyValuePair.Value.DocumentRoute}" }); } } if (!string.IsNullOrWhiteSpace(configuration.UserInterfaceRoute)) { outputModel.OpenApiFileReferences.Add( new OpenApiFileReference { Filename = "OpenApi.openapi-documents-spec.json", Content = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(openApiDocumentsSpec.Values.ToArray())) } ); CopySwaggerUserInterfaceFilesToWebFolder(configuration, outputModel.OpenApiFileReferences); } if (!string.IsNullOrWhiteSpace(configuration.ReDocUserInterfaceRoute)) { outputModel.OpenApiFileReferences.Add( new OpenApiFileReference { Filename = "ReDoc.redoc-documents-spec.json", Content = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(reDocDocumentsSpec.Values.ToArray())) } ); CopyReDocUserInterfaceFilesToWebFolder(configuration, outputModel.OpenApiFileReferences); } outputModel.UserInterfaceRoute = configuration.UserInterfaceRoute; outputModel.ReDocUserInterfaceRoute = configuration.ReDocUserInterfaceRoute; return(outputModel); }