diff --git a/Saunter.sln b/Saunter.sln index 85c435a4..60ff6a88 100644 --- a/Saunter.sln +++ b/Saunter.sln @@ -12,6 +12,9 @@ EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Saunter.Tests", "test\Saunter.Tests\Saunter.Tests.csproj", "{3ADB27EF-7C80-40EB-AFC6-5D06D415FFAB}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "examples", "examples", "{6ABD4842-47AF-49A5-B057-0EBA64416789}" + ProjectSection(SolutionItems) = preProject + examples\.gitignore = examples\.gitignore + EndProjectSection EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "StreetlightsAPI", "examples\StreetlightsAPI\StreetlightsAPI.csproj", "{F188D4A7-BBCB-464F-A370-2BD84D18EA79}" EndProject @@ -48,6 +51,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AsyncAPI.Saunter.Generator. EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AsyncAPI.Saunter.Generator.Cli.Tests", "test\AsyncAPI.Saunter.Generator.Cli.Tests\AsyncAPI.Saunter.Generator.Cli.Tests.csproj", "{18AD0249-0436-4A26-9972-B97BA6905A54}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "StreetlightsAPI.TopLevelStatement", "examples\StreetlightsAPI.TopLevelStatement\StreetlightsAPI.TopLevelStatement.csproj", "{6F6B8B03-9045-46EC-AE12-E7ADA492F9FA}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -142,6 +147,18 @@ Global {18AD0249-0436-4A26-9972-B97BA6905A54}.Release|x64.Build.0 = Release|Any CPU {18AD0249-0436-4A26-9972-B97BA6905A54}.Release|x86.ActiveCfg = Release|Any CPU {18AD0249-0436-4A26-9972-B97BA6905A54}.Release|x86.Build.0 = Release|Any CPU + {6F6B8B03-9045-46EC-AE12-E7ADA492F9FA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {6F6B8B03-9045-46EC-AE12-E7ADA492F9FA}.Debug|Any CPU.Build.0 = Debug|Any CPU + {6F6B8B03-9045-46EC-AE12-E7ADA492F9FA}.Debug|x64.ActiveCfg = Debug|Any CPU + {6F6B8B03-9045-46EC-AE12-E7ADA492F9FA}.Debug|x64.Build.0 = Debug|Any CPU + {6F6B8B03-9045-46EC-AE12-E7ADA492F9FA}.Debug|x86.ActiveCfg = Debug|Any CPU + {6F6B8B03-9045-46EC-AE12-E7ADA492F9FA}.Debug|x86.Build.0 = Debug|Any CPU + {6F6B8B03-9045-46EC-AE12-E7ADA492F9FA}.Release|Any CPU.ActiveCfg = Release|Any CPU + {6F6B8B03-9045-46EC-AE12-E7ADA492F9FA}.Release|Any CPU.Build.0 = Release|Any CPU + {6F6B8B03-9045-46EC-AE12-E7ADA492F9FA}.Release|x64.ActiveCfg = Release|Any CPU + {6F6B8B03-9045-46EC-AE12-E7ADA492F9FA}.Release|x64.Build.0 = Release|Any CPU + {6F6B8B03-9045-46EC-AE12-E7ADA492F9FA}.Release|x86.ActiveCfg = Release|Any CPU + {6F6B8B03-9045-46EC-AE12-E7ADA492F9FA}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -156,6 +173,7 @@ Global {E8FACA22-CFED-4710-89E4-D55F31BF96B3} = {D8CB9C0D-9605-457B-979F-C8994B20A926} {6C102D4D-3DA4-4763-B75E-C15E33E7E94A} = {28D4C365-FDED-49AE-A97D-36202E24A55A} {18AD0249-0436-4A26-9972-B97BA6905A54} = {6491E321-2D02-44AB-9116-D722FE169595} + {6F6B8B03-9045-46EC-AE12-E7ADA492F9FA} = {6ABD4842-47AF-49A5-B057-0EBA64416789} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {2F85D9DA-DBCF-4F13-8C42-5719F1469B2E} diff --git a/examples/.gitignore b/examples/.gitignore new file mode 100644 index 00000000..f91a1165 --- /dev/null +++ b/examples/.gitignore @@ -0,0 +1,4 @@ +specs/ +streetlights.json +streetlights.yml +streetlights.yaml \ No newline at end of file diff --git a/examples/StreetlightsAPI.TopLevelStatement/Program.cs b/examples/StreetlightsAPI.TopLevelStatement/Program.cs new file mode 100644 index 00000000..79aa9229 --- /dev/null +++ b/examples/StreetlightsAPI.TopLevelStatement/Program.cs @@ -0,0 +1,76 @@ +using System.Linq; +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Http; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; +using NLog; +using NLog.Web; +using Saunter; +using Saunter.AsyncApiSchema.v2; +using StreetlightsAPI; + +LogManager.Setup().LoadConfigurationFromAppSettings(); + +var builder = WebApplication.CreateBuilder(args); +builder.Host.ConfigureLogging(logging => logging.AddSimpleConsole(console => console.SingleLine = true)); +builder.Host.UseNLog(); + +// Add Saunter to the application services. +builder.Services.AddAsyncApiSchemaGeneration(options => +{ + options.AssemblyMarkerTypes = [typeof(StreetlightMessageBus)]; + + options.Middleware.UiTitle = "Streetlights API"; + + options.AsyncApi = new AsyncApiDocument + { + Info = new Info("Streetlights API", "1.0.0") + { + Description = "The Smartylighting Streetlights API allows you to remotely manage the city lights.", + License = new License("Apache 2.0") + { + Url = "https://www.apache.org/licenses/LICENSE-2.0" + } + }, + Servers = + { + ["mosquitto"] = new Server("test.mosquitto.org", "mqtt"), + ["webapi"] = new Server("localhost:5000", "http"), + }, + }; +}); + +builder.Services.AddScoped(); +builder.Services.AddControllers(); + +var app = builder.Build(); + +app.UseDeveloperExceptionPage(); + +app.UseRouting(); +app.UseCors(configure => configure.AllowAnyOrigin().AllowAnyMethod()); + +app.UseEndpoints(endpoints => +{ + endpoints.MapAsyncApiDocuments(); + endpoints.MapAsyncApiUi(); + + endpoints.MapControllers(); +}); + +await app.StartAsync(); + +// Print the AsyncAPI doc location +var logger = app.Services.GetService().CreateLogger(); +var options = app.Services.GetService>(); +var addresses = app.Urls; +logger.LogInformation("AsyncAPI doc available at: {URL}", $"{addresses.FirstOrDefault()}{options.Value.Middleware.Route}"); +logger.LogInformation("AsyncAPI UI available at: {URL}", $"{addresses.FirstOrDefault()}{options.Value.Middleware.UiBaseRoute}"); + +// Redirect base url to AsyncAPI UI +app.Map("/", () => Results.Redirect("index.html")); +app.Map("/index.html", () => Results.Redirect(options.Value.Middleware.UiBaseRoute)); + +await app.WaitForShutdownAsync(); diff --git a/examples/StreetlightsAPI.TopLevelStatement/StreetlightsAPI.TopLevelStatement.csproj b/examples/StreetlightsAPI.TopLevelStatement/StreetlightsAPI.TopLevelStatement.csproj new file mode 100644 index 00000000..4e4dfcc0 --- /dev/null +++ b/examples/StreetlightsAPI.TopLevelStatement/StreetlightsAPI.TopLevelStatement.csproj @@ -0,0 +1,46 @@ + + + + + net8.0 + false + + + true + json,yml + streetlights.{extension} + specs + + + + bin\Debug\StreetlightsAPI.TopLevelStatement.xml + 1701;1702;1591 + + + + bin\Release\StreetlightsAPI.TopLevelStatement.xml + 1701;1702;1591 + + + + + + + + + + + + + + PreserveNewest + + + + + + + + + diff --git a/examples/StreetlightsAPI.TopLevelStatement/appsettings.json b/examples/StreetlightsAPI.TopLevelStatement/appsettings.json new file mode 100644 index 00000000..b4f6487b --- /dev/null +++ b/examples/StreetlightsAPI.TopLevelStatement/appsettings.json @@ -0,0 +1,19 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft": "Warning", + "Microsoft.Hosting.Lifetime": "Information" + } + }, + + "AllowedHosts": "*", + + "Kestrel": { + "EndPoints": { + "Http": { + "Url": "http://localhost:5001" + } + } + } +} diff --git a/examples/StreetlightsAPI/Program.cs b/examples/StreetlightsAPI/Program.cs index aa3f77ad..9afd805e 100644 --- a/examples/StreetlightsAPI/Program.cs +++ b/examples/StreetlightsAPI/Program.cs @@ -6,6 +6,8 @@ using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; +using NLog; +using NLog.Web; using Saunter; using Saunter.AsyncApiSchema.v2; @@ -15,6 +17,8 @@ public class Program { public static void Main(string[] args) { + LogManager.Setup().LoadConfigurationFromAppSettings(); + CreateHostBuilder(args).Build().Run(); } @@ -22,10 +26,11 @@ public static IHostBuilder CreateHostBuilder(string[] args) { return Host.CreateDefaultBuilder(args) .ConfigureLogging(logging => logging.AddSimpleConsole(console => console.SingleLine = true)) + .UseNLog() .ConfigureWebHostDefaults(web => { web.UseStartup(); - web.UseUrls("http://localhost:5000"); + web.UseUrls("http://localhost:5001"); }); } } diff --git a/examples/StreetlightsAPI/StreetlightsAPI.csproj b/examples/StreetlightsAPI/StreetlightsAPI.csproj index 43f0b54f..ab72e944 100644 --- a/examples/StreetlightsAPI/StreetlightsAPI.csproj +++ b/examples/StreetlightsAPI/StreetlightsAPI.csproj @@ -1,6 +1,8 @@  + net6.0 false @@ -19,4 +21,17 @@ + + + + + PreserveNewest + + + + + + + + diff --git a/examples/StreetlightsAPI/nlog.config b/examples/StreetlightsAPI/nlog.config new file mode 100644 index 00000000..dd855146 --- /dev/null +++ b/examples/StreetlightsAPI/nlog.config @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/AsyncAPI.Saunter.Generator.Cli/AsyncAPI.Saunter.Generator.Cli.csproj b/src/AsyncAPI.Saunter.Generator.Cli/AsyncAPI.Saunter.Generator.Cli.csproj index e510838e..6ab8e1ae 100644 --- a/src/AsyncAPI.Saunter.Generator.Cli/AsyncAPI.Saunter.Generator.Cli.csproj +++ b/src/AsyncAPI.Saunter.Generator.Cli/AsyncAPI.Saunter.Generator.Cli.csproj @@ -6,6 +6,7 @@ enable 12 AsyncAPI.Saunter.Generator.Cli + $(NoWarn);EF1001 AsyncAPI Command Line Tools: Dotnet tool to generate AsyncAPI spec file from dotnet startup assembly. AsyncAPI Initiative @@ -40,8 +41,8 @@ all runtime; build; native; contentfiles; analyzers; buildtransitive + - diff --git a/src/AsyncAPI.Saunter.Generator.Cli/ToFile/DependencyResolver.cs b/src/AsyncAPI.Saunter.Generator.Cli/ToFile/DependencyResolver.cs new file mode 100644 index 00000000..3d6d010a --- /dev/null +++ b/src/AsyncAPI.Saunter.Generator.Cli/ToFile/DependencyResolver.cs @@ -0,0 +1,22 @@ +using System.Reflection; + +namespace AsyncAPI.Saunter.Generator.Cli.ToFile; + +internal static class DependencyResolver +{ + public static void Init(string startupAssemblyBasePath) + { + AppDomain.CurrentDomain.AssemblyResolve += (sender, args) => + { + var requestedAssembly = new AssemblyName(args.Name); + var fullPath = Path.Combine(startupAssemblyBasePath, $"{requestedAssembly.Name}.dll"); + if (File.Exists(fullPath)) + { + var assembly = Assembly.LoadFile(fullPath); + return assembly; + } + Console.WriteLine($"Could not resolve assembly: {args.Name}, requested by {args.RequestingAssembly?.FullName}"); + return default; + }; + } +} diff --git a/src/AsyncAPI.Saunter.Generator.Cli/ToFile/ServiceProviderBuilder.cs b/src/AsyncAPI.Saunter.Generator.Cli/ToFile/ServiceProviderBuilder.cs index 69bde4f2..eed4c58b 100644 --- a/src/AsyncAPI.Saunter.Generator.Cli/ToFile/ServiceProviderBuilder.cs +++ b/src/AsyncAPI.Saunter.Generator.Cli/ToFile/ServiceProviderBuilder.cs @@ -1,5 +1,6 @@ -using System.Reflection; -using System.Runtime.Loader; +using System.Runtime.Loader; +using Microsoft.EntityFrameworkCore.Design; +using Microsoft.EntityFrameworkCore.Design.Internal; using Microsoft.Extensions.Logging; namespace AsyncAPI.Saunter.Generator.Cli.ToFile; @@ -13,12 +14,20 @@ internal class ServiceProviderBuilder(ILogger logger) : { public IServiceProvider BuildServiceProvider(string startupAssembly) { - var fullPath = Path.GetFullPath(Path.Combine(Directory.GetCurrentDirectory(), startupAssembly)); + var fullPath = Path.GetFullPath(startupAssembly); + var basePath = Path.GetDirectoryName(fullPath); + DependencyResolver.Init(basePath); + logger.LogInformation($"Loading startup assembly: {fullPath}"); var assembly = AssemblyLoadContext.Default.LoadFromAssemblyPath(fullPath); - var nswagCommandsAssembly = Assembly.LoadFrom("NSwag.Commands.dll"); - var nswagServiceProvider = nswagCommandsAssembly.GetType("NSwag.Commands.ServiceProviderResolver"); - var serviceProvider = (IServiceProvider)nswagServiceProvider.InvokeMember("GetServiceProvider", BindingFlags.InvokeMethod | BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static, null, null, [assembly]); + var reporter = new OperationReporter(new OperationReportHandler( + m => logger.LogError(m), + m => logger.LogWarning(m), + m => logger.LogInformation(m), + m => logger.LogDebug(m))); + var appServiceProvider = new AppServiceProviderFactory(assembly, reporter); + var serviceProvider = appServiceProvider.Create([]); + return serviceProvider; } } diff --git a/test/AsyncAPI.Saunter.Generator.Cli.Tests/AsyncAPI.Saunter.Generator.Cli.Tests.csproj b/test/AsyncAPI.Saunter.Generator.Cli.Tests/AsyncAPI.Saunter.Generator.Cli.Tests.csproj index 6704dac9..ad8e79fc 100644 --- a/test/AsyncAPI.Saunter.Generator.Cli.Tests/AsyncAPI.Saunter.Generator.Cli.Tests.csproj +++ b/test/AsyncAPI.Saunter.Generator.Cli.Tests/AsyncAPI.Saunter.Generator.Cli.Tests.csproj @@ -31,4 +31,13 @@ + + + PreserveNewest + + + PreserveNewest + + + diff --git a/test/AsyncAPI.Saunter.Generator.Cli.Tests/IntegrationTests.cs b/test/AsyncAPI.Saunter.Generator.Cli.Tests/IntegrationTests.cs index e7751ac3..52cb62e7 100644 --- a/test/AsyncAPI.Saunter.Generator.Cli.Tests/IntegrationTests.cs +++ b/test/AsyncAPI.Saunter.Generator.Cli.Tests/IntegrationTests.cs @@ -50,186 +50,36 @@ Retrieves AsyncAPI spec from a startup assembly and writes to file. """, StringCompareShould.IgnoreLineEndings); } - [Fact] - public void StreetlightsAPIExportSpecTest() + /// + /// Both example projects are used to check whether AsyncAPI spec generation is working because they are targeting different .NET versions and are using different hosting strategies. + /// - StreetlightsAPI project is targeting NET6 using the 'old school' Startup-class hosting mechanism. + /// - StreetlightsAPI.TopLevelStatement project is targeting NET8 using the new Top Level Statement hosting mechanism. + /// + [Theory] + [InlineData("StreetlightsAPI", "net6.0")] + [InlineData("StreetlightsAPI.TopLevelStatement", "net8.0")] + public void Streetlights_ExportSpecTest(string csprojName, string targetFramework) { - var path = Directory.GetCurrentDirectory(); + var path = Path.Combine(Directory.GetCurrentDirectory(), csprojName); output.WriteLine($"Output path: {path}"); - var stdOut = RunTool($"tofile ../../../../../examples/StreetlightsAPI/bin/Debug/net6.0/StreetlightsAPI.dll --output {path} --format json,yml,yaml"); + var stdOut = RunTool($"tofile ../../../../../examples/{csprojName}/bin/Debug/{targetFramework}/{csprojName}.dll --output {path} --format json,yml,yaml"); stdOut.ShouldNotBeEmpty(); stdOut.ShouldContain($"AsyncAPI yaml successfully written to {Path.Combine(path, "asyncapi.yaml")}"); stdOut.ShouldContain($"AsyncAPI yml successfully written to {Path.Combine(path, "asyncapi.yml")}"); stdOut.ShouldContain($"AsyncAPI json successfully written to {Path.Combine(path, "asyncapi.json")}"); - File.Exists("asyncapi.yml").ShouldBeTrue("asyncapi.yml"); - File.Exists("asyncapi.yaml").ShouldBeTrue("asyncapi.yaml"); - File.Exists("asyncapi.json").ShouldBeTrue("asyncapi.json"); + File.Exists(Path.Combine(csprojName, "asyncapi.yml")).ShouldBeTrue("asyncapi.yml"); + File.Exists(Path.Combine(csprojName, "asyncapi.yaml")).ShouldBeTrue("asyncapi.yaml"); + File.Exists(Path.Combine(csprojName, "asyncapi.json")).ShouldBeTrue("asyncapi.json"); - var yml = File.ReadAllText("asyncapi.yml"); - yml.ShouldBe(""" - asyncapi: 2.6.0 - info: - title: Streetlights API - version: 1.0.0 - description: The Smartylighting Streetlights API allows you to remotely manage the city lights. - license: - name: Apache 2.0 - url: https://www.apache.org/licenses/LICENSE-2.0 - servers: - mosquitto: - url: test.mosquitto.org - protocol: mqtt - webapi: - url: localhost:5000 - protocol: http - defaultContentType: application/json - channels: - publish/light/measured: - servers: - - webapi - publish: - operationId: MeasureLight - summary: Inform about environmental lighting conditions for a particular streetlight. - tags: - - name: Light - message: - $ref: '#/components/messages/lightMeasuredEvent' - subscribe/light/measured: - servers: - - mosquitto - subscribe: - operationId: PublishLightMeasurement - summary: Subscribe to environmental lighting conditions for a particular streetlight. - tags: - - name: Light - message: - payload: - $ref: '#/components/schemas/lightMeasuredEvent' - components: - schemas: - lightMeasuredEvent: - type: object - properties: - id: - type: integer - format: int32 - description: Id of the streetlight. - lumens: - type: integer - format: int32 - description: Light intensity measured in lumens. - sentAt: - type: string - format: date-time - description: Light intensity measured in lumens. - additionalProperties: false - messages: - lightMeasuredEvent: - payload: - $ref: '#/components/schemas/lightMeasuredEvent' - name: lightMeasuredEvent - """, "yaml"); + var yml = File.ReadAllText(Path.Combine(csprojName, "asyncapi.yml")); + yml.ShouldBe(ExpectedSpecFiles.Yml_v2_6, "yml"); - var yaml = File.ReadAllText("asyncapi.yaml"); - yaml.ShouldBe(yml, "yml"); + var yaml = File.ReadAllText(Path.Combine(csprojName, "asyncapi.yaml")); + yaml.ShouldBe(yml, "yaml"); - var json = File.ReadAllText("asyncapi.json"); - json.ShouldBe(""" - { - "asyncapi": "2.6.0", - "info": { - "title": "Streetlights API", - "version": "1.0.0", - "description": "The Smartylighting Streetlights API allows you to remotely manage the city lights.", - "license": { - "name": "Apache 2.0", - "url": "https://www.apache.org/licenses/LICENSE-2.0" - } - }, - "servers": { - "mosquitto": { - "url": "test.mosquitto.org", - "protocol": "mqtt" - }, - "webapi": { - "url": "localhost:5000", - "protocol": "http" - } - }, - "defaultContentType": "application/json", - "channels": { - "publish/light/measured": { - "servers": [ - "webapi" - ], - "publish": { - "operationId": "MeasureLight", - "summary": "Inform about environmental lighting conditions for a particular streetlight.", - "tags": [ - { - "name": "Light" - } - ], - "message": { - "$ref": "#/components/messages/lightMeasuredEvent" - } - } - }, - "subscribe/light/measured": { - "servers": [ - "mosquitto" - ], - "subscribe": { - "operationId": "PublishLightMeasurement", - "summary": "Subscribe to environmental lighting conditions for a particular streetlight.", - "tags": [ - { - "name": "Light" - } - ], - "message": { - "payload": { - "$ref": "#/components/schemas/lightMeasuredEvent" - } - } - } - } - }, - "components": { - "schemas": { - "lightMeasuredEvent": { - "type": "object", - "properties": { - "id": { - "type": "integer", - "format": "int32", - "description": "Id of the streetlight." - }, - "lumens": { - "type": "integer", - "format": "int32", - "description": "Light intensity measured in lumens." - }, - "sentAt": { - "type": "string", - "format": "date-time", - "description": "Light intensity measured in lumens." - } - }, - "additionalProperties": false - } - }, - "messages": { - "lightMeasuredEvent": { - "payload": { - "$ref": "#/components/schemas/lightMeasuredEvent" - }, - "name": "lightMeasuredEvent" - } - } - } - } - """, "json"); + var json = File.ReadAllText(Path.Combine(csprojName, "asyncapi.json")); + json.ShouldBe(ExpectedSpecFiles.Json_v2_6, "json"); } } diff --git a/test/AsyncAPI.Saunter.Generator.Cli.Tests/Specs/ExpectedSpecFiles.cs b/test/AsyncAPI.Saunter.Generator.Cli.Tests/Specs/ExpectedSpecFiles.cs new file mode 100644 index 00000000..aa6ed033 --- /dev/null +++ b/test/AsyncAPI.Saunter.Generator.Cli.Tests/Specs/ExpectedSpecFiles.cs @@ -0,0 +1,12 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +namespace AsyncAPI.Saunter.Generator.Cli.Tests; + +public static class ExpectedSpecFiles +{ + public static string Json_v2_6 => File.ReadAllText("Specs/streetlights_v2.6.json"); + + public static string Yml_v2_6 => File.ReadAllText("Specs/streetlights_v2.6.yml"); +} diff --git a/test/AsyncAPI.Saunter.Generator.Cli.Tests/Specs/streetlights_v2.6.json b/test/AsyncAPI.Saunter.Generator.Cli.Tests/Specs/streetlights_v2.6.json new file mode 100644 index 00000000..8a429cbb --- /dev/null +++ b/test/AsyncAPI.Saunter.Generator.Cli.Tests/Specs/streetlights_v2.6.json @@ -0,0 +1,94 @@ +{ + "asyncapi": "2.6.0", + "info": { + "title": "Streetlights API", + "version": "1.0.0", + "description": "The Smartylighting Streetlights API allows you to remotely manage the city lights.", + "license": { + "name": "Apache 2.0", + "url": "https://www.apache.org/licenses/LICENSE-2.0" + } + }, + "servers": { + "mosquitto": { + "url": "test.mosquitto.org", + "protocol": "mqtt" + }, + "webapi": { + "url": "localhost:5000", + "protocol": "http" + } + }, + "defaultContentType": "application/json", + "channels": { + "publish/light/measured": { + "servers": [ + "webapi" + ], + "publish": { + "operationId": "MeasureLight", + "summary": "Inform about environmental lighting conditions for a particular streetlight.", + "tags": [ + { + "name": "Light" + } + ], + "message": { + "$ref": "#/components/messages/lightMeasuredEvent" + } + } + }, + "subscribe/light/measured": { + "servers": [ + "mosquitto" + ], + "subscribe": { + "operationId": "PublishLightMeasurement", + "summary": "Subscribe to environmental lighting conditions for a particular streetlight.", + "tags": [ + { + "name": "Light" + } + ], + "message": { + "payload": { + "$ref": "#/components/schemas/lightMeasuredEvent" + } + } + } + } + }, + "components": { + "schemas": { + "lightMeasuredEvent": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "format": "int32", + "description": "Id of the streetlight." + }, + "lumens": { + "type": "integer", + "format": "int32", + "description": "Light intensity measured in lumens." + }, + "sentAt": { + "type": "string", + "format": "date-time", + "description": "Light intensity measured in lumens." + } + }, + "additionalProperties": false + } + }, + "messages": { + "lightMeasuredEvent": { + "payload": { + "$ref": "#/components/schemas/lightMeasuredEvent" + }, + "name": "lightMeasuredEvent" + } + } + } +} \ No newline at end of file diff --git a/test/AsyncAPI.Saunter.Generator.Cli.Tests/Specs/streetlights_v2.6.yml b/test/AsyncAPI.Saunter.Generator.Cli.Tests/Specs/streetlights_v2.6.yml new file mode 100644 index 00000000..efccd7ed --- /dev/null +++ b/test/AsyncAPI.Saunter.Generator.Cli.Tests/Specs/streetlights_v2.6.yml @@ -0,0 +1,61 @@ +asyncapi: 2.6.0 +info: + title: Streetlights API + version: 1.0.0 + description: The Smartylighting Streetlights API allows you to remotely manage the city lights. + license: + name: Apache 2.0 + url: https://www.apache.org/licenses/LICENSE-2.0 +servers: + mosquitto: + url: test.mosquitto.org + protocol: mqtt + webapi: + url: localhost:5000 + protocol: http +defaultContentType: application/json +channels: + publish/light/measured: + servers: + - webapi + publish: + operationId: MeasureLight + summary: Inform about environmental lighting conditions for a particular streetlight. + tags: + - name: Light + message: + $ref: '#/components/messages/lightMeasuredEvent' + subscribe/light/measured: + servers: + - mosquitto + subscribe: + operationId: PublishLightMeasurement + summary: Subscribe to environmental lighting conditions for a particular streetlight. + tags: + - name: Light + message: + payload: + $ref: '#/components/schemas/lightMeasuredEvent' +components: + schemas: + lightMeasuredEvent: + type: object + properties: + id: + type: integer + format: int32 + description: Id of the streetlight. + lumens: + type: integer + format: int32 + description: Light intensity measured in lumens. + sentAt: + type: string + format: date-time + description: Light intensity measured in lumens. + additionalProperties: false + messages: + lightMeasuredEvent: + payload: + $ref: '#/components/schemas/lightMeasuredEvent' + name: lightMeasuredEvent \ No newline at end of file