1
+ using Cmf . CLI . Core ;
2
+ using Cmf . CLI . Core . Attributes ;
3
+ using Cmf . CLI . Core . Commands ;
4
+ using Cmf . CLI . Core . Enums ;
5
+ using Cmf . CLI . Core . Objects ;
6
+ using Cmf . CLI . Utilities ;
7
+ using Microsoft . Extensions . DependencyInjection ;
8
+ using Newtonsoft . Json ;
9
+ using Spectre . Console ;
10
+ using System ;
11
+ using System . Collections . Generic ;
12
+ using System . CommandLine ;
13
+ using System . CommandLine . NamingConventionBinder ;
14
+ using System . IO . Abstractions ;
15
+
16
+ namespace Cmf . CLI . Commands . New . IoT
17
+ {
18
+ /// <summary>
19
+ /// Generates IoT Converter structure
20
+ /// </summary>
21
+ [ CmfCommand ( "converter" , ParentId = "new_iot" , Id = "iot_converter" ) ]
22
+ public class GenerateConverterCommand : TemplateCommand
23
+ {
24
+ /// <summary>
25
+ /// constructor
26
+ /// </summary>
27
+ public GenerateConverterCommand ( ) : base ( "converter" )
28
+ {
29
+ }
30
+
31
+ /// <summary>
32
+ /// constructor
33
+ /// </summary>
34
+ /// <param name="fileSystem">the filesystem implementation</param>
35
+ public GenerateConverterCommand ( IFileSystem fileSystem ) : base ( "converter" , fileSystem )
36
+ {
37
+ }
38
+
39
+ public override void Configure ( Command cmd )
40
+ {
41
+ var nearestIoTPackage = FileSystemUtilities . GetPackageRootByType (
42
+ this . fileSystem . Directory . GetCurrentDirectory ( ) ,
43
+ PackageType . IoT ,
44
+ this . fileSystem
45
+ ) ;
46
+
47
+ cmd . AddArgument ( new Argument < IDirectoryInfo > (
48
+ name : "workingDir" ,
49
+ parse : ( argResult ) => Parse < IDirectoryInfo > ( argResult , nearestIoTPackage ? . FullName ) ,
50
+ isDefault : true
51
+ )
52
+ {
53
+ Description = "Working Directory"
54
+ } ) ;
55
+
56
+ cmd . Handler = CommandHandler . Create < IDirectoryInfo > ( this . Execute ) ;
57
+ }
58
+
59
+ /// <summary>
60
+ /// Execute the command
61
+ /// </summary>
62
+ /// <param name="workingDir">nearest root package</param>
63
+ /// <param name="version">package version</param>
64
+ /// <param name="htmlPackageLocation">location of html package</param>
65
+ public void Execute ( IDirectoryInfo workingDir )
66
+ {
67
+ if ( workingDir == null )
68
+ {
69
+ throw new CliException ( "This command needs to run inside an iot project. Run `cmf new iot` to create a new project." ) ;
70
+ }
71
+
72
+ if ( ExecutionContext . Instance . ProjectConfig . MESVersion . Major < 11 )
73
+ {
74
+ throw new CliException ( "This command is only valid for versions above 11.0.0" ) ;
75
+ }
76
+
77
+ using var activity = ExecutionContext . ServiceProvider ? . GetService < ITelemetryService > ( ) ? . StartExtendedActivity ( this . GetType ( ) . Name ) ;
78
+
79
+ var converter = HandleConverter ( new ConverterValues ( ) ) ;
80
+
81
+ var args = this . GenerateArgs ( workingDir , this . fileSystem . Directory . GetCurrentDirectory ( ) , converter . Name , converter . ClassName , converter . Title , converter . InputAsJS , converter . OutputAsJS ) ;
82
+ this . CommandName = "iot-converter" ;
83
+ base . RunCommand ( args ) ;
84
+
85
+ var indexPath = this . fileSystem . Path . Join ( this . fileSystem . Directory . GetCurrentDirectory ( ) , "src/index.ts" ) ;
86
+ this . fileSystem . File . AppendAllLines ( indexPath , [ "export { " + converter . ClassName + "Converter } from \" ./converters/" + converter . Name + "/" + converter . Name + ".converter\" ;\r \n " ] ) ;
87
+
88
+ var template = new TemplateTaskLibrary ( )
89
+ {
90
+ Converters = [ converter ]
91
+ } ;
92
+ var templatePath = this . fileSystem . Path . Join ( this . fileSystem . Directory . GetCurrentDirectory ( ) , $ "templates/converter_{ converter . Name } .json") ;
93
+ this . fileSystem . File . WriteAllText ( templatePath ,
94
+ JsonConvert . SerializeObject ( template ,
95
+ new JsonSerializerSettings ( )
96
+ {
97
+ NullValueHandling = NullValueHandling . Ignore ,
98
+ Formatting = Formatting . Indented
99
+ } ) ) ;
100
+ }
101
+
102
+ private ConverterValues HandleConverter ( ConverterValues converter )
103
+ {
104
+ converter . Name = AnsiConsole . Ask ( "What is the converter name?" , converter . Name ) . ToCamelCase ( ) ;
105
+ converter . ClassName = converter . Name . ToPascalCase ( ) ;
106
+ converter . Title = AnsiConsole . Ask ( "What is the converter Title?" , converter . Title ) ;
107
+
108
+ converter . Input = AnsiConsole . Prompt (
109
+ new SelectionPrompt < string > ( )
110
+ . Title ( "What is the input type?" )
111
+ . AddChoices ( Enum . GetNames ( typeof ( DataTypeInputOutput ) ) ) ) ;
112
+ converter . Output = AnsiConsole . Prompt (
113
+ new SelectionPrompt < string > ( )
114
+ . Title ( "What is the output type?" )
115
+ . AddChoices ( Enum . GetNames ( typeof ( DataTypeInputOutput ) ) ) ) ;
116
+
117
+ converter . HasParameters = AnsiConsole . Prompt ( new ConfirmationPrompt ( "Do you require parameters?" ) { DefaultValue = converter . HasParameters } ) ;
118
+
119
+ if ( converter . HasParameters )
120
+ {
121
+ converter = this . HandleParameters ( converter ) ;
122
+ }
123
+
124
+ converter . InputAsJS = IoTStructures . ConvertIoTTypesToJSTypes ( converter . Input ) ;
125
+ converter . OutputAsJS = IoTStructures . ConvertIoTTypesToJSTypes ( converter . Output ) ;
126
+
127
+ return converter ;
128
+ }
129
+
130
+ private ConverterValues HandleParameters ( ConverterValues converter )
131
+ {
132
+ var addParameter = true ;
133
+
134
+ while ( addParameter )
135
+ {
136
+ var name = AnsiConsole . Ask ( "Parameter Name:" , "newParameter" ) ;
137
+ var type = AnsiConsole . Prompt (
138
+ new SelectionPrompt < string > ( )
139
+ . Title ( "Parameter Type:" )
140
+ . AddChoices ( Enum . GetNames ( typeof ( IoTValueType ) ) ) ) ;
141
+ var typeEnum = ( IoTValueType ) Enum . Parse ( typeof ( IoTValueType ) , type , true ) ;
142
+ var value = IoTStructures . ConvertIoTValueTypeToTaskValueType ( typeEnum ) ;
143
+
144
+ if ( typeEnum == IoTValueType . Any || typeEnum == IoTValueType . Enum )
145
+ {
146
+ value = """
147
+ [{
148
+ friendlyName: "First",
149
+ value: "1"
150
+ }, {
151
+ friendlyName: "Second",
152
+ value: "2"
153
+ }]
154
+ """ ;
155
+ converter . ParametersAsJS += $ "\t { name } :{ value } \r \n ";
156
+ }
157
+
158
+ if ( ! converter . Parameters . TryAdd ( name , typeEnum ) )
159
+ {
160
+ converter . Parameters [ name ] = typeEnum ;
161
+ }
162
+
163
+ converter . ParametersAsJS = converter . ParametersAsJS . TrimEnd ( ) ;
164
+
165
+ addParameter = AnsiConsole . Prompt ( new ConfirmationPrompt ( "Do you require more parameters?" ) { DefaultValue = false } ) ;
166
+ }
167
+
168
+ return converter ;
169
+ }
170
+
171
+ /// <inheritdoc />
172
+ private List < string > GenerateArgs (
173
+ IDirectoryInfo workingDir ,
174
+ string packageLocation ,
175
+ string converterName ,
176
+ string className ,
177
+ string title ,
178
+ string inputAsJS ,
179
+ string outputAsJS )
180
+ {
181
+ Log . Debug ( $ "Creating IoT Converter at { packageLocation } ") ;
182
+
183
+ var args = new List < string > ( ) ;
184
+ args . AddRange ( new [ ]
185
+ {
186
+ "--converterName" , converterName ,
187
+ "--className" , className ,
188
+ "--title" , title ,
189
+ "--inputAsJS" , inputAsJS ,
190
+ "--outputAsJS" , outputAsJS
191
+ } ) ;
192
+
193
+ return args ;
194
+ }
195
+ }
196
+ }
0 commit comments