@@ -54,18 +54,53 @@ static async Task<int> Main(string[] args)
5454 description : "Treat warnings as errors" ,
5555 getDefaultValue : ( ) => false ) ;
5656
57+ var exportsOption = new Option < bool > (
58+ aliases : new [ ] { "--exports" } ,
59+ description : "Use ES module exports for tree-shaking (requires --raw --single-file)" ,
60+ getDefaultValue : ( ) => false ) ;
61+
62+ var packageOption = new Option < bool > (
63+ aliases : new [ ] { "--package" } ,
64+ description : "Generate a complete npm package with esbuild plugin" ,
65+ getDefaultValue : ( ) => false ) ;
66+
67+ var packageNameOption = new Option < string ? > (
68+ aliases : new [ ] { "--package-name" } ,
69+ description : "npm package name (e.g., @nativewrappers/natives-rdr3)" ) ;
70+
71+ var packageVersionOption = new Option < string ? > (
72+ aliases : new [ ] { "--package-version" } ,
73+ description : "npm package version (e.g., 1.0.0)" ,
74+ getDefaultValue : ( ) => "0.0.1" ) ;
75+
5776 generateCommand . AddOption ( inputOption ) ;
5877 generateCommand . AddOption ( outputOption ) ;
5978 generateCommand . AddOption ( formatOption ) ;
6079 generateCommand . AddOption ( namespacesOption ) ;
6180 generateCommand . AddOption ( rawOption ) ;
6281 generateCommand . AddOption ( singleFileOption ) ;
6382 generateCommand . AddOption ( strictOption ) ;
83+ generateCommand . AddOption ( exportsOption ) ;
84+ generateCommand . AddOption ( packageOption ) ;
85+ generateCommand . AddOption ( packageNameOption ) ;
86+ generateCommand . AddOption ( packageVersionOption ) ;
6487
65- generateCommand . SetHandler ( async ( input , output , format , namespaces , raw , singleFile , strict ) =>
88+ generateCommand . SetHandler ( async ( context ) =>
6689 {
67- await Generate ( input , output , format , namespaces , raw , singleFile , strict ) ;
68- } , inputOption , outputOption , formatOption , namespacesOption , rawOption , singleFileOption , strictOption ) ;
90+ var input = context . ParseResult . GetValueForOption ( inputOption ) ! ;
91+ var output = context . ParseResult . GetValueForOption ( outputOption ) ! ;
92+ var format = context . ParseResult . GetValueForOption ( formatOption ) ! ;
93+ var namespaces = context . ParseResult . GetValueForOption ( namespacesOption ) ;
94+ var raw = context . ParseResult . GetValueForOption ( rawOption ) ;
95+ var singleFile = context . ParseResult . GetValueForOption ( singleFileOption ) ;
96+ var strict = context . ParseResult . GetValueForOption ( strictOption ) ;
97+ var exports = context . ParseResult . GetValueForOption ( exportsOption ) ;
98+ var package_ = context . ParseResult . GetValueForOption ( packageOption ) ;
99+ var packageName = context . ParseResult . GetValueForOption ( packageNameOption ) ;
100+ var packageVersion = context . ParseResult . GetValueForOption ( packageVersionOption ) ;
101+
102+ await Generate ( input , output , format , namespaces , raw , singleFile , strict , exports , package_ , packageName , packageVersion ) ;
103+ } ) ;
69104
70105 // Validate command
71106 var validateCommand = new Command ( "validate" , "Validate MDX files without generating output" ) ;
@@ -94,7 +129,7 @@ static async Task<int> Main(string[] args)
94129 return await rootCommand . InvokeAsync ( args ) ;
95130 }
96131
97- static async Task Generate ( string input , string output , string format , string [ ] ? namespaces , bool raw , bool singleFile , bool strict )
132+ static async Task Generate ( string input , string output , string format , string [ ] ? namespaces , bool raw , bool singleFile , bool strict , bool exports , bool package_ , string ? packageName , string ? packageVersion )
98133 {
99134 Console . WriteLine ( $ "Generating { format } output...") ;
100135 Console . WriteLine ( $ "Input: { input } ") ;
@@ -107,6 +142,30 @@ static async Task Generate(string input, string output, string format, string[]?
107142 return ;
108143 }
109144
145+ if ( exports && ( ! raw || ! singleFile ) )
146+ {
147+ Console . Error . WriteLine ( "Error: --exports requires --raw --single-file" ) ;
148+ Environment . ExitCode = 1 ;
149+ return ;
150+ }
151+
152+ if ( package_ )
153+ {
154+ if ( string . IsNullOrEmpty ( packageName ) )
155+ {
156+ Console . Error . WriteLine ( "Error: --package requires --package-name" ) ;
157+ Environment . ExitCode = 1 ;
158+ return ;
159+ }
160+
161+ // If raw mode is specified with package, also enable single-file and exports
162+ if ( raw )
163+ {
164+ singleFile = true ;
165+ exports = true ;
166+ }
167+ }
168+
110169 var ( db , errors , warnings ) = await ParseAllFiles ( input ) ;
111170
112171 // Report issues
@@ -142,6 +201,10 @@ static async Task Generate(string input, string output, string format, string[]?
142201 Raw = raw ,
143202 SingleFile = singleFile ,
144203 Strict = strict ,
204+ UseExports = exports ,
205+ Package = package_ ,
206+ PackageName = packageName ,
207+ PackageVersion = packageVersion ?? "0.0.1" ,
145208 Namespaces = namespaces ? . Length > 0
146209 ? new HashSet < string > ( namespaces . SelectMany ( n => n . Split ( ',' ) ) , StringComparer . OrdinalIgnoreCase )
147210 : null
@@ -320,23 +383,44 @@ static async Task Validate(string input, bool strict)
320383 . GroupBy ( n => n . Namespace , StringComparer . OrdinalIgnoreCase )
321384 . ToDictionary ( g => g . Key , g => g . ToList ( ) , StringComparer . OrdinalIgnoreCase ) ;
322385
323- // Track struct usage - check parameter types for struct references
386+ // Track struct and enum usage
324387 var structDict = structRegistry . GetAllStructs ( ) ;
388+ var enumDict = enumRegistry . GetAllEnums ( ) ;
389+
325390 foreach ( var native in allNatives )
326391 {
392+ // Check parameter types
327393 foreach ( var param in native . Parameters )
328394 {
329- // Check if parameter type matches a known struct
330395 var typeName = param . Type . Name ;
396+
397+ // Check struct usage
331398 if ( structDict . TryGetValue ( typeName , out var structDef ) )
332399 {
333- // Avoid duplicates
334- if ( ! structDef . UsedByNatives . Any ( u => u . Hash == native . Hash ) )
400+ if ( ! structDef . UsedByNatives . Contains ( native . Hash ) )
401+ {
402+ structDef . UsedByNatives . Add ( native . Hash ) ;
403+ }
404+ }
405+
406+ // Check enum usage (when Category is Enum, Name holds the enum name)
407+ if ( param . Type . Category == TypeCategory . Enum && enumDict . TryGetValue ( param . Type . Name , out var enumDef ) )
408+ {
409+ if ( ! enumDef . UsedByNatives . Contains ( native . Hash ) )
335410 {
336- structDef . UsedByNatives . Add ( ( native . Name , native . Hash ) ) ;
411+ enumDef . UsedByNatives . Add ( native . Hash ) ;
337412 }
338413 }
339414 }
415+
416+ // Check return type for enum usage
417+ if ( native . ReturnType . Category == TypeCategory . Enum && enumDict . TryGetValue ( native . ReturnType . Name , out var returnEnumDef ) )
418+ {
419+ if ( ! returnEnumDef . UsedByNatives . Contains ( native . Hash ) )
420+ {
421+ returnEnumDef . UsedByNatives . Add ( native . Hash ) ;
422+ }
423+ }
340424 }
341425
342426 // Convert to namespace list
0 commit comments