66 * wheels plugins list --available
77 */
88component aliases = " wheels plugin list" extends = " ../base" {
9-
9+ property name = " forgebox " inject = " ForgeBox " ;
1010 property name = " pluginService" inject = " PluginService@wheels-cli" ;
1111 property name = " detailOutput" inject = " DetailOutputService@wheels-cli" ;
1212
@@ -30,8 +30,120 @@ component aliases="wheels plugin list" extends="../base" {
3030 if (arguments .available ) {
3131 // Show available plugins from ForgeBox
3232 detailOutput .header (" Available Wheels Plugins on ForgeBox" );
33+ detailOutput .output (" Searching, please wait..." );
3334 detailOutput .line ();
34- command (' forgebox show' ).params (type = " cfwheels-plugins" ).run ();
35+
36+ // Get list of all cfwheels plugins slugs
37+ var forgeboxResult = command (' forgebox show' )
38+ .params (type = ' cfwheels-plugins' )
39+ .run (returnOutput = true );
40+
41+ var results = [];
42+
43+ if (len (forgeboxResult )) {
44+ var lines = listToArray (forgeboxResult , chr (10 ) & chr (13 ));
45+
46+ for (var i = 1 ; i <= arrayLen (lines ); i ++ ) {
47+ var line = trim (lines [i ]);
48+
49+ // Check if this is a slug line: Slug: "slug-name"
50+ if (findNoCase (' Slug:' , line )) {
51+ // Extract slug from quotes
52+ var slugMatch = reFind (' Slug:\s*"([^"]+)"' , line , 1 , true );
53+ if (slugMatch .pos [1 ] > 0 ) {
54+ var slug = mid (line , slugMatch .pos [2 ], slugMatch .len [2 ]);
55+
56+ try {
57+ var pluginInfo = forgebox .getEntry (slug );
58+
59+ if (isStruct (pluginInfo ) && structKeyExists (pluginInfo , " slug" )) {
60+ // Extract version from latestVersion structure
61+ var version = " N/A" ;
62+ if (structKeyExists (pluginInfo , " latestVersion" ) &&
63+ isStruct (pluginInfo .latestVersion ) &&
64+ structKeyExists (pluginInfo .latestVersion , " version" )) {
65+ version = pluginInfo .latestVersion .version ;
66+ }
67+
68+ // Extract author from user structure
69+ var author = " Unknown" ;
70+ if (structKeyExists (pluginInfo , " user" ) &&
71+ isStruct (pluginInfo .user ) &&
72+ structKeyExists (pluginInfo .user , " username" )) {
73+ author = pluginInfo .user .username ;
74+ }
75+
76+ arrayAppend (results , {
77+ name : pluginInfo .title ?: slug ,
78+ slug : slug ,
79+ version : version ,
80+ description : pluginInfo .summary ?: pluginInfo .description ?: " " ,
81+ author : author ,
82+ downloads : pluginInfo .hits ?: 0 ,
83+ updateDate : pluginInfo .updatedDate ?: " "
84+ });
85+ }
86+ } catch (any e ) {
87+ // Skip plugins that can't be retrieved
88+ }
89+ }
90+ }
91+ }
92+ }
93+
94+ results .sort (function (a , b ) {
95+ return compareNoCase (a .name , b .name );
96+ });
97+
98+ if (arguments .format == " json" ) {
99+ var jsonOutput = {
100+ " plugins" : results ,
101+ " count" : arrayLen (results )
102+ };
103+ print .line (jsonOutput ).toConsole ();
104+ } else {
105+ detailOutput .subHeader (" Found #arrayLen (results ) # plugin(s)" );
106+ detailOutput .line ();
107+
108+ // Create table for results
109+ var rows = [];
110+
111+ for (var plugin in results ) {
112+ // use ordered struct so JSON keeps key order
113+ var row = structNew (" ordered" );
114+
115+ row [" Name" ] = plugin .name ;
116+ row [" Slug" ] = plugin .slug ;
117+ row [" Version" ] = plugin .version ;
118+ row [" Downloads" ] = numberFormat (plugin .downloads ?: 0 );
119+ row [" Description" ] = plugin .description ?: " No description" ;
120+
121+ // Truncate long descriptions
122+ if (len (row [" Description" ]) > 50 ) {
123+ row [" Description" ] = left (row [" Description" ], 47 ) & " ..." ;
124+ }
125+
126+ arrayAppend (rows , row );
127+ }
128+
129+ // Display the table
130+ detailOutput .getPrint ().table (rows ).toConsole ();
131+
132+ detailOutput .line ();
133+ detailOutput .divider ();
134+ detailOutput .line ();
135+
136+ // Show summary
137+ detailOutput .metric (" Total plugins found" , " #arrayLen (results ) #" );
138+ detailOutput .line ();
139+
140+ // Show commands
141+ detailOutput .subHeader (" Commands" );
142+ detailOutput .output (" - Install: wheels plugin install <name>" , true );
143+ detailOutput .output (" - Details: wheels plugin info <name>" , true );
144+ detailOutput .output (" - Add --format=json for JSON output" , true );
145+ detailOutput .line ();
146+ }
35147 return ;
36148 }
37149
@@ -58,17 +170,17 @@ component aliases="wheels plugin list" extends="../base" {
58170 " plugins" : plugins ,
59171 " count" : arrayLen (plugins )
60172 };
61- print .line (serializeJSON ( jsonOutput , true ) );
173+ print .line (jsonOutput ). toConsole ( );
62174 } else {
63175 // Table format output
64176 detailOutput .header (" Installed Wheels Plugins (#arrayLen (plugins ) #)" );
65- detailOutput .line ();
66177
67178 // Create table rows
68179 var rows = [];
69180 for (var plugin in plugins ) {
70181 var row = {
71182 " Plugin Name" : plugin .name ,
183+ " Slug" : plugin .slug ,
72184 " Version" : plugin .version
73185 };
74186
@@ -87,7 +199,7 @@ component aliases="wheels plugin list" extends="../base" {
87199 }
88200
89201 // Display the table
90- detailOutput .getPrint ().table (rows ). toConsole () ;
202+ detailOutput .getPrint ().table (rows );
91203
92204 detailOutput .line ();
93205 detailOutput .divider (" -" , 60 );
0 commit comments