|
1 | 1 | using DotNetConfig; |
2 | 2 | using System.CommandLine; |
3 | | -using System.CommandLine.Parsing; |
4 | 3 | using TypeContractor; |
5 | 4 | using TypeContractor.Logger; |
6 | 5 | using TypeContractor.Tool; |
7 | 6 |
|
8 | 7 | var config = Config.Build("typecontractor.config"); |
9 | 8 |
|
10 | 9 | var rootCommand = new RootCommand("Tool for generating TypeScript definitions from C# code"); |
11 | | -var assemblyOption = new Option<string>("--assembly", "Path to the assembly to start with. Will be relative to the current directory"); |
12 | | -var outputOption = new Option<string>("--output", "Output path to write to. Will be relative to the current directory"); |
13 | | -var relativeRootOption = new Option<string>("--root", "Relative root for generating cleaner imports. For example '~/api'"); |
14 | | -var cleanOption = new Option<CleanMethod>("--clean", () => CleanMethod.Smart, "Choose how to clean up no longer relevant type files in output directory. Danger!"); |
15 | | -var replaceOptions = new Option<string[]>("--replace", "Provide one replacement in the form '<search>:<replace>'. Can be repeated"); |
16 | | -var stripOptions = new Option<string[]>("--strip", "Provide a prefix to strip out of types. Can be repeated"); |
17 | | -var mapOptions = new Option<string[]>("--custom-map", "Provide a custom type map in the form '<from>:<to>'. Can be repeated"); |
18 | | -var packsOptions = new Option<string>("--packs-path", () => @"C:\Program Files\dotnet\packs\", "Path where dotnet is installed and reference assemblies can be found."); |
19 | | -var dotnetVersionOptions = new Option<int>("--dotnet-version", () => 8, "Major version of dotnet to look for"); |
20 | | -var logLevelOptions = new Option<LogLevel>("--log-level", () => LogLevel.Info); |
21 | | -var buildZodSchemasOptions = new Option<bool>("--build-zod-schemas", () => false, "Enable experimental support for Zod schemas alongside generated types."); |
22 | | -var generateApiClientsOptions = new Option<bool>("--generate-api-clients", () => false, "Enable experimental support for auto-generating API clients for each endpoint."); |
23 | | -var apiClientsTemplateOptions = new Option<string>("--api-client-template", () => "aurelia", "Template to use for API clients. Either 'aurelia', 'react-axios' (built-in) or a path to a Handlebars file, including extension"); |
24 | | -var casingOptions = new Option<Casing>("--casing", () => Casing.Pascal, "Casing to use for generated file names"); |
25 | | -assemblyOption.IsRequired = true; |
26 | | -outputOption.IsRequired = true; |
27 | | - |
28 | | -rootCommand.AddOption(assemblyOption); |
29 | | -rootCommand.AddOption(outputOption); |
30 | | -rootCommand.AddOption(relativeRootOption); |
31 | | -rootCommand.AddOption(cleanOption); |
32 | | -rootCommand.AddOption(replaceOptions); |
33 | | -rootCommand.AddOption(stripOptions); |
34 | | -rootCommand.AddOption(mapOptions); |
35 | | -rootCommand.AddOption(packsOptions); |
36 | | -rootCommand.AddOption(dotnetVersionOptions); |
37 | | -rootCommand.AddOption(logLevelOptions); |
38 | | -rootCommand.AddOption(buildZodSchemasOptions); |
39 | | -rootCommand.AddOption(generateApiClientsOptions); |
40 | | -rootCommand.AddOption(apiClientsTemplateOptions); |
41 | | -rootCommand.AddOption(casingOptions); |
42 | | - |
43 | | -apiClientsTemplateOptions.AddValidator(result => |
44 | | -{ |
45 | | - var value = result.GetValueForOption(apiClientsTemplateOptions)!; |
| 10 | + |
| 11 | +var assemblyOption = new Option<string>("--assembly") |
| 12 | +{ |
| 13 | + Description = "Path to the assembly to start with. Will be relative to the current directory", |
| 14 | + Required = true, |
| 15 | +}; |
| 16 | + |
| 17 | +var outputOption = new Option<string>("--output") |
| 18 | +{ |
| 19 | + Description = "Output path to write to. Will be relative to the current directory", |
| 20 | + Required = true, |
| 21 | +}; |
| 22 | + |
| 23 | +var relativeRootOption = new Option<string>("--root") |
| 24 | +{ |
| 25 | + Description = "Relative root for generating cleaner imports. For example '~/api'", |
| 26 | +}; |
| 27 | + |
| 28 | +var cleanOption = new Option<CleanMethod>("--clean") |
| 29 | +{ |
| 30 | + DefaultValueFactory = (arg) => CleanMethod.Smart, |
| 31 | + Description = "Choose how to clean up no longer relevant type files in output directory. Danger!", |
| 32 | +}; |
| 33 | + |
| 34 | +var replaceOptions = new Option<string[]>("--replace") |
| 35 | +{ |
| 36 | + Description = "Provide one replacement in the form '<search>:<replace>'. Can be repeated", |
| 37 | +}; |
| 38 | + |
| 39 | +var stripOptions = new Option<string[]>("--strip") |
| 40 | +{ |
| 41 | + Description = "Provide a prefix to strip out of types. Can be repeated", |
| 42 | +}; |
| 43 | + |
| 44 | +var mapOptions = new Option<string[]>("--custom-map") |
| 45 | +{ |
| 46 | + Description = "Provide a custom type map in the form '<from>:<to>'. Can be repeated", |
| 47 | +}; |
| 48 | + |
| 49 | +var packsOptions = new Option<string>("--packs-path") |
| 50 | +{ |
| 51 | + DefaultValueFactory = (arg) => @"C:\Program Files\dotnet\packs\", |
| 52 | + Description = "Path where dotnet is installed and reference assemblies can be found.", |
| 53 | +}; |
| 54 | + |
| 55 | +var dotnetVersionOptions = new Option<int>("--dotnet-version") |
| 56 | +{ |
| 57 | + DefaultValueFactory = (arg) => 8, |
| 58 | + Description = "Major version of dotnet to look for", |
| 59 | +}; |
| 60 | + |
| 61 | +var logLevelOptions = new Option<LogLevel>("--log-level") |
| 62 | +{ |
| 63 | + DefaultValueFactory = (arg) => LogLevel.Info, |
| 64 | +}; |
| 65 | + |
| 66 | +var buildZodSchemasOptions = new Option<bool>("--build-zod-schemas") |
| 67 | +{ |
| 68 | + DefaultValueFactory = (arg) => false, |
| 69 | + Description = "Enable experimental support for Zod schemas alongside generated types.", |
| 70 | +}; |
| 71 | + |
| 72 | +var generateApiClientsOptions = new Option<bool>("--generate-api-clients") |
| 73 | +{ |
| 74 | + DefaultValueFactory = (arg) => false, |
| 75 | + Description = "Enable experimental support for auto-generating API clients for each endpoint.", |
| 76 | +}; |
| 77 | + |
| 78 | +var apiClientsTemplateOptions = new Option<string>("--api-client-template") |
| 79 | +{ |
| 80 | + DefaultValueFactory = (arg) => "aurelia", |
| 81 | + Description = "Template to use for API clients. Either 'aurelia', 'react-axios' (built-in) or a path to a Handlebars file, including extension", |
| 82 | +}; |
| 83 | + |
| 84 | +var casingOptions = new Option<Casing>("--casing") |
| 85 | +{ |
| 86 | + DefaultValueFactory = (arg) => Casing.Pascal, |
| 87 | + Description = "Casing to use for generated file names", |
| 88 | +}; |
| 89 | + |
| 90 | +rootCommand.Options.Add(assemblyOption); |
| 91 | +rootCommand.Options.Add(outputOption); |
| 92 | +rootCommand.Options.Add(relativeRootOption); |
| 93 | +rootCommand.Options.Add(cleanOption); |
| 94 | +rootCommand.Options.Add(replaceOptions); |
| 95 | +rootCommand.Options.Add(stripOptions); |
| 96 | +rootCommand.Options.Add(mapOptions); |
| 97 | +rootCommand.Options.Add(packsOptions); |
| 98 | +rootCommand.Options.Add(dotnetVersionOptions); |
| 99 | +rootCommand.Options.Add(logLevelOptions); |
| 100 | +rootCommand.Options.Add(buildZodSchemasOptions); |
| 101 | +rootCommand.Options.Add(generateApiClientsOptions); |
| 102 | +rootCommand.Options.Add(apiClientsTemplateOptions); |
| 103 | +rootCommand.Options.Add(casingOptions); |
| 104 | + |
| 105 | +apiClientsTemplateOptions.Validators.Add(result => |
| 106 | +{ |
| 107 | + var value = result.GetValue(apiClientsTemplateOptions)!; |
46 | 108 | if (value.Equals("aurelia", StringComparison.CurrentCultureIgnoreCase) || value.Equals("react-axios", StringComparison.CurrentCultureIgnoreCase)) |
47 | 109 | return; |
48 | 110 |
|
49 | | - var generateClients = result.GetValueForOption(generateApiClientsOptions); |
| 111 | + var generateClients = result.GetValue(generateApiClientsOptions); |
50 | 112 | if (!generateClients) |
51 | 113 | { |
52 | | - result.ErrorMessage = $"Must generate API clients for --{apiClientsTemplateOptions.Name} to have any effect."; |
| 114 | + result.AddError($"Must generate API clients for --{apiClientsTemplateOptions.Name} to have any effect."); |
53 | 115 | return; |
54 | 116 | } |
55 | 117 |
|
56 | 118 | if (!File.Exists(value)) |
57 | 119 | { |
58 | | - result.ErrorMessage = $"The template specified does not exist or is not readable. Searched for {Path.GetFullPath(Path.Join(Directory.GetCurrentDirectory(), value))}."; |
| 120 | + result.AddError($"The template specified does not exist or is not readable. Searched for {Path.GetFullPath(Path.Join(Directory.GetCurrentDirectory(), value))}."); |
59 | 121 | return; |
60 | 122 | } |
61 | 123 | }); |
62 | 124 |
|
63 | 125 | // Apply configuration from file, if any |
64 | 126 | rootCommand = rootCommand.WithConfigurableDefaults("typecontractor", config); |
65 | 127 |
|
66 | | -rootCommand.SetHandler(async (context) => |
67 | | -{ |
68 | | - var assemblyOptionValue = context.ParseResult.GetValueForOption(assemblyOption)!; |
69 | | - var outputValue = context.ParseResult.GetValueForOption(outputOption)!; |
70 | | - var relativeRootValue = context.ParseResult.GetValueForOption(relativeRootOption); |
71 | | - var cleanValue = context.ParseResult.GetValueForOption(cleanOption); |
72 | | - var replacementsValue = context.ParseResult.GetValueForOption(replaceOptions) ?? []; |
73 | | - var stripValue = context.ParseResult.GetValueForOption(stripOptions) ?? []; |
74 | | - var customMapsValue = context.ParseResult.GetValueForOption(mapOptions) ?? []; |
75 | | - var packsPathValue = context.ParseResult.GetValueForOption(packsOptions)!; |
76 | | - var dotnetVersionValue = context.ParseResult.GetValueForOption(dotnetVersionOptions); |
77 | | - var logLevelValue = context.ParseResult.GetValueForOption(logLevelOptions); |
78 | | - var buildZodSchemasValue = context.ParseResult.GetValueForOption(buildZodSchemasOptions); |
79 | | - var generateApiClientsValue = context.ParseResult.GetValueForOption(generateApiClientsOptions); |
80 | | - var apiClientsTemplateValue = context.ParseResult.GetValueForOption(apiClientsTemplateOptions)!; |
81 | | - var casingValue = context.ParseResult.GetValueForOption(casingOptions); |
| 128 | +rootCommand.SetAction(async (parseResult, cancellationToken) => |
| 129 | +{ |
| 130 | + var assemblyOptionValue = parseResult.GetValue(assemblyOption)!; |
| 131 | + var outputValue = parseResult.GetValue(outputOption)!; |
| 132 | + var relativeRootValue = parseResult.GetValue(relativeRootOption); |
| 133 | + var cleanValue = parseResult.GetValue(cleanOption); |
| 134 | + var replacementsValue = parseResult.GetValue(replaceOptions) ?? []; |
| 135 | + var stripValue = parseResult.GetValue(stripOptions) ?? []; |
| 136 | + var customMapsValue = parseResult.GetValue(mapOptions) ?? []; |
| 137 | + var packsPathValue = parseResult.GetValue(packsOptions)!; |
| 138 | + var dotnetVersionValue = parseResult.GetValue(dotnetVersionOptions); |
| 139 | + var logLevelValue = parseResult.GetValue(logLevelOptions); |
| 140 | + var buildZodSchemasValue = parseResult.GetValue(buildZodSchemasOptions); |
| 141 | + var generateApiClientsValue = parseResult.GetValue(generateApiClientsOptions); |
| 142 | + var apiClientsTemplateValue = parseResult.GetValue(apiClientsTemplateOptions)!; |
| 143 | + var casingValue = parseResult.GetValue(casingOptions); |
82 | 144 |
|
83 | 145 | Log.Instance = new ConsoleLogger(logLevelValue); |
84 | 146 | var generator = new Generator(assemblyOptionValue, |
|
95 | 157 | apiClientsTemplateValue, |
96 | 158 | casingValue); |
97 | 159 |
|
98 | | - context.ExitCode = await generator.Execute(); |
| 160 | + return await generator.Execute(cancellationToken); |
99 | 161 | }); |
100 | 162 |
|
101 | | -return await rootCommand.InvokeAsync(args); |
| 163 | +var parsedResult = rootCommand.Parse(args); |
| 164 | +return await parsedResult.InvokeAsync(); |
0 commit comments