@@ -199,6 +199,255 @@ program
199199 process . exit ( 1 ) ;
200200 }
201201 } ) ;
202+
203+ // Plugin management commands
204+ const pluginCmd = program
205+ . command ( 'plugin' )
206+ . description ( 'Manage plugins' ) ;
207+
208+ pluginCmd
209+ . command ( 'list' )
210+ . description ( 'List all plugins in the current workspace' )
211+ . option ( '--json' , 'Output as JSON' )
212+ . option ( '--enabled-only' , 'Show only enabled plugins' )
213+ . action ( async ( opts ) => {
214+ try {
215+ const { pluginSystem } = await import ( './lib/plugin-system.js' ) ;
216+ const cwd = process . cwd ( ) ;
217+
218+ await pluginSystem . initialize ( cwd ) ;
219+ const plugins = pluginSystem . getAllPlugins ( ) ;
220+
221+ let filteredPlugins = plugins ;
222+ if ( opts . enabledOnly ) {
223+ filteredPlugins = plugins . filter ( p => p . enabled ) ;
224+ }
225+
226+ if ( opts . json ) {
227+ console . log ( JSON . stringify ( filteredPlugins , null , 2 ) ) ;
228+ } else {
229+ if ( filteredPlugins . length === 0 ) {
230+ console . log ( chalk . yellow ( 'No plugins found.' ) ) ;
231+ return ;
232+ }
233+
234+ console . log ( chalk . blue ( `\n📦 Found ${ filteredPlugins . length } plugin(s):\n` ) ) ;
235+ for ( const plugin of filteredPlugins ) {
236+ const status = plugin . enabled ? chalk . green ( 'enabled' ) : chalk . red ( 'disabled' ) ;
237+ const type = plugin . type === 'local' ? chalk . cyan ( 'local' ) : chalk . magenta ( 'external' ) ;
238+ console . log ( ` ${ chalk . bold ( plugin . name ) } [${ status } ] (${ type } )` ) ;
239+ if ( plugin . plugin ?. description ) {
240+ console . log ( ` ${ chalk . gray ( plugin . plugin . description ) } ` ) ;
241+ }
242+ if ( plugin . plugin ?. version ) {
243+ console . log ( ` ${ chalk . gray ( 'v' + plugin . plugin . version ) } ` ) ;
244+ }
245+ console . log ( ) ;
246+ }
247+ }
248+ } catch ( e ) {
249+ console . error ( chalk . red ( 'Failed to list plugins:' ) , e . message ) ;
250+ process . exit ( 1 ) ;
251+ }
252+ } ) ;
253+
254+ pluginCmd
255+ . command ( 'enable' )
256+ . description ( 'Enable a plugin' )
257+ . argument ( '<name>' , 'Plugin name' )
258+ . action ( async ( name ) => {
259+ try {
260+ const { pluginSystem } = await import ( './lib/plugin-system.js' ) ;
261+ const cwd = process . cwd ( ) ;
262+
263+ await pluginSystem . initialize ( cwd ) ;
264+ await pluginSystem . enablePlugin ( name ) ;
265+
266+ console . log ( chalk . green ( `✅ Plugin '${ name } ' enabled successfully` ) ) ;
267+ } catch ( e ) {
268+ console . error ( chalk . red ( 'Failed to enable plugin:' ) , e . message ) ;
269+ process . exit ( 1 ) ;
270+ }
271+ } ) ;
272+
273+ pluginCmd
274+ . command ( 'disable' )
275+ . description ( 'Disable a plugin' )
276+ . argument ( '<name>' , 'Plugin name' )
277+ . action ( async ( name ) => {
278+ try {
279+ const { pluginSystem } = await import ( './lib/plugin-system.js' ) ;
280+ const cwd = process . cwd ( ) ;
281+
282+ await pluginSystem . initialize ( cwd ) ;
283+ await pluginSystem . disablePlugin ( name ) ;
284+
285+ console . log ( chalk . green ( `✅ Plugin '${ name } ' disabled successfully` ) ) ;
286+ } catch ( e ) {
287+ console . error ( chalk . red ( 'Failed to disable plugin:' ) , e . message ) ;
288+ process . exit ( 1 ) ;
289+ }
290+ } ) ;
291+
292+ pluginCmd
293+ . command ( 'info' )
294+ . description ( 'Show detailed information about a plugin' )
295+ . argument ( '<name>' , 'Plugin name' )
296+ . option ( '--json' , 'Output as JSON' )
297+ . action ( async ( name , opts ) => {
298+ try {
299+ const { pluginSystem, HOOK_POINTS } = await import ( './lib/plugin-system.js' ) ;
300+ const cwd = process . cwd ( ) ;
301+
302+ await pluginSystem . initialize ( cwd ) ;
303+ const plugin = pluginSystem . getPlugin ( name ) ;
304+
305+ if ( ! plugin ) {
306+ console . log ( chalk . yellow ( `Plugin '${ name } ' not found.` ) ) ;
307+ process . exit ( 1 ) ;
308+ }
309+
310+ if ( opts . json ) {
311+ const info = {
312+ name : plugin . name ,
313+ type : plugin . type ,
314+ enabled : plugin . enabled ,
315+ loadedAt : plugin . loadedAt ,
316+ plugin : plugin . plugin ,
317+ config : plugin . config
318+ } ;
319+ console . log ( JSON . stringify ( info , null , 2 ) ) ;
320+ } else {
321+ console . log ( chalk . blue ( `\n📦 Plugin: ${ chalk . bold ( plugin . name ) } \n` ) ) ;
322+ console . log ( `Type: ${ plugin . type === 'local' ? chalk . cyan ( 'Local' ) : chalk . magenta ( 'External' ) } ` ) ;
323+ console . log ( `Status: ${ plugin . enabled ? chalk . green ( 'Enabled' ) : chalk . red ( 'Disabled' ) } ` ) ;
324+ console . log ( `Loaded: ${ plugin . loadedAt ? new Date ( plugin . loadedAt ) . toLocaleString ( ) : 'Not loaded' } ` ) ;
325+
326+ if ( plugin . plugin ) {
327+ if ( plugin . plugin . version ) {
328+ console . log ( `Version: ${ plugin . plugin . version } ` ) ;
329+ }
330+ if ( plugin . plugin . description ) {
331+ console . log ( `Description: ${ plugin . plugin . description } ` ) ;
332+ }
333+
334+ if ( plugin . plugin . hooks ) {
335+ console . log ( `\nHooks (${ Object . keys ( plugin . plugin . hooks ) . length } ):` ) ;
336+ for ( const [ hookName , handler ] of Object . entries ( plugin . plugin . hooks ) ) {
337+ const description = HOOK_POINTS [ hookName ] || 'Custom hook' ;
338+ console . log ( ` ${ chalk . cyan ( hookName ) } - ${ chalk . gray ( description ) } ` ) ;
339+ }
340+ }
341+
342+ if ( plugin . plugin . methods ) {
343+ console . log ( `\nMethods (${ Object . keys ( plugin . plugin . methods ) . length } ):` ) ;
344+ for ( const methodName of Object . keys ( plugin . plugin . methods ) ) {
345+ console . log ( ` ${ chalk . cyan ( methodName ) } ` ) ;
346+ }
347+ }
348+ }
349+
350+ if ( plugin . config ) {
351+ console . log ( `\nConfiguration:` ) ;
352+ console . log ( JSON . stringify ( plugin . config , null , 2 ) ) ;
353+ }
354+ console . log ( ) ;
355+ }
356+ } catch ( e ) {
357+ console . error ( chalk . red ( 'Failed to get plugin info:' ) , e . message ) ;
358+ process . exit ( 1 ) ;
359+ }
360+ } ) ;
361+
362+ pluginCmd
363+ . command ( 'configure' )
364+ . description ( 'Configure a plugin' )
365+ . argument ( '<name>' , 'Plugin name' )
366+ . option ( '--config <json>' , 'Configuration as JSON string' )
367+ . option ( '--priority <number>' , 'Plugin loading priority (higher = loads first)' )
368+ . option ( '--external <path>' , 'Set external plugin path or npm package' )
369+ . action ( async ( name , opts ) => {
370+ try {
371+ const { pluginSystem } = await import ( './lib/plugin-system.js' ) ;
372+ const cwd = process . cwd ( ) ;
373+
374+ await pluginSystem . initialize ( cwd ) ;
375+
376+ const config = { } ;
377+
378+ if ( opts . config ) {
379+ try {
380+ Object . assign ( config , JSON . parse ( opts . config ) ) ;
381+ } catch ( e ) {
382+ console . error ( chalk . red ( 'Invalid JSON in --config option' ) ) ;
383+ process . exit ( 1 ) ;
384+ }
385+ }
386+
387+ if ( opts . priority !== undefined ) {
388+ config . priority = parseInt ( opts . priority ) ;
389+ }
390+
391+ if ( opts . external ) {
392+ config . external = opts . external ;
393+ }
394+
395+ if ( Object . keys ( config ) . length === 0 ) {
396+ console . log ( chalk . yellow ( 'No configuration options provided. Use --config, --priority, or --external.' ) ) ;
397+ process . exit ( 1 ) ;
398+ }
399+
400+ await pluginSystem . configurePlugin ( name , config ) ;
401+
402+ console . log ( chalk . green ( `✅ Plugin '${ name } ' configured successfully` ) ) ;
403+ console . log ( 'New configuration:' , JSON . stringify ( config , null , 2 ) ) ;
404+ } catch ( e ) {
405+ console . error ( chalk . red ( 'Failed to configure plugin:' ) , e . message ) ;
406+ process . exit ( 1 ) ;
407+ }
408+ } ) ;
409+
410+ pluginCmd
411+ . command ( 'stats' )
412+ . description ( 'Show plugin system statistics' )
413+ . option ( '--json' , 'Output as JSON' )
414+ . action ( async ( opts ) => {
415+ try {
416+ const { pluginSystem } = await import ( './lib/plugin-system.js' ) ;
417+ const cwd = process . cwd ( ) ;
418+
419+ await pluginSystem . initialize ( cwd ) ;
420+ const stats = pluginSystem . getStats ( ) ;
421+
422+ if ( opts . json ) {
423+ console . log ( JSON . stringify ( stats , null , 2 ) ) ;
424+ } else {
425+ console . log ( chalk . blue ( '\n📊 Plugin System Statistics\n' ) ) ;
426+ console . log ( `Initialized: ${ stats . initialized ? chalk . green ( 'Yes' ) : chalk . red ( 'No' ) } ` ) ;
427+ console . log ( `Project Directory: ${ stats . projectDir || 'N/A' } ` ) ;
428+ console . log ( `Total Plugins: ${ stats . totalPlugins } ` ) ;
429+ console . log ( `Enabled Plugins: ${ stats . enabledPlugins } ` ) ;
430+ console . log ( `Available Hook Points: ${ stats . hookPoints } ` ) ;
431+
432+ console . log ( '\nRegistered Hooks:' ) ;
433+ for ( const [ hookName , count ] of Object . entries ( stats . registeredHooks ) ) {
434+ console . log ( ` ${ chalk . cyan ( hookName ) } : ${ count } handler(s)` ) ;
435+ }
436+
437+ if ( Object . keys ( stats . config ) . length > 0 ) {
438+ console . log ( '\nPlugin Configuration:' ) ;
439+ for ( const [ pluginName , config ] of Object . entries ( stats . config ) ) {
440+ console . log ( ` ${ chalk . bold ( pluginName ) } :` ) ;
441+ console . log ( ` ${ JSON . stringify ( config , null , 4 ) . replace ( / ^ / gm, ' ' ) } ` ) ;
442+ }
443+ }
444+ console . log ( ) ;
445+ }
446+ } catch ( e ) {
447+ console . error ( chalk . red ( 'Failed to get plugin stats:' ) , e . message ) ;
448+ process . exit ( 1 ) ;
449+ }
450+ } ) ;
202451
203452program . parse ( ) ;
204453
0 commit comments