From f9f0f4bb1a4da4f0c5b7e132d88a03f8bc6c5d17 Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Mon, 19 Aug 2024 09:04:20 -0400 Subject: [PATCH 1/5] fix: missing map in java reserved names Signed-off-by: Vincent Biret --- CHANGELOG.md | 1 + src/Kiota.Builder/Refiners/JavaReservedNamesProvider.cs | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index e0d4c20127..7e439f607f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Fixed an issue where models would be missing when they had no properties and a single allOf entry. [#5014](https://github.com/microsoft/kiota/issues/5014) - Reverts modification of responses in output openApi file when generating plugins [#4945](https://github.com/microsoft/kiota/issues/4945) - Expand properties types with null type for Typescript. [#4993](https://github.com/microsoft/kiota-typescript/issues/1188) +- Added Collection, HashMap, Map, Objects, InputStream, BigDecimal to the list of reserved names for Java generation. [#5135](https://github.com/microsoft/kiota/issues/5135) ## [1.17.0] - 2024-08-09 diff --git a/src/Kiota.Builder/Refiners/JavaReservedNamesProvider.cs b/src/Kiota.Builder/Refiners/JavaReservedNamesProvider.cs index d9e864e637..42d7c22e7d 100644 --- a/src/Kiota.Builder/Refiners/JavaReservedNamesProvider.cs +++ b/src/Kiota.Builder/Refiners/JavaReservedNamesProvider.cs @@ -38,6 +38,7 @@ public class JavaReservedNamesProvider : IReservedNamesProvider "int", "interface", "long", + "map", "native", "new", "notify", @@ -68,6 +69,11 @@ public class JavaReservedNamesProvider : IReservedNamesProvider "while", "BaseRequestBuilder", "MultipartBody", + "HashMap", + "Collection", + "Objects", + "InputStream", + "BigDecimal", }); public HashSet ReservedNames => _reservedNames.Value; } From de197986591ce90566c0c386f359c9e85c9c0a58 Mon Sep 17 00:00:00 2001 From: Andrew Omondi Date: Mon, 19 Aug 2024 16:04:43 +0300 Subject: [PATCH 2/5] Revert "Merge pull request #5025 from microsoft/andrueastman/defaultIcons" This reverts commit 44d61a46454e8e2b13ef4e18d9f8d38cb04fda8e, reversing changes made to 1983ca4d023c212786adedb6dd022cd5b78f7452. --- resources/color.png | Bin 8038 -> 0 bytes resources/outline.png | Bin 512 -> 0 bytes src/Kiota.Builder/Kiota.Builder.csproj | 8 +----- .../Plugins/PluginsGenerationService.cs | 27 +----------------- .../Plugins/PluginsGenerationServiceTests.cs | 8 ------ 5 files changed, 2 insertions(+), 41 deletions(-) delete mode 100644 resources/color.png delete mode 100644 resources/outline.png diff --git a/resources/color.png b/resources/color.png deleted file mode 100644 index fea3285f4d8ef36a2044c844a28b2c564a1f135d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8038 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 JS>7_@{{W+ISONe5 diff --git a/resources/outline.png b/resources/outline.png deleted file mode 100644 index 6530cb998ae4620b6740fe992eb89f35d7587597..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 512 zcmV+b0{{JqP)Px$x=BPqR9HvNm%lGWK@i91MXr$e1GI{By}}=G_y?2Q7A|e6+xE*5vZRHMN zagR^x)G(wL8z4*oK|BT#M6qD(f81nv0B!X){y33C5^>L-UfyBtcqq2bRY3)y ztG2enRYZ$50fZ$u($S9*wd9&Go`_0wJ{7~sxi-)k$&f4nXFSe`)P&M+Yzz^=1yXvc zyxcSCohX3jaH*u+Ucf;V2k6Yt!P)k*ud<~LjkI94H3J`?U*lFMw;*h*VFK2BS8)6M z<`e#z38`3YDvFGuWh)M~#DY1~5IYaDw&K`$;^fldh2zXy@nCBSHcqeoyQ71yKkKzo z9X`CmX8*=^7-?bCZ!>=KFx41bA9pakJFf;G#HC0&if5oNMrzTCjn0Y0000..\Microsoft.OpenApi.snk true All - true @@ -50,8 +49,7 @@ - - + @@ -60,8 +58,4 @@ - - - - diff --git a/src/Kiota.Builder/Plugins/PluginsGenerationService.cs b/src/Kiota.Builder/Plugins/PluginsGenerationService.cs index c446a99ad1..eeea94082f 100644 --- a/src/Kiota.Builder/Plugins/PluginsGenerationService.cs +++ b/src/Kiota.Builder/Plugins/PluginsGenerationService.cs @@ -2,7 +2,6 @@ using System.Collections.Generic; using System.IO; using System.Linq; -using System.Reflection; using System.Text.Json; using System.Text.Json.Serialization; using System.Text.RegularExpressions; @@ -12,7 +11,6 @@ using Kiota.Builder.Extensions; using Kiota.Builder.OpenApiExtensions; using Kiota.Builder.Plugins.Models; -using Microsoft.Extensions.FileProviders; using Microsoft.Kiota.Abstractions.Extensions; using Microsoft.OpenApi.ApiManifest; using Microsoft.OpenApi.Models; @@ -116,8 +114,6 @@ public async Task GenerateManifestAsync(CancellationToken cancellationToken = de } } - private const string ColorFileName = "color.png"; - private const string OutlineFileName = "outline.png"; [GeneratedRegex(@"[^a-zA-Z0-9_]+", RegexOptions.IgnoreCase | RegexOptions.Singleline, 2000)] private static partial Regex PluginNameCleanupRegex(); @@ -159,16 +155,6 @@ private async Task GetAppManifestModelAsync(string pluginFileN if (manifestModelFromFile != null) manifestModel = manifestModelFromFile; } - else - { - // The manifest file did not exist, so setup any dependencies needed. - // If it already existed, the user has setup them up in another way. - - // 1. Check if icons exist and write them out. - var embeddedProvider = new EmbeddedFileProvider(Assembly.GetExecutingAssembly()); - await CopyResourceFileToDirectoryIfNotExistsAsync(ColorFileName, embeddedProvider, cancellationToken).ConfigureAwait(false); - await CopyResourceFileToDirectoryIfNotExistsAsync(OutlineFileName, embeddedProvider, cancellationToken).ConfigureAwait(false); - } manifestModel.CopilotExtensions ??= new CopilotExtensions();// ensure its not null. @@ -189,18 +175,7 @@ private async Task GetAppManifestModelAsync(string pluginFileN return manifestModel; } - private async Task CopyResourceFileToDirectoryIfNotExistsAsync(string fileName, EmbeddedFileProvider embeddedProvider, CancellationToken cancellationToken) - { - var targetPath = Path.Combine(Configuration.OutputPath, fileName); - if (!File.Exists(targetPath)) - { -#pragma warning disable CA2007 - await using var reader = embeddedProvider.GetFileInfo(fileName).CreateReadStream(); - await using var defaultColorFile = File.Open(targetPath, FileMode.Create); -#pragma warning restore CA2007 - await reader.CopyToAsync(defaultColorFile, cancellationToken).ConfigureAwait(false); - } - } + internal static readonly AppManifestModelGenerationContext AppManifestModelGenerationContext = new(new JsonSerializerOptions { PropertyNamingPolicy = JsonNamingPolicy.CamelCase, diff --git a/tests/Kiota.Builder.Tests/Plugins/PluginsGenerationServiceTests.cs b/tests/Kiota.Builder.Tests/Plugins/PluginsGenerationServiceTests.cs index 451f054589..9f07a8e019 100644 --- a/tests/Kiota.Builder.Tests/Plugins/PluginsGenerationServiceTests.cs +++ b/tests/Kiota.Builder.Tests/Plugins/PluginsGenerationServiceTests.cs @@ -95,8 +95,6 @@ public async Task GeneratesManifest(string inputPluginName, string expectedPlugi Assert.True(File.Exists(Path.Combine(outputDirectory, OpenAIPluginFileName))); Assert.True(File.Exists(Path.Combine(outputDirectory, $"{expectedPluginName.ToLower()}-openapi.yml"))); Assert.True(File.Exists(Path.Combine(outputDirectory, AppManifestFileName))); - Assert.True(File.Exists(Path.Combine(outputDirectory, "color.png"))); - Assert.True(File.Exists(Path.Combine(outputDirectory, "outline.png"))); // Validate the v2 plugin var manifestContent = await File.ReadAllTextAsync(Path.Combine(outputDirectory, $"{expectedPluginName.ToLower()}-apiplugin.json")); @@ -509,8 +507,6 @@ public async Task GeneratesManifestAndUpdatesExistingAppManifest() Assert.True(File.Exists(Path.Combine(outputDirectory, ManifestFileName))); Assert.True(File.Exists(Path.Combine(outputDirectory, OpenApiFileName))); - Assert.False(File.Exists(Path.Combine(outputDirectory, "color.png"))); // manifest already existed and specifed the path to a file, so we did not add it. - Assert.False(File.Exists(Path.Combine(outputDirectory, "outline.png")));// manifest already existed and specifed the path to a file, so we did not add it. Assert.True(File.Exists(Path.Combine(outputDirectory, "manifest.json")));// Assert manifest exists after generation // Validate the manifest file @@ -644,8 +640,6 @@ public async Task GeneratesManifestAndUpdatesExistingAppManifestWithExistingPlug Assert.True(File.Exists(Path.Combine(outputDirectory, ManifestFileName))); Assert.True(File.Exists(Path.Combine(outputDirectory, OpenApiFileName))); Assert.True(File.Exists(Path.Combine(outputDirectory, "manifest.json")));// Assert manifest exists after generation - Assert.False(File.Exists(Path.Combine(outputDirectory, "color.png"))); // manifest already existed and specifed the path to a file, so we did not add it. - Assert.False(File.Exists(Path.Combine(outputDirectory, "outline.png")));// manifest already existed and specifed the path to a file, so we did not add it. // Validate the manifest file var appManifestFile = await File.ReadAllTextAsync(Path.Combine(outputDirectory, AppManifestFileName)); @@ -751,8 +745,6 @@ public async Task GeneratesManifestAndCleansUpInputDescription() Assert.True(File.Exists(Path.Combine(outputDirectory, ManifestFileName))); Assert.True(File.Exists(Path.Combine(outputDirectory, OpenApiFileName))); - Assert.True(File.Exists(Path.Combine(outputDirectory, "color.png"))); - Assert.True(File.Exists(Path.Combine(outputDirectory, "outline.png"))); // Validate the v2 plugin var manifestContent = await File.ReadAllTextAsync(Path.Combine(outputDirectory, ManifestFileName)); From a8dbd29b644d603ab3c2b8d6b7ec0c1d1bf83277 Mon Sep 17 00:00:00 2001 From: Andrew Omondi Date: Mon, 19 Aug 2024 16:08:10 +0300 Subject: [PATCH 3/5] Revert "Merge pull request #4914 from microsoft/andrueastman/generateManifest" This reverts commit 59c637ff8b738706074ee4bdc5a33477c23879ff, reversing changes made to 46ff43623e30e1414565c8fd9872a913c0fb150b. --- .../Plugins/Models/AppManifestModel.cs | 181 ------ .../Plugins/PluginsGenerationService.cs | 84 +-- .../Plugins/PluginsGenerationServiceTests.cs | 558 +----------------- 3 files changed, 4 insertions(+), 819 deletions(-) delete mode 100644 src/Kiota.Builder/Plugins/Models/AppManifestModel.cs diff --git a/src/Kiota.Builder/Plugins/Models/AppManifestModel.cs b/src/Kiota.Builder/Plugins/Models/AppManifestModel.cs deleted file mode 100644 index 1cdab12172..0000000000 --- a/src/Kiota.Builder/Plugins/Models/AppManifestModel.cs +++ /dev/null @@ -1,181 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Text.Json; -using System.Text.Json.Serialization; - -namespace Kiota.Builder.Plugins.Models; - -internal class AppManifestModel -{ - private const string DefaultSchema = "https://developer.microsoft.com/json-schemas/teams/vDevPreview/MicrosoftTeams.schema.json"; - private const string DefaultManifestVersion = "devPreview"; - private const string DefaultVersion = "1.0.0"; - - [JsonPropertyName("$schema")] - public string? Schema - { - get; - set; - } = DefaultSchema; - - public string? ManifestVersion - { - get; - set; - } = DefaultManifestVersion; - - public string? Version - { - get; - set; - } = DefaultVersion; - public string? Id - { - get; set; - } - public Developer? Developer - { - get; init; - } - public string? PackageName - { - get; set; - } - public Name? Name - { - get; set; - } - public Description? Description - { - get; set; - } - public Icons? Icons - { - get; set; - } - public string? AccentColor - { - get; set; - } - public CopilotExtensions? CopilotExtensions - { - get; set; - } - - [JsonExtensionData] - public Dictionary AdditionalData { get; set; } = new(); -} - -[JsonSerializable(typeof(AppManifestModel))] -[JsonSerializable(typeof(JsonElement))] -internal partial class AppManifestModelGenerationContext : JsonSerializerContext -{ -} - -#pragma warning disable CA1054 -internal class Developer -#pragma warning restore CA1054 -{ - public string? Name - { - get; set; - } -#pragma warning disable CA1056 - public string? WebsiteUrl - { - get; set; - } - public string? PrivacyUrl - { - get; set; - } - public string? TermsOfUseUrl - { - get; set; - } -#pragma warning restore CA1056 - - [JsonExtensionData] - public Dictionary AdditionalData { get; set; } = new(); -} - -internal class Name -{ - [JsonPropertyName("short")] - public string? ShortName - { - get; set; - } - [JsonPropertyName("full")] - public string? FullName - { - get; set; - } -} - -internal class Description -{ - [JsonPropertyName("short")] - public string? ShortName - { - get; set; - } - [JsonPropertyName("full")] - public string? FullName - { - get; set; - } -} - -internal class Icons -{ - public string? Color - { - get; - set; - } = "color.png"; - - public string? Outline - { - get; - set; - } = "outline.png"; -} - -internal class CopilotExtensions -{ - public IList? Plugins - { - get; set; - } - public IList? DeclarativeCopilots - { - get; set; - } - [JsonExtensionData] - public Dictionary AdditionalData { get; set; } = []; -} - -internal class Plugin -{ - public string? Id - { - get; set; - } - public string? File - { - get; set; - } -} - -internal class DeclarativeCopilot -{ - public string? Id - { - get; set; - } - public string? File - { - get; set; - } -} diff --git a/src/Kiota.Builder/Plugins/PluginsGenerationService.cs b/src/Kiota.Builder/Plugins/PluginsGenerationService.cs index eeea94082f..4cff5d1560 100644 --- a/src/Kiota.Builder/Plugins/PluginsGenerationService.cs +++ b/src/Kiota.Builder/Plugins/PluginsGenerationService.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.IO; using System.Linq; @@ -10,7 +10,6 @@ using Kiota.Builder.Configuration; using Kiota.Builder.Extensions; using Kiota.Builder.OpenApiExtensions; -using Kiota.Builder.Plugins.Models; using Microsoft.Kiota.Abstractions.Extensions; using Microsoft.OpenApi.ApiManifest; using Microsoft.OpenApi.Models; @@ -41,7 +40,6 @@ public PluginsGenerationService(OpenApiDocument document, OpenApiUrlTreeNode ope private const string ManifestFileNameSuffix = ".json"; private const string DescriptionPathSuffix = "openapi.yml"; private const string OpenAIManifestFileName = "openai-plugins"; - private const string AppManifestFileName = "manifest.json"; public async Task GenerateManifestAsync(CancellationToken cancellationToken = default) { // 1. cleanup any namings to be used later on. @@ -100,88 +98,10 @@ public async Task GenerateManifestAsync(CancellationToken cancellationToken = de } await writer.FlushAsync(cancellationToken).ConfigureAwait(false); } - - // 4. write the app manifest if its an Api Plugin - if (Configuration.PluginTypes.Any(static plugin => plugin == PluginType.APIPlugin)) - { - var manifestFullPath = Path.Combine(Configuration.OutputPath, AppManifestFileName); - var pluginFileName = $"{Configuration.ClientClassName.ToLowerInvariant()}-{PluginType.APIPlugin.ToString().ToLowerInvariant()}{ManifestFileNameSuffix}"; - var appManifestModel = await GetAppManifestModelAsync(pluginFileName, manifestFullPath, cancellationToken).ConfigureAwait(false); -#pragma warning disable CA2007 - await using var appManifestStream = File.Open(manifestFullPath, FileMode.Create); -#pragma warning restore CA2007 - await JsonSerializer.SerializeAsync(appManifestStream, appManifestModel, AppManifestModelGenerationContext.AppManifestModel, cancellationToken).ConfigureAwait(false); - } } - [GeneratedRegex(@"[^a-zA-Z0-9_]+", RegexOptions.IgnoreCase | RegexOptions.Singleline, 2000)] private static partial Regex PluginNameCleanupRegex(); - - private async Task GetAppManifestModelAsync(string pluginFileName, string manifestFullPath, CancellationToken cancellationToken) - { - var manifestInfo = ExtractInfoFromDocument(OAIDocument.Info); - // create default model - var manifestModel = new AppManifestModel - { - Id = Guid.NewGuid().ToString(), - Developer = new Developer - { - Name = !string.IsNullOrEmpty(OAIDocument.Info?.Contact?.Name) ? OAIDocument.Info?.Contact?.Name : "Microsoft Kiota.", - WebsiteUrl = !string.IsNullOrEmpty(OAIDocument.Info?.Contact?.Url?.OriginalString) ? OAIDocument.Info?.Contact?.Url?.OriginalString : "https://www.example.com/contact/", - PrivacyUrl = !string.IsNullOrEmpty(manifestInfo.PrivacyUrl) ? manifestInfo.PrivacyUrl : "https://www.example.com/privacy/", - TermsOfUseUrl = !string.IsNullOrEmpty(OAIDocument.Info?.TermsOfService?.OriginalString) ? OAIDocument.Info?.TermsOfService?.OriginalString : "https://www.example.com/terms/", - }, - PackageName = $"com.microsoft.kiota.plugin.{Configuration.ClientClassName}", - Name = new Name - { - ShortName = Configuration.ClientClassName, - FullName = $"API Plugin {Configuration.ClientClassName} for {OAIDocument.Info?.Title.CleanupXMLString() ?? "OpenApi Document"}" - }, - Description = new Description - { - ShortName = !string.IsNullOrEmpty(OAIDocument.Info?.Description.CleanupXMLString()) ? $"API Plugin for {OAIDocument.Info?.Description.CleanupXMLString()}." : OAIDocument.Info?.Title.CleanupXMLString() ?? "OpenApi Document", - FullName = !string.IsNullOrEmpty(OAIDocument.Info?.Description.CleanupXMLString()) ? $"API Plugin for {OAIDocument.Info?.Description.CleanupXMLString()}." : OAIDocument.Info?.Title.CleanupXMLString() ?? "OpenApi Document" - }, - Icons = new Icons(), - AccentColor = "#FFFFFF" - }; - - if (File.Exists(manifestFullPath)) // No need for default, try to update the model from the file - { -#pragma warning disable CA2007 // Consider calling ConfigureAwait on the awaited task - await using var fileStream = File.OpenRead(manifestFullPath); -#pragma warning restore CA2007 // Consider calling ConfigureAwait on the awaited task - var manifestModelFromFile = await JsonSerializer.DeserializeAsync(fileStream, AppManifestModelGenerationContext.AppManifestModel, cancellationToken).ConfigureAwait(false); - if (manifestModelFromFile != null) - manifestModel = manifestModelFromFile; - } - - manifestModel.CopilotExtensions ??= new CopilotExtensions();// ensure its not null. - - if (manifestModel.CopilotExtensions.Plugins is not null && manifestModel.CopilotExtensions.Plugins.FirstOrDefault(pluginItem => Configuration.ClientClassName.Equals(pluginItem.Id, StringComparison.OrdinalIgnoreCase)) is { } plugin) - { - plugin.File = pluginFileName; // id is already consistent so make sure the file name is ok - } - else - { - manifestModel.CopilotExtensions.Plugins ??= []; - // Add a new plugin entry - manifestModel.CopilotExtensions.Plugins.Add(new Plugin - { - File = pluginFileName, - Id = Configuration.ClientClassName - }); - } - - return manifestModel; - } - - internal static readonly AppManifestModelGenerationContext AppManifestModelGenerationContext = new(new JsonSerializerOptions - { - PropertyNamingPolicy = JsonNamingPolicy.CamelCase, - WriteIndented = true, - DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull - }); + [GeneratedRegex(@"[^a-zA-Z0-9_]+", RegexOptions.IgnoreCase | RegexOptions.Singleline, 2000)] private OpenApiDocument GetDocumentWithTrimmedComponentsAndResponses(OpenApiDocument doc) { diff --git a/tests/Kiota.Builder.Tests/Plugins/PluginsGenerationServiceTests.cs b/tests/Kiota.Builder.Tests/Plugins/PluginsGenerationServiceTests.cs index 9f07a8e019..4f586fc3e5 100644 --- a/tests/Kiota.Builder.Tests/Plugins/PluginsGenerationServiceTests.cs +++ b/tests/Kiota.Builder.Tests/Plugins/PluginsGenerationServiceTests.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.IO; using System.Linq; using System.Net.Http; @@ -6,7 +6,6 @@ using System.Threading.Tasks; using Kiota.Builder.Configuration; using Kiota.Builder.Plugins; -using Kiota.Builder.Plugins.Models; using Microsoft.Extensions.Logging; using Microsoft.OpenApi.Models; using Microsoft.OpenApi.Readers; @@ -93,8 +92,7 @@ public async Task GeneratesManifest(string inputPluginName, string expectedPlugi Assert.True(File.Exists(Path.Combine(outputDirectory, $"{expectedPluginName.ToLower()}-apiplugin.json"))); Assert.True(File.Exists(Path.Combine(outputDirectory, $"{expectedPluginName.ToLower()}-apimanifest.json"))); Assert.True(File.Exists(Path.Combine(outputDirectory, OpenAIPluginFileName))); - Assert.True(File.Exists(Path.Combine(outputDirectory, $"{expectedPluginName.ToLower()}-openapi.yml"))); - Assert.True(File.Exists(Path.Combine(outputDirectory, AppManifestFileName))); + Assert.True(File.Exists(Path.Combine(outputDirectory, OpenApiFileName))); // Validate the v2 plugin var manifestContent = await File.ReadAllTextAsync(Path.Combine(outputDirectory, $"{expectedPluginName.ToLower()}-apiplugin.json")); @@ -113,563 +111,11 @@ public async Task GeneratesManifest(string inputPluginName, string expectedPlugi Assert.NotNull(resultingManifest.Document); Assert.Equal($"{expectedPluginName.ToLower()}-openapi.yml", v1Manifest.Document.Api.URL); Assert.Empty(v1Manifest.Problems); - - // Validate the manifest file - var appManifestFile = await File.ReadAllTextAsync(Path.Combine(outputDirectory, AppManifestFileName)); - var appManifestModelObject = JsonSerializer.Deserialize(appManifestFile, PluginsGenerationService.AppManifestModelGenerationContext.AppManifestModel); - Assert.Equal($"com.microsoft.kiota.plugin.{expectedPluginName}", appManifestModelObject.PackageName); - Assert.Equal(expectedPluginName, appManifestModelObject.Name.ShortName); - Assert.Equal("Microsoft Kiota.", appManifestModelObject.Developer.Name); - Assert.Equal("color.png", appManifestModelObject.Icons.Color); - Assert.NotNull(appManifestModelObject.CopilotExtensions.Plugins); - Assert.Single(appManifestModelObject.CopilotExtensions.Plugins); - Assert.Equal(expectedPluginName, appManifestModelObject.CopilotExtensions.Plugins[0].Id); - Assert.Equal($"{expectedPluginName.ToLower()}-apiplugin.json", appManifestModelObject.CopilotExtensions.Plugins[0].File); } private const string ManifestFileName = "client-apiplugin.json"; private const string OpenAIPluginFileName = "openai-plugins.json"; private const string OpenApiFileName = "client-openapi.yml"; - private const string AppManifestFileName = "manifest.json"; - - [Fact] - public async Task GeneratesManifestAndUpdatesExistingAppManifest() - { - var simpleDescriptionContent = @"openapi: 3.0.0 -info: - title: test - version: 1.0 - description: A sample test api -servers: - - url: http://localhost/ - description: There's no place like home -paths: - /test/{id}: - get: - description: description for test path with id - operationId: test.WithId - parameters: - - name: id - in: path - required: true - description: The id of the test - schema: - type: integer - format: int32 - responses: - '200': - description: test"; - var workingDirectory = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName()); - var simpleDescriptionPath = Path.Combine(workingDirectory) + "description.yaml"; - await File.WriteAllTextAsync(simpleDescriptionPath, simpleDescriptionContent); - var mockLogger = new Mock>(); - var openAPIDocumentDS = new OpenApiDocumentDownloadService(_httpClient, mockLogger.Object); - var outputDirectory = Path.Combine(workingDirectory, "output"); - Directory.CreateDirectory(outputDirectory); - var preExistingManifestContents = @"{ - ""$schema"": ""https://developer.microsoft.com/json-schemas/teams/v1.17/MicrosoftTeams.schema.json"", - ""manifestVersion"": ""1.17"", - ""version"": ""1.0.0"", - ""id"": ""%MICROSOFT-APP-ID%"", - ""localizationInfo"": { - ""defaultLanguageTag"": ""en-us"", - ""additionalLanguages"": [ - { - ""languageTag"": ""es-es"", - ""file"": ""en-us.json"" - } - ] - }, - ""developer"": { - ""name"": ""Publisher Name"", - ""websiteUrl"": ""https://example.com/"", - ""privacyUrl"": ""https://example.com/privacy"", - ""termsOfUseUrl"": ""https://example.com/app-tos"", - ""mpnId"": ""1234567890"" - }, - ""name"": { - ""short"": ""Name of your app"", - ""full"": ""Full name of app, if longer than 30 characters"" - }, - ""description"": { - ""short"": ""Short description of your app (<= 80 chars)"", - ""full"": ""Full description of your app (<= 4000 chars)"" - }, - ""icons"": { - ""outline"": ""A relative path to a transparent .png icon — 32px X 32px"", - ""color"": ""A relative path to a full color .png icon — 192px X 192px"" - }, - ""accentColor"": ""A valid HTML color code."", - ""configurableTabs"": [ - { - ""configurationUrl"": ""https://contoso.com/teamstab/configure"", - ""scopes"": [ - ""team"", - ""groupChat"" - ], - ""canUpdateConfiguration"": true, - ""context"": [ - ""channelTab"", - ""privateChatTab"", - ""meetingChatTab"", - ""meetingDetailsTab"", - ""meetingSidePanel"", - ""meetingStage"" - ], - ""sharePointPreviewImage"": ""Relative path to a tab preview image for use in SharePoint — 1024px X 768"", - ""supportedSharePointHosts"": [ - ""sharePointFullPage"", - ""sharePointWebPart"" - ] - } - ], - ""staticTabs"": [ - { - ""entityId"": ""unique Id for the page entity"", - ""scopes"": [ - ""personal"" - ], - ""context"": [ - ""personalTab"", - ""channelTab"" - ], - ""name"": ""Display name of tab"", - ""contentUrl"": ""https://contoso.com/content (displayed in Teams canvas)"", - ""websiteUrl"": ""https://contoso.com/content (displayed in web browser)"", - ""searchUrl"": ""https://contoso.com/content (displayed in web browser)"" - } - ], - ""supportedChannelTypes"": [ - ""sharedChannels"", - ""privateChannels"" - ], - ""bots"": [ - { - ""botId"": ""%MICROSOFT-APP-ID-REGISTERED-WITH-BOT-FRAMEWORK%"", - ""scopes"": [ - ""team"", - ""personal"", - ""groupChat"" - ], - ""needsChannelSelector"": false, - ""isNotificationOnly"": false, - ""supportsFiles"": true, - ""supportsCalling"": false, - ""supportsVideo"": true, - ""commandLists"": [ - { - ""scopes"": [ - ""team"", - ""groupChat"" - ], - ""commands"": [ - { - ""title"": ""Command 1"", - ""description"": ""Description of Command 1"" - }, - { - ""title"": ""Command 2"", - ""description"": ""Description of Command 2"" - } - ] - }, - { - ""scopes"": [ - ""personal"", - ""groupChat"" - ], - ""commands"": [ - { - ""title"": ""Personal command 1"", - ""description"": ""Description of Personal command 1"" - }, - { - ""title"": ""Personal command N"", - ""description"": ""Description of Personal command N"" - } - ] - } - ] - } - ], - ""connectors"": [ - { - ""connectorId"": ""GUID-FROM-CONNECTOR-DEV-PORTAL%"", - ""scopes"": [ - ""team"" - ], - ""configurationUrl"": ""https://contoso.com/teamsconnector/configure"" - } - ], - ""composeExtensions"": [ - { - ""canUpdateConfiguration"": true, - ""botId"": ""%MICROSOFT-APP-ID-REGISTERED-WITH-BOT-FRAMEWORK%"", - ""commands"": [ - { - ""id"": ""exampleCmd1"", - ""title"": ""Example Command"", - ""type"": ""query"", - ""context"": [ - ""compose"", - ""commandBox"" - ], - ""description"": ""Command Description; e.g., Search on the web"", - ""initialRun"": true, - ""fetchTask"": false, - ""parameters"": [ - { - ""name"": ""keyword"", - ""title"": ""Search keywords"", - ""inputType"": ""choiceset"", - ""description"": ""Enter the keywords to search for"", - ""value"": ""Initial value for the parameter"", - ""choices"": [ - { - ""title"": ""Title of the choice"", - ""value"": ""Value of the choice"" - } - ] - } - ] - }, - { - ""id"": ""exampleCmd2"", - ""title"": ""Example Command 2"", - ""type"": ""action"", - ""context"": [ - ""message"" - ], - ""description"": ""Command Description; e.g., Add a customer"", - ""initialRun"": true, - ""fetchTask"": false , - ""parameters"": [ - { - ""name"": ""custinfo"", - ""title"": ""Customer name"", - ""description"": ""Enter a customer name"", - ""inputType"": ""text"" - } - ] - }, - { - ""id"": ""exampleCmd3"", - ""title"": ""Example Command 3"", - ""type"": ""action"", - ""context"": [ - ""compose"", - ""commandBox"", - ""message"" - ], - ""description"": ""Command Description; e.g., Add a customer"", - ""fetchTask"": false, - ""taskInfo"": { - ""title"": ""Initial dialog title"", - ""width"": ""Dialog width"", - ""height"": ""Dialog height"", - ""url"": ""Initial webview URL"" - } - } - ], - ""messageHandlers"": [ - { - ""type"": ""link"", - ""value"": { - ""domains"": [ - ""mysite.someplace.com"", - ""othersite.someplace.com"" - ], - ""supportsAnonymizedPayloads"": false - } - } - ] - } - ], - ""permissions"": [ - ""identity"", - ""messageTeamMembers"" - ], - ""devicePermissions"": [ - ""geolocation"", - ""media"", - ""notifications"", - ""midi"", - ""openExternal"" - ], - ""validDomains"": [ - ""contoso.com"", - ""mysite.someplace.com"", - ""othersite.someplace.com"" - ], - ""webApplicationInfo"": { - ""id"": ""AAD App ID"", - ""resource"": ""Resource URL for acquiring auth token for SSO"" - }, - ""authorization"": { - ""permissions"": { - ""resourceSpecific"": [ - { - ""type"": ""Application"", - ""name"": ""ChannelSettings.Read.Group"" - }, - { - ""type"": ""Delegated"", - ""name"": ""ChannelMeetingParticipant.Read.Group"" - } - ] - } - }, - ""showLoadingIndicator"": false, - ""isFullScreen"": false, - ""activities"": { - ""activityTypes"": [ - { - ""type"": ""taskCreated"", - ""description"": ""Task created activity"", - ""templateText"": "" created task for you"" - }, - { - ""type"": ""userMention"", - ""description"": ""Personal mention activity"", - ""templateText"": "" mentioned you"" - } - ] - }, - ""defaultBlockUntilAdminAction"": true, - ""publisherDocsUrl"": ""https://example.com/app-info"", - ""defaultInstallScope"": ""meetings"", - ""defaultGroupCapability"": { - ""meetings"": ""tab"", - ""team"": ""bot"", - ""groupChat"": ""bot"" - }, - ""configurableProperties"": [ - ""name"", - ""shortDescription"", - ""longDescription"", - ""smallImageUrl"", - ""largeImageUrl"", - ""accentColor"", - ""developerUrl"", - ""privacyUrl"", - ""termsOfUseUrl"" - ], - ""subscriptionOffer"": { - ""offerId"": ""publisherId.offerId"" - }, - ""meetingExtensionDefinition"": { - ""scenes"": [ - { - ""id"": ""9082c811-7e6a-4174-8173-6ccd57d377e6"", - ""name"": ""Getting started sample"", - ""file"": ""scenes/sceneMetadata.json"", - ""preview"": ""scenes/scenePreview.png"", - ""maxAudience"": 15, - ""seatsReservedForOrganizersOrPresenters"": 0 - }, - { - ""id"": ""afeaed22-f89b-48e1-98b4-46a514344e4a"", - ""name"": ""Sample-1"", - ""file"": ""scenes/sceneMetadata.json"", - ""preview"": ""scenes/scenePreview.png"", - ""maxAudience"": 15, - ""seatsReservedForOrganizersOrPresenters"": 3 - } - ] - } -}"; - var preExistingManifestPath = Path.Combine(outputDirectory, "manifest.json"); - await File.WriteAllTextAsync(preExistingManifestPath, preExistingManifestContents); - var generationConfiguration = new GenerationConfiguration - { - OutputPath = outputDirectory, - OpenAPIFilePath = "openapiPath", - PluginTypes = [PluginType.APIPlugin], - ClientClassName = "client", - ApiRootUrl = "http://localhost/", //Kiota builder would set this for us - }; - var (openAPIDocumentStream, _) = await openAPIDocumentDS.LoadStreamAsync(simpleDescriptionPath, generationConfiguration, null, false); - var openApiDocument = await openAPIDocumentDS.GetDocumentFromStreamAsync(openAPIDocumentStream, generationConfiguration); - KiotaBuilder.CleanupOperationIdForPlugins(openApiDocument); - var urlTreeNode = OpenApiUrlTreeNode.Create(openApiDocument, Constants.DefaultOpenApiLabel); - - // Assert manifest exists before generation and is parsable - Assert.True(File.Exists(Path.Combine(outputDirectory, "manifest.json"))); - var originalManifestFile = await File.ReadAllTextAsync(Path.Combine(outputDirectory, AppManifestFileName)); - var originalAppManifestModelObject = JsonSerializer.Deserialize(originalManifestFile, PluginsGenerationService.AppManifestModelGenerationContext.AppManifestModel); - Assert.Null(originalAppManifestModelObject.PackageName);// package wasn't present - Assert.Equal("Name of your app", originalAppManifestModelObject.Name.ShortName); // app name is same - Assert.Equal("Publisher Name", originalAppManifestModelObject.Developer.Name); // app name is same - Assert.Null(originalAppManifestModelObject.CopilotExtensions?.Plugins); // no plugins present - - // Run the plugin generation - var pluginsGenerationService = new PluginsGenerationService(openApiDocument, urlTreeNode, generationConfiguration, workingDirectory); - await pluginsGenerationService.GenerateManifestAsync(); - - Assert.True(File.Exists(Path.Combine(outputDirectory, ManifestFileName))); - Assert.True(File.Exists(Path.Combine(outputDirectory, OpenApiFileName))); - Assert.True(File.Exists(Path.Combine(outputDirectory, "manifest.json")));// Assert manifest exists after generation - - // Validate the manifest file - var appManifestFile = await File.ReadAllTextAsync(Path.Combine(outputDirectory, AppManifestFileName)); - var appManifestModelObject = JsonSerializer.Deserialize(appManifestFile, PluginsGenerationService.AppManifestModelGenerationContext.AppManifestModel); - Assert.Null(appManifestModelObject.PackageName);// package wasn't present - Assert.Equal("Name of your app", appManifestModelObject.Name.ShortName); // app name is same - Assert.Equal("Publisher Name", originalAppManifestModelObject.Developer.Name); // developer name is same - Assert.NotNull(appManifestModelObject.CopilotExtensions); - Assert.NotNull(appManifestModelObject.CopilotExtensions.Plugins); - Assert.Single(appManifestModelObject.CopilotExtensions.Plugins);//one plugin present - Assert.Equal("client", appManifestModelObject.CopilotExtensions.Plugins[0].Id); - Assert.Equal(ManifestFileName, appManifestModelObject.CopilotExtensions.Plugins[0].File); - var rootJsonElement = JsonDocument.Parse(appManifestFile).RootElement; - Assert.True(rootJsonElement.TryGetProperty("subscriptionOffer", out _));// no loss of information - Assert.True(rootJsonElement.TryGetProperty("meetingExtensionDefinition", out _));// no loss of information - Assert.True(rootJsonElement.TryGetProperty("activities", out _));// no loss of information - Assert.True(rootJsonElement.TryGetProperty("devicePermissions", out _));// no loss of information - Assert.True(rootJsonElement.TryGetProperty("composeExtensions", out _));// no loss of information - } - - [Fact] - public async Task GeneratesManifestAndUpdatesExistingAppManifestWithExistingPlugins() - { - var simpleDescriptionContent = @"openapi: 3.0.0 -info: - termsOfService: http://example.com/terms/ - contact: - name: API Support - email: support@example.com - url: http://example.com/support -servers: - - url: http://localhost/ - description: There's no place like home -paths: - /test/{id}: - get: - description: description for test path with id - operationId: test.WithId - parameters: - - name: id - in: path - required: true - description: The id of the test - schema: - type: integer - format: int32 - responses: - '200': - description: test"; - var workingDirectory = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName()); - var simpleDescriptionPath = Path.Combine(workingDirectory) + "description.yaml"; - await File.WriteAllTextAsync(simpleDescriptionPath, simpleDescriptionContent); - var mockLogger = new Mock>(); - var openAPIDocumentDS = new OpenApiDocumentDownloadService(_httpClient, mockLogger.Object); - var outputDirectory = Path.Combine(workingDirectory, "output"); - Directory.CreateDirectory(outputDirectory); - var preExistingManifestContents = @"{ - ""$schema"": ""https://developer.microsoft.com/json-schemas/teams/vDevPreview/MicrosoftTeams.schema.json"", - ""manifestVersion"": ""devPreview"", - ""version"": ""1.0.0"", - ""id"": """", - ""developer"": { - ""name"": ""Test Name"", - ""websiteUrl"": """", - ""privacyUrl"": """", - ""termsOfUseUrl"": """" - }, - ""packageName"": ""com.microsoft.kiota.plugin.client"", - ""name"": { - ""short"": ""client"", - ""full"": ""API Plugin for "" - }, - ""description"": { - ""short"": ""API Plugin for . If the description is not available, it defaults to `API Plugin for `"", - ""full"": ""API Plugin for . If the description is not available, it defaults to `API Plugin for `"" - }, - ""icons"": { - ""color"": ""color.png"", - ""outline"": ""outline.png"" - }, - ""accentColor"": ""#FFFFFF"", - ""copilotExtensions"": { - ""plugins"": [ - { - ""id"": ""client"", - ""file"": ""dummyFile.json"" - } - ], - ""declarativeCopilots"": [ - { - ""id"": ""client"", - ""file"": ""dummyFile.json"" - } - ] - } -}"; - var preExistingManifestPath = Path.Combine(outputDirectory, "manifest.json"); - await File.WriteAllTextAsync(preExistingManifestPath, preExistingManifestContents); - var generationConfiguration = new GenerationConfiguration - { - OutputPath = outputDirectory, - OpenAPIFilePath = "openapiPath", - PluginTypes = [PluginType.APIPlugin], - ClientClassName = "client", - ApiRootUrl = "http://localhost/", //Kiota builder would set this for us - }; - var (openAPIDocumentStream, _) = await openAPIDocumentDS.LoadStreamAsync(simpleDescriptionPath, generationConfiguration, null, false); - var openApiDocument = await openAPIDocumentDS.GetDocumentFromStreamAsync(openAPIDocumentStream, generationConfiguration); - KiotaBuilder.CleanupOperationIdForPlugins(openApiDocument); - var urlTreeNode = OpenApiUrlTreeNode.Create(openApiDocument, Constants.DefaultOpenApiLabel); - - // Assert manifest exists before generation and is parsable - Assert.True(File.Exists(Path.Combine(outputDirectory, "manifest.json"))); - var originalManifestFile = await File.ReadAllTextAsync(Path.Combine(outputDirectory, AppManifestFileName)); - var originalAppManifestModelObject = JsonSerializer.Deserialize(originalManifestFile, PluginsGenerationService.AppManifestModelGenerationContext.AppManifestModel); - Assert.Equal("com.microsoft.kiota.plugin.client", originalAppManifestModelObject.PackageName);// package was present - Assert.NotNull(originalAppManifestModelObject.CopilotExtensions); - Assert.NotNull(originalAppManifestModelObject.CopilotExtensions.Plugins); - Assert.Single(originalAppManifestModelObject.CopilotExtensions.Plugins);//one plugin present - Assert.Equal("dummyFile.json", originalAppManifestModelObject.CopilotExtensions.Plugins[0].File); // no plugins present - Assert.NotNull(originalAppManifestModelObject.CopilotExtensions.DeclarativeCopilots); - Assert.Single(originalAppManifestModelObject.CopilotExtensions.DeclarativeCopilots);// one declarative copilot present - Assert.Equal("dummyFile.json", originalAppManifestModelObject.CopilotExtensions.DeclarativeCopilots[0].File); // no plugins present - - // Run the plugin generation - var pluginsGenerationService = new PluginsGenerationService(openApiDocument, urlTreeNode, generationConfiguration, workingDirectory); - await pluginsGenerationService.GenerateManifestAsync(); - - Assert.True(File.Exists(Path.Combine(outputDirectory, ManifestFileName))); - Assert.True(File.Exists(Path.Combine(outputDirectory, OpenApiFileName))); - Assert.True(File.Exists(Path.Combine(outputDirectory, "manifest.json")));// Assert manifest exists after generation - - // Validate the manifest file - var appManifestFile = await File.ReadAllTextAsync(Path.Combine(outputDirectory, AppManifestFileName)); - var appManifestModelObject = JsonSerializer.Deserialize(appManifestFile, PluginsGenerationService.AppManifestModelGenerationContext.AppManifestModel); - Assert.Equal("com.microsoft.kiota.plugin.client", originalAppManifestModelObject.PackageName);// package was present - Assert.Equal("client", appManifestModelObject.Name.ShortName); // app name is same - Assert.Equal("Test Name", originalAppManifestModelObject.Developer.Name); // developer name is same - Assert.Equal("client", appManifestModelObject.CopilotExtensions.Plugins[0].Id); - Assert.Equal(ManifestFileName, appManifestModelObject.CopilotExtensions.Plugins[0].File);// file name is updated - Assert.Single(appManifestModelObject.CopilotExtensions.DeclarativeCopilots);// we didn't erase the existing declarative copilots - Assert.Equal("dummyFile.json", appManifestModelObject.CopilotExtensions.DeclarativeCopilots[0].File); // no plugins present - } - [Fact] - public async Task DoesNotGenerateEmptyPluginOrDeclarativeCopilots() - { - var manifestModel = new AppManifestModel - { - CopilotExtensions = new CopilotExtensions - { - } - }; - - using var appManifestStream = new MemoryStream(); - await JsonSerializer.SerializeAsync(appManifestStream, manifestModel, PluginsGenerationService.AppManifestModelGenerationContext.AppManifestModel); - appManifestStream.Seek(0, SeekOrigin.Begin); - var stringRepresentation = await new StreamReader(appManifestStream).ReadToEndAsync(); - - Assert.DoesNotContain("\"plugins\":", stringRepresentation); - Assert.DoesNotContain("\"declarativeCopilots\":", stringRepresentation); - } [Fact] public async Task GeneratesManifestAndCleansUpInputDescription() { From b437d83c1e81d43be1ca93011260bc936469e04f Mon Sep 17 00:00:00 2001 From: Andrew Omondi Date: Mon, 19 Aug 2024 16:14:39 +0300 Subject: [PATCH 4/5] fixes: merge errors and validates reverted changes --- src/Kiota.Builder/Plugins/PluginsGenerationService.cs | 4 ++-- .../Plugins/PluginsGenerationServiceTests.cs | 7 +++++-- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/Kiota.Builder/Plugins/PluginsGenerationService.cs b/src/Kiota.Builder/Plugins/PluginsGenerationService.cs index 4cff5d1560..78c2035864 100644 --- a/src/Kiota.Builder/Plugins/PluginsGenerationService.cs +++ b/src/Kiota.Builder/Plugins/PluginsGenerationService.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.IO; using System.Linq; @@ -100,8 +100,8 @@ public async Task GenerateManifestAsync(CancellationToken cancellationToken = de } } - private static partial Regex PluginNameCleanupRegex(); [GeneratedRegex(@"[^a-zA-Z0-9_]+", RegexOptions.IgnoreCase | RegexOptions.Singleline, 2000)] + private static partial Regex PluginNameCleanupRegex(); private OpenApiDocument GetDocumentWithTrimmedComponentsAndResponses(OpenApiDocument doc) { diff --git a/tests/Kiota.Builder.Tests/Plugins/PluginsGenerationServiceTests.cs b/tests/Kiota.Builder.Tests/Plugins/PluginsGenerationServiceTests.cs index 4f586fc3e5..9e3a3bd400 100644 --- a/tests/Kiota.Builder.Tests/Plugins/PluginsGenerationServiceTests.cs +++ b/tests/Kiota.Builder.Tests/Plugins/PluginsGenerationServiceTests.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.IO; using System.Linq; using System.Net.Http; @@ -92,7 +92,10 @@ public async Task GeneratesManifest(string inputPluginName, string expectedPlugi Assert.True(File.Exists(Path.Combine(outputDirectory, $"{expectedPluginName.ToLower()}-apiplugin.json"))); Assert.True(File.Exists(Path.Combine(outputDirectory, $"{expectedPluginName.ToLower()}-apimanifest.json"))); Assert.True(File.Exists(Path.Combine(outputDirectory, OpenAIPluginFileName))); - Assert.True(File.Exists(Path.Combine(outputDirectory, OpenApiFileName))); + Assert.True(File.Exists(Path.Combine(outputDirectory, $"{expectedPluginName.ToLower()}-openapi.yml"))); + Assert.False(File.Exists(Path.Combine(outputDirectory, "manifest.json"))); + Assert.False(File.Exists(Path.Combine(outputDirectory, "color.png"))); + Assert.False(File.Exists(Path.Combine(outputDirectory, "outline.png"))); // Validate the v2 plugin var manifestContent = await File.ReadAllTextAsync(Path.Combine(outputDirectory, $"{expectedPluginName.ToLower()}-apiplugin.json")); From 5c442ea880a6d0673f52b748dd000ec41dac43a3 Mon Sep 17 00:00:00 2001 From: Andrew Omondi Date: Mon, 19 Aug 2024 16:18:38 +0300 Subject: [PATCH 5/5] fix: restore version downgrade on revert --- src/Kiota.Builder/Kiota.Builder.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Kiota.Builder/Kiota.Builder.csproj b/src/Kiota.Builder/Kiota.Builder.csproj index 2f5eaefb64..119b4bcef8 100644 --- a/src/Kiota.Builder/Kiota.Builder.csproj +++ b/src/Kiota.Builder/Kiota.Builder.csproj @@ -49,7 +49,7 @@ - +