1+ // packages/cli/src/commands/config.ts
12import chalk from 'chalk' ;
23import Configstore from 'configstore' ;
34import inquirer from 'inquirer' ;
45import fs from 'fs/promises' ;
56import path from 'path' ;
67import { t } from '@stackcode/i18n' ;
8+ const globalConfig = new Configstore ( '@stackcode/cli' ) ;
9+ /**
10+ * Handles the non-interactive command logic based on provided arguments.
11+ * This function is easily testable in isolation.
12+ * @param argv - The arguments object from yargs.
13+ */
14+ export async function handleNonInteractiveMode ( argv ) {
15+ switch ( argv . action ) {
16+ case 'set' :
17+ if ( ! argv . key || ! argv . value ) {
18+ console . error ( chalk . red ( t ( 'config.error.missing_set_args' ) ) ) ;
19+ return ;
20+ }
21+ globalConfig . set ( argv . key , argv . value ) ;
22+ console . log ( chalk . green ( t ( 'config.success.set' , { key : argv . key , value : argv . value } ) ) ) ;
23+ break ;
24+ // Futuras implementações não-interativas (get, delete, etc.) podem ser adicionadas aqui.
25+ default :
26+ console . error ( chalk . yellow ( t ( 'config.error.invalid_action' , { action : argv . action || 'unknown' } ) ) ) ;
27+ break ;
28+ }
29+ }
30+ /**
31+ * Finds the project root by looking for a package.json file.
32+ */
733const findProjectRoot = async ( startPath ) => {
834 let currentPath = startPath ;
935 while ( currentPath !== path . parse ( currentPath ) . root ) {
@@ -16,57 +42,87 @@ const findProjectRoot = async (startPath) => {
1642 }
1743 return null ;
1844} ;
19- const globalConfig = new Configstore ( '@stackcode/cli' ) ;
20- export const getConfigCommand = ( ) => ( {
21- command : 'config' ,
22- describe : t ( 'config.command_description' ) ,
23- builder : { } ,
24- handler : async ( ) => {
25- const { choice } = await inquirer . prompt ( [
45+ /**
46+ * Runs the fully interactive configuration session using inquirer.
47+ */
48+ export async function runInteractiveMode ( ) {
49+ const { choice } = await inquirer . prompt ( [
50+ {
51+ type : 'list' , name : 'choice' , message : t ( 'config.prompt.main' ) ,
52+ choices : [
53+ { name : t ( 'config.prompt.select_lang' ) , value : 'lang' } ,
54+ { name : t ( 'config.prompt.toggle_validation' ) , value : 'commitValidation' } ,
55+ ] ,
56+ }
57+ ] ) ;
58+ if ( choice === 'lang' ) {
59+ const { lang } = await inquirer . prompt ( [
2660 {
27- type : 'list' , name : 'choice' , message : t ( 'config.prompt.main' ) ,
28- choices : [
29- { name : t ( 'config.prompt.select_lang' ) , value : 'lang' } ,
30- { name : t ( 'config.prompt.toggle_validation' ) , value : 'commitValidation' } ,
31- ] ,
61+ type : 'list' , name : 'lang' , message : t ( 'config.prompt.select_lang' ) ,
62+ choices : [ { name : 'English' , value : 'en' } , { name : 'Português' , value : 'pt' } ] ,
3263 }
3364 ] ) ;
34- if ( choice === 'lang' ) {
35- const { lang } = await inquirer . prompt ( [
36- {
37- type : 'list' , name : 'lang' , message : t ( 'config.prompt.select_lang' ) ,
38- choices : [ { name : 'English' , value : 'en' } , { name : 'Português' , value : 'pt' } ] ,
39- }
40- ] ) ;
41- globalConfig . set ( 'lang' , lang ) ;
42- console . log ( chalk . green ( t ( 'config.success.set' , { key : 'lang' , value : lang } ) ) ) ;
65+ globalConfig . set ( 'lang' , lang ) ;
66+ console . log ( chalk . green ( t ( 'config.success.set' , { key : 'lang' , value : lang } ) ) ) ;
67+ }
68+ else if ( choice === 'commitValidation' ) {
69+ const projectRoot = await findProjectRoot ( process . cwd ( ) ) ;
70+ if ( ! projectRoot ) {
71+ console . error ( chalk . red ( t ( 'config.error.not_in_project' ) ) ) ;
72+ return ;
4373 }
44- else if ( choice === 'commitValidation' ) {
45- const projectRoot = await findProjectRoot ( process . cwd ( ) ) ;
46- if ( ! projectRoot ) {
47- console . error ( chalk . red ( t ( 'config.error.not_in_project' ) ) ) ;
48- return ;
49- }
50- const localConfigPath = path . join ( projectRoot , '.stackcoderc.json' ) ;
51- try {
52- await fs . access ( localConfigPath ) ;
53- }
54- catch {
55- console . error ( chalk . red ( t ( 'config.error.not_in_project' ) ) ) ;
56- return ;
74+ const localConfigPath = path . join ( projectRoot , '.stackcoderc.json' ) ;
75+ try {
76+ await fs . access ( localConfigPath ) ;
77+ }
78+ catch {
79+ console . error ( chalk . red ( t ( 'config.error.no_stackcoderc' ) ) ) ;
80+ return ;
81+ }
82+ const { enable } = await inquirer . prompt ( [
83+ {
84+ type : 'confirm' , name : 'enable' , message : t ( 'config.prompt.toggle_validation' ) ,
85+ default : true ,
5786 }
58- const { enable } = await inquirer . prompt ( [
59- {
60- type : 'confirm' , name : 'enable' , message : t ( 'config.prompt.toggle_validation' ) ,
61- default : true ,
62- }
63- ] ) ;
64- const localConfigContent = await fs . readFile ( localConfigPath , 'utf-8' ) ;
65- const localConfig = JSON . parse ( localConfigContent ) ;
66- localConfig . features . commitValidation = enable ;
67- await fs . writeFile ( localConfigPath , JSON . stringify ( localConfig , null , 2 ) ) ;
68- const status = enable ? t ( 'config.status.enabled' ) : t ( 'config.status.disabled' ) ;
69- console . log ( chalk . green ( t ( 'config.success.set_validation' , { status } ) ) ) ;
87+ ] ) ;
88+ const localConfigContent = await fs . readFile ( localConfigPath , 'utf-8' ) ;
89+ const localConfig = JSON . parse ( localConfigContent ) ;
90+ localConfig . features . commitValidation = enable ;
91+ await fs . writeFile ( localConfigPath , JSON . stringify ( localConfig , null , 2 ) ) ;
92+ const status = enable ? t ( 'config.status.enabled' ) : t ( 'config.status.disabled' ) ;
93+ console . log ( chalk . green ( t ( 'config.success.set_validation' , { status } ) ) ) ;
94+ }
95+ }
96+ /**
97+ * Defines the 'config' command, its arguments, and the handler logic.
98+ */
99+ export const getConfigCommand = ( ) => ( {
100+ command : 'config [action] [key] [value]' ,
101+ describe : t ( 'config.command_description' ) ,
102+ builder : ( yargs ) => {
103+ return yargs
104+ . positional ( 'action' , {
105+ describe : t ( 'config.args.action_description' ) ,
106+ type : 'string' ,
107+ choices : [ 'set' ] , // Apenas 'set' está implementado no modo não-interativo por enquanto
108+ } )
109+ . positional ( 'key' , {
110+ describe : t ( 'config.args.key_description' ) ,
111+ type : 'string' ,
112+ } )
113+ . positional ( 'value' , {
114+ describe : t ( 'config.args.value_description' ) ,
115+ type : 'string' ,
116+ } ) ;
117+ } ,
118+ handler : async ( argv ) => {
119+ // The handler is now an orchestrator.
120+ const isInteractive = ! argv . action ;
121+ if ( isInteractive ) {
122+ await runInteractiveMode ( ) ;
123+ }
124+ else {
125+ await handleNonInteractiveMode ( argv ) ;
70126 }
71127 } ,
72128} ) ;
0 commit comments