Skip to content

Commit

Permalink
asyncapi#196 renamed tool to make up a more logical name, fixed empty…
Browse files Browse the repository at this point in the history
… parameter handling
  • Loading branch information
Senn Geerts authored and Senn Geerts committed Jul 7, 2024
1 parent f0af6d1 commit 1ebb77c
Show file tree
Hide file tree
Showing 9 changed files with 37 additions and 38 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFrameworks>net8.0;net6.0</TargetFrameworks>
<TargetFrameworks>net6.0;net8.0</TargetFrameworks>
<ImplicitUsings>enable</ImplicitUsings>
<LangVersion>12</LangVersion>
<RootNamespace>AsyncAPI.Saunter.Generator.Cli</RootNamespace>
Expand All @@ -11,7 +11,7 @@
<Authors>AsyncAPI Initiative</Authors>
<PackAsTool>true</PackAsTool>
<PackageId>AsyncAPI.Saunter.Generator.Cli</PackageId>
<ToolCommandName>AsyncAPI.NET</ToolCommandName>
<ToolCommandName>dotnet-asyncapi</ToolCommandName>
<PackageTags>asyncapi;aspnetcore;openapi;documentation;amqp;generator;cli;tool</PackageTags>
<PackageReadmeFile>readme.md</PackageReadmeFile>
<PackageIcon>logo.png</PackageIcon>
Expand All @@ -23,6 +23,7 @@
<PackageRequireLicenseAcceptance>false</PackageRequireLicenseAcceptance>
<IncludeSymbols>true</IncludeSymbols>
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
<Version>1.0.1</Version>
</PropertyGroup>

<ItemGroup Condition=" '$(TargetFramework)' != 'netstandard2.0' ">
Expand Down
2 changes: 1 addition & 1 deletion src/AsyncAPI.Saunter.Generator.Cli/Commands/Tofile.cs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,6 @@ internal static Func<IDictionary<string, string>, int> Run(string[] args) => nam

private static string EscapePath(string path)
{
return path.Contains(' ') ? "\"" + path + "\"" : path;
return (path.Contains(' ') || string.IsNullOrWhiteSpace(path)) ? "\"" + path + "\"" : path;
}
}
19 changes: 8 additions & 11 deletions src/AsyncAPI.Saunter.Generator.Cli/Commands/TofileInternal.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
using Saunter.AsyncApiSchema.v2;
using static Program;
using AsyncApiDocument = Saunter.AsyncApiSchema.v2.AsyncApiDocument;
using System.IO;

namespace AsyncApi.Saunter.Generator.Cli.Commands;

Expand All @@ -31,7 +32,7 @@ internal static int Run(IDictionary<string, string> namedArgs)
var startupAssembly = AssemblyLoadContext.Default.LoadFromAssemblyPath(Path.Combine(Directory.GetCurrentDirectory(), namedArgs[StartupAssemblyArgument]));

// 2) Build a service container that's based on the startup assembly
var envVars = namedArgs.TryGetValue(EnvOption, out var x) ? x.Split(',').Select(x => x.Trim()) : Array.Empty<string>();
var envVars = (namedArgs.TryGetValue(EnvOption, out var x) && !string.IsNullOrWhiteSpace(x)) ? x.Split(',').Select(x => x.Trim()) : Array.Empty<string>();
foreach (var envVar in envVars.Select(x => x.Split('=').Select(x => x.Trim()).ToList()))
{
if (envVar.Count == 2)
Expand All @@ -50,9 +51,9 @@ internal static int Run(IDictionary<string, string> namedArgs)
var asyncapiOptions = serviceProvider.GetService<IOptions<AsyncApiOptions>>().Value;
var documentSerializer = serviceProvider.GetRequiredService<IAsyncApiDocumentSerializer>();

var documentNames = namedArgs.TryGetValue(DocOption, out var doc) ? [doc] : asyncapiOptions.NamedApis.Keys;
var fileTemplate = namedArgs.TryGetValue(FileNameOption, out var template) ? template : "{document}_asyncapi.{extension}";
if (documentNames.Count == 0)
var documentNames = (namedArgs.TryGetValue(DocOption, out var doc) && !string.IsNullOrWhiteSpace(doc)) ? [doc] : asyncapiOptions.NamedApis.Keys;
var fileTemplate = (namedArgs.TryGetValue(FileNameOption, out var template) && !string.IsNullOrWhiteSpace(template)) ? template : "{document}_asyncapi.{extension}";
if (documentNames.Count == 0)
{
if (asyncapiOptions.AssemblyMarkerTypes.Any())
{
Expand Down Expand Up @@ -86,20 +87,16 @@ internal static int Run(IDictionary<string, string> namedArgs)
}

// 4) Serialize to specified output location or stdout
var outputPath = namedArgs.TryGetValue(OutputOption, out var arg1) ? Path.Combine(Directory.GetCurrentDirectory(), arg1) : null;
var outputPath = (namedArgs.TryGetValue(OutputOption, out var path) && !string.IsNullOrWhiteSpace(path)) ? Path.Combine(Directory.GetCurrentDirectory(), path) : null;
if (!string.IsNullOrEmpty(outputPath))
{
var directoryPath = Path.GetDirectoryName(outputPath);
if (!string.IsNullOrEmpty(directoryPath) && !Directory.Exists(directoryPath))
{
Directory.CreateDirectory(directoryPath);
}
Directory.CreateDirectory(outputPath);
}

var exportJson = true;
var exportYml = false;
var exportYaml = false;
if (namedArgs.TryGetValue(FormatOption, out var format))
if (namedArgs.TryGetValue(FormatOption, out var format) && !string.IsNullOrWhiteSpace(format))
{
var splitted = format.Split(',').Select(x => x.Trim()).ToList();
exportJson = splitted.Any(x => x.Equals("json", StringComparison.OrdinalIgnoreCase));
Expand Down
6 changes: 3 additions & 3 deletions src/AsyncAPI.Saunter.Generator.Cli/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,14 @@
DependencyResolver.Init();

// Helper to simplify command line parsing etc.
var runner = new CommandRunner("dotnet asyncapi.net", "AsyncAPI Command Line Tools", Console.Out);
var runner = new CommandRunner("dotnet asyncapi", "AsyncAPI Command Line Tools", Console.Out);

// NOTE: The "dotnet asyncapi tofile" command does not serve the request directly. Instead, it invokes a corresponding
// command (called _tofile) via "dotnet exec" so that the runtime configuration (*.runtimeconfig & *.deps.json) of the
// provided startupassembly can be used instead of the tool's. This is neccessary to successfully load the
// startupassembly and it's transitive dependencies. See https://github.com/dotnet/coreclr/issues/13277 for more.

// > dotnet asyncapi.net tofile ...
// > dotnet asyncapi tofile ...
runner.SubCommand("tofile", "retrieves AsyncAPI from a startup assembly, and writes to file ", c =>
{
c.Argument(StartupAssemblyArgument, "relative path to the application's startup assembly");
Expand All @@ -24,7 +24,7 @@
c.OnRun(Tofile.Run(args));
});

// > dotnet asyncapi.net _tofile ... (* should only be invoked via "dotnet exec")
// > dotnet asyncapi _tofile ... (* should only be invoked via "dotnet exec")
runner.SubCommand("_tofile", "", c =>
{
c.Argument(StartupAssemblyArgument, "");
Expand Down
23 changes: 16 additions & 7 deletions src/AsyncAPI.Saunter.Generator.Cli/readme.md
Original file line number Diff line number Diff line change
@@ -1,15 +1,24 @@
# AsyncApi Generator.Cli Tool
A dotnet tool to generate AsyncAPI specification files based of dotnet DLL (The application itself).
A dotnet tool to generate AsyncAPI specification files based of a dotnet DLL (The application itself).

## Tool usage
```
dotnet asyncapi.net tofile --output [output-path] --format [json,yml,yaml] --doc [asyncapi-document-name] [startup-assembly]
dotnet asyncapi tofile --output [output-path] --format [json,yml,yaml] --doc [asyncapi-document-name] [startup-assembly]
```
startup-assembly: the file path to the entrypoint dotnet DLL that hosts AsyncAPI document(s).

## Tool options
--doc: The name of the AsyncAPI document as defined in the startup class by the ```.ConfigureNamedAsyncApi()```-method. If not specified, all documents will be exported.
--output: relative path where the AsyncAPI will be output [defaults to stdout]
--filename: the template for the outputted file names. Default: "{document}_asyncapi.{extension}"
--format: the output formats to generate, can be a combination of json, yml and/or yaml. File extension is appended to the output path.
--env: define environment variable(s) for the application
- _--doc_: The name of the AsyncAPI document as defined in the startup class by the ```.ConfigureNamedAsyncApi()```-method. If only ```.AddAsyncApiSchemaGeneration()``` is used, the document is unnamed and will always be exported. If not specified, all documents will be exported.
- _--output_: relative path where the AsyncAPI will be output [defaults to stdout]
- _--filename_: the template for the outputted file names. Default: "{document}_asyncapi.{extension}"
- _--format_: the output formats to generate, can be a combination of json, yml and/or yaml. File extension is appended to the output path.
- _--env_: define environment variable(s) for the application

## Install the Generator.Cli dotnet Tool
```
dotnet tool install --global AsyncAPI.Saunter.Generator.Cli
```
After installing the tool globally, it is available using commands: ```dotnet asyncapi``` or ```dotnet-asyncapi```

Want to learn more about .NET tools? Or want to install it local using a manifest?
(Check out this Microsoft page on how to manage .NET tools)[https://learn.microsoft.com/en-us/dotnet/core/tools/global-tools]
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,4 @@
<Using Include="Xunit" />
</ItemGroup>

<ItemGroup>
<None Update="asyncapi.cmd">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>

</Project>
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ public void DefaultCallPrintsCommandInfo()
var stdOut = RunTool("", 1);

stdOut.ShouldBe("""
Usage: dotnet asyncapi.net tofile [options] [startupassembly]
Usage: dotnet asyncapi tofile [options] [startupassembly]
startupassembly:
relative path to the application's startup assembly
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,19 +38,19 @@ public void Pack_Install_Run_Uninstall_Test()
stdOut.ShouldContain("Successfully created package");

stdOut = this.Run("dotnet", "tool install --global --add-source ./bin/Release AsyncAPI.Saunter.Generator.Cli", "../../../../../src/AsyncAPI.Saunter.Generator.Cli");
stdOut.ShouldBeOneOf("You can invoke the tool using the following command: AsyncAPI.NET\r\nTool 'asyncapi.saunter.generator.cli' (version '1.0.0') was successfully installed.",
"Tool 'asyncapi.saunter.generator.cli' was reinstalled with the stable version (version '1.0.0').");
stdOut.ShouldBeOneOf("You can invoke the tool using the following command: dotnet-asyncapi\r\nTool 'asyncapi.saunter.generator.cli' (version '1.0.1') was successfully installed.",
"Tool 'asyncapi.saunter.generator.cli' was reinstalled with the stable version (version '1.0.1').");

stdOut = this.Run("dotnet", "tool list -g asyncapi.saunter.generator.cli", "");
stdOut.ShouldContain("AsyncAPI.NET");
stdOut.ShouldContain("dotnet-asyncapi");

stdOut = this.Run("asyncapi.cmd", "", "", 1);
stdOut = this.Run("dotnet", "asyncapi", "", 1);
stdOut.ShouldContain("tofile: retrieves AsyncAPI from a startup assembly, and writes to file");

stdOut = this.Run("dotnet", "tool uninstall -g asyncapi.saunter.generator.cli", "");
stdOut.ShouldContain(" was successfully uninstalled.");

stdOut = this.Run("dotnet", "tool list -g asyncapi.saunter.generator.cli", "", 1);
stdOut.ShouldNotContain("AsyncAPI.NET");
stdOut.ShouldNotContain("dotnet-asyncapi");
}
}
2 changes: 0 additions & 2 deletions test/AsyncAPI.Saunter.Generator.Cli.Tests/asyncapi.cmd

This file was deleted.

0 comments on commit 1ebb77c

Please sign in to comment.