diff --git a/CHANGELOG.md b/CHANGELOG.md index 16b5a8ec98..c766fd0c98 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed +- Fixed RPC server to respect the `KIOTA_CONFIG_PREVIEW` flag. + ## [1.14.0] - 2024-05-02 ### Added @@ -30,7 +32,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Fixes request builder disambiguation when child nodes had different prefixes for different paths with same parameters.[#4448](https://github.com/microsoft/kiota/issues/4448) - Do not generate CS8603 warnings when enabling backing store in CSharp generation. - Fixed excluding operation. [#4399](https://github.com/microsoft/kiota/issues/4399) -- Fided a bug where absolute path would be used for workspace for local descriptions. [#4582](https://github.com/microsoft/kiota/issues/4582) [#4581](https://github.com/microsoft/kiota/issues/4581) +- Fixed a bug where absolute path would be used for workspace for local descriptions. [#4582](https://github.com/microsoft/kiota/issues/4582) [#4581](https://github.com/microsoft/kiota/issues/4581) - Fixed plugin generation of `ApiManifest` type to not include the `x-ms-kiota-hash` in the generated plugin. [#4561](https://github.com/microsoft/kiota/issues/4561) ## [1.13.0] - 2024-04-04 diff --git a/src/kiota/KiotaHost.cs b/src/kiota/KiotaHost.cs index 5923772de7..8dda187bf3 100644 --- a/src/kiota/KiotaHost.cs +++ b/src/kiota/KiotaHost.cs @@ -11,7 +11,8 @@ namespace kiota; public static partial class KiotaHost { - internal static readonly Lazy IsConfigPreviewEnabled = new(() => bool.TryParse(Environment.GetEnvironmentVariable("KIOTA_CONFIG_PREVIEW"), out var isPreviewEnabled) && isPreviewEnabled); + internal const string KiotaPreviewEnvironmentVariable = "KIOTA_CONFIG_PREVIEW"; + internal static readonly Lazy IsConfigPreviewEnabled = new(() => bool.TryParse(Environment.GetEnvironmentVariable(KiotaPreviewEnvironmentVariable), out var isPreviewEnabled) && isPreviewEnabled); public static RootCommand GetRootCommand() { var rootCommand = new RootCommand(); diff --git a/src/kiota/Rpc/IServer.cs b/src/kiota/Rpc/IServer.cs index 52f1409e41..5c467acdbe 100644 --- a/src/kiota/Rpc/IServer.cs +++ b/src/kiota/Rpc/IServer.cs @@ -12,4 +12,5 @@ internal interface IServer Task GetManifestDetailsAsync(string manifestPath, string apiIdentifier, bool clearCache, CancellationToken cancellationToken); Task> GenerateAsync(string openAPIFilePath, string outputPath, GenerationLanguage language, string[] includePatterns, string[] excludePatterns, string clientClassName, string clientNamespaceName, bool usesBackingStore, bool cleanOutput, bool clearCache, bool excludeBackwardCompatible, string[] disabledValidationRules, string[] serializers, string[] deserializers, string[] structuredMimeTypes, bool includeAdditionalData, CancellationToken cancellationToken); Task InfoForDescriptionAsync(string descriptionPath, bool clearCache, CancellationToken cancellationToken); + Task> GeneratePluginAsync(string openAPIFilePath, string outputPath, PluginType[] pluginTypes, string[] includePatterns, string[] excludePatterns, string clientClassName, bool cleanOutput, bool clearCache, string[] disabledValidationRules, CancellationToken cancellationToken); } diff --git a/src/kiota/Rpc/Server.cs b/src/kiota/Rpc/Server.cs index 878aa9b9d0..871f20bb54 100644 --- a/src/kiota/Rpc/Server.cs +++ b/src/kiota/Rpc/Server.cs @@ -30,6 +30,7 @@ protected KiotaConfiguration Configuration return configObject; }); private static readonly HttpClient httpClient = new(); + private static readonly Lazy IsConfigPreviewEnabled = new(() => bool.TryParse(Environment.GetEnvironmentVariable(KiotaHost.KiotaPreviewEnvironmentVariable), out var isPreviewEnabled) && isPreviewEnabled); public string GetVersion() { return KiotaVersion.Current(); @@ -80,7 +81,7 @@ private static async Task GenerateClientAsync(GenerationConfiguration conf { using var fileLogger = new FileLogLogger(config.OutputPath, LogLevel.Warning); var logger = new AggregateLogger(globalLogger, fileLogger); - return await new KiotaBuilder(logger, config, httpClient).GenerateClientAsync(cancellationToken); + return await new KiotaBuilder(logger, config, httpClient, IsConfigPreviewEnabled.Value).GenerateClientAsync(cancellationToken); } public async Task SearchAsync(string searchTerm, bool clearCache, CancellationToken cancellationToken) { @@ -97,7 +98,7 @@ public async Task GetManifestDetailsAsync(string manifestPath, s var configuration = Configuration.Generation; configuration.ClearCache = clearCache; configuration.ApiManifestPath = $"{manifestPath}#{apiIdentifier}"; - var builder = new KiotaBuilder(logger, configuration, httpClient); + var builder = new KiotaBuilder(logger, configuration, httpClient, IsConfigPreviewEnabled.Value); var manifestResult = await builder.GetApiManifestDetailsAsync(cancellationToken: cancellationToken); return new ManifestResult(logger.LogEntries, manifestResult?.Item1, @@ -109,12 +110,12 @@ public async Task ShowAsync(string descriptionPath, string[] include var configuration = Configuration.Generation; configuration.ClearCache = clearCache; configuration.OpenAPIFilePath = GetAbsolutePath(descriptionPath); - var builder = new KiotaBuilder(logger, configuration, httpClient); + var builder = new KiotaBuilder(logger, configuration, httpClient, IsConfigPreviewEnabled.Value); var fullUrlTreeNode = await builder.GetUrlTreeNodeAsync(cancellationToken); configuration.IncludePatterns = includeFilters.ToHashSet(StringComparer.Ordinal); configuration.ExcludePatterns = excludeFilters.ToHashSet(StringComparer.Ordinal); var filteredTreeNode = configuration.IncludePatterns.Count != 0 || configuration.ExcludePatterns.Count != 0 ? - await new KiotaBuilder(new NoopLogger(), configuration, httpClient).GetUrlTreeNodeAsync(cancellationToken) : // openapi.net seems to have side effects between tree node and the document, we need to drop all references + await new KiotaBuilder(new NoopLogger(), configuration, httpClient, IsConfigPreviewEnabled.Value).GetUrlTreeNodeAsync(cancellationToken) : // openapi.net seems to have side effects between tree node and the document, we need to drop all references default; var filteredPaths = filteredTreeNode is null ? new HashSet() : GetOperationsFromTreeNode(filteredTreeNode).ToHashSet(StringComparer.Ordinal); var rootNode = fullUrlTreeNode != null ? ConvertOpenApiUrlTreeNodeToPathItem(fullUrlTreeNode, filteredPaths) : null; @@ -150,14 +151,20 @@ public async Task> GenerateAsync(string openAPIFilePath, string o configuration.ClearCache = clearCache; configuration.ExcludeBackwardCompatible = excludeBackwardCompatible; configuration.IncludeAdditionalData = includeAdditionalData; - if (disabledValidationRules is not null && disabledValidationRules.Length != 0) + configuration.Operation = ConsumerOperation.Add; //TODO should be updated to edit in the edit scenario + if (disabledValidationRules is { Length: > 0 }) configuration.DisabledValidationRules = disabledValidationRules.ToHashSet(StringComparer.OrdinalIgnoreCase); - if (serializers is not null && serializers.Length != 0) + if (serializers is { Length: > 0 }) configuration.Serializers = serializers.ToHashSet(StringComparer.OrdinalIgnoreCase); - if (deserializers is not null && deserializers.Length != 0) + if (deserializers is { Length: > 0 }) configuration.Deserializers = deserializers.ToHashSet(StringComparer.OrdinalIgnoreCase); - if (structuredMimeTypes is not null && structuredMimeTypes.Length != 0) + if (structuredMimeTypes is { Length: > 0 }) configuration.StructuredMimeTypes = new(structuredMimeTypes); + if (IsConfigPreviewEnabled.Value) + { + configuration.Serializers.Clear(); + configuration.Deserializers.Clear(); + } if (!string.IsNullOrEmpty(clientClassName)) configuration.ClientClassName = clientClassName; if (!string.IsNullOrEmpty(clientNamespaceName)) @@ -176,6 +183,44 @@ public async Task> GenerateAsync(string openAPIFilePath, string o } return logger.LogEntries; } + public async Task> GeneratePluginAsync(string openAPIFilePath, string outputPath, PluginType[] pluginTypes, string[] includePatterns, string[] excludePatterns, string clientClassName, bool cleanOutput, bool clearCache, string[] disabledValidationRules, CancellationToken cancellationToken) + { + var globalLogger = new ForwardedLogger(); + var configuration = Configuration.Generation; + configuration.PluginTypes = pluginTypes.ToHashSet(); + configuration.OpenAPIFilePath = GetAbsolutePath(openAPIFilePath); + configuration.OutputPath = GetAbsolutePath(outputPath); + if (!string.IsNullOrEmpty(clientClassName)) + configuration.ClientClassName = clientClassName; + configuration.CleanOutput = cleanOutput; + configuration.ClearCache = clearCache; + configuration.Operation = ConsumerOperation.Add; //TODO should be updated to edit in the edit scenario + if (disabledValidationRules is { Length: > 0 }) + configuration.DisabledValidationRules = disabledValidationRules.ToHashSet(StringComparer.OrdinalIgnoreCase); + if (pluginTypes is { Length: > 0 }) + configuration.PluginTypes = pluginTypes.ToHashSet(); + if (includePatterns is { Length: > 0 }) + configuration.IncludePatterns = includePatterns.Select(static x => x.TrimQuotes()).ToHashSet(StringComparer.OrdinalIgnoreCase); + if (excludePatterns is { Length: > 0 }) + configuration.ExcludePatterns = excludePatterns.Select(static x => x.TrimQuotes()).ToHashSet(StringComparer.OrdinalIgnoreCase); + configuration.OpenAPIFilePath = GetAbsolutePath(configuration.OpenAPIFilePath); + configuration.OutputPath = NormalizeSlashesInPath(GetAbsolutePath(configuration.OutputPath)); + try + { + using var fileLogger = new FileLogLogger(configuration.OutputPath, LogLevel.Warning); + var logger = new AggregateLogger(globalLogger, fileLogger); + var result = await new KiotaBuilder(logger, configuration, httpClient, IsConfigPreviewEnabled.Value).GeneratePluginAsync(cancellationToken); + if (result) + logger.LogInformation("Generation completed successfully"); + else + logger.LogInformation("Generation skipped as --skip-generation was passed"); + } + catch (Exception ex) + { + globalLogger.LogCritical(ex, "error adding the client: {exceptionMessage}", ex.Message); + } + return globalLogger.LogEntries; + } public LanguagesInformation Info() { return Configuration.Languages; @@ -191,7 +236,7 @@ private async Task InfoInternalAsync(string descriptionPat var configuration = Configuration.Generation; configuration.ClearCache = clearCache; configuration.OpenAPIFilePath = GetAbsolutePath(descriptionPath); - var builder = new KiotaBuilder(logger, configuration, httpClient); + var builder = new KiotaBuilder(logger, configuration, httpClient, IsConfigPreviewEnabled.Value); var result = await builder.GetLanguagesInformationAsync(cancellationToken); if (result is not null) return result; return Configuration.Languages; @@ -214,13 +259,13 @@ private static PathItem ConvertOpenApiUrlTreeNodeToPathItem(OpenApiUrlTreeNode n .ToArray(); return new PathItem(node.Path, node.DeduplicatedSegment(), children, filteredPaths.Count == 0 || Array.Exists(children, static x => x.isOperation) && children.Where(static x => x.isOperation).All(static x => x.selected)); } - protected static string GetAbsolutePath(string source) + private static string GetAbsolutePath(string source) { if (string.IsNullOrEmpty(source)) return string.Empty; return Path.IsPathRooted(source) || source.StartsWith("http", StringComparison.OrdinalIgnoreCase) ? source : NormalizeSlashesInPath(Path.Combine(Directory.GetCurrentDirectory(), source)); } - protected static string NormalizeSlashesInPath(string path) + private static string NormalizeSlashesInPath(string path) { if (string.IsNullOrEmpty(path)) return path;