trello-cli-unofficial 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.eslintignore +26 -0
- package/CHANGELOG.md +48 -0
- package/LICENSE +21 -0
- package/README.md +261 -0
- package/bun.lock +788 -0
- package/dist/main.js +27751 -0
- package/install.sh +45 -0
- package/main.ts +19 -0
- package/package.json +75 -0
- package/src/application/index.ts +1 -0
- package/src/application/use-cases/AuthenticateUserUseCase.ts +47 -0
- package/src/application/use-cases/CreateCardUseCase.ts +14 -0
- package/src/application/use-cases/DeleteCardUseCase.ts +9 -0
- package/src/application/use-cases/GetBoardsUseCase.ts +10 -0
- package/src/application/use-cases/GetCardsUseCase.ts +10 -0
- package/src/application/use-cases/GetListsUseCase.ts +10 -0
- package/src/application/use-cases/MoveCardUseCase.ts +10 -0
- package/src/application/use-cases/UpdateCardUseCase.ts +17 -0
- package/src/application/use-cases/index.ts +8 -0
- package/src/domain/entities/Board.ts +17 -0
- package/src/domain/entities/Card.ts +53 -0
- package/src/domain/entities/Config.ts +20 -0
- package/src/domain/entities/List.ts +12 -0
- package/src/domain/entities/index.ts +4 -0
- package/src/domain/index.ts +3 -0
- package/src/domain/repositories/ConfigRepository.ts +6 -0
- package/src/domain/repositories/TrelloRepository.ts +11 -0
- package/src/domain/repositories/index.ts +2 -0
- package/src/domain/services/AuthenticationService.ts +26 -0
- package/src/domain/services/index.ts +1 -0
- package/src/index.ts +5 -0
- package/src/infrastructure/index.ts +1 -0
- package/src/infrastructure/repositories/FileConfigRepository.ts +51 -0
- package/src/infrastructure/repositories/TrelloApiRepository.ts +93 -0
- package/src/infrastructure/repositories/index.ts +2 -0
- package/src/presentation/cli/CommandController.ts +59 -0
- package/src/presentation/cli/TrelloCliController.ts +408 -0
- package/src/presentation/cli/index.ts +2 -0
- package/src/presentation/index.ts +1 -0
- package/src/shared/index.ts +1 -0
- package/src/shared/types.ts +31 -0
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { Command } from 'commander';
|
|
2
|
+
import { FileConfigRepository } from '../../infrastructure/repositories';
|
|
3
|
+
import { TrelloCliController } from './TrelloCliController';
|
|
4
|
+
|
|
5
|
+
export class CommandController {
|
|
6
|
+
private cli: TrelloCliController;
|
|
7
|
+
private program: Command;
|
|
8
|
+
|
|
9
|
+
constructor() {
|
|
10
|
+
const configRepository = new FileConfigRepository();
|
|
11
|
+
this.cli = new TrelloCliController(configRepository);
|
|
12
|
+
this.program = new Command();
|
|
13
|
+
this.setupCommands();
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
private setupCommands(): void {
|
|
17
|
+
this.program
|
|
18
|
+
.name('trello-cli-unofficial')
|
|
19
|
+
.description('Unofficial Trello CLI using Power-Up authentication')
|
|
20
|
+
.version('1.0.0');
|
|
21
|
+
|
|
22
|
+
this.program
|
|
23
|
+
.command('interactive')
|
|
24
|
+
.alias('i')
|
|
25
|
+
.description('Start interactive mode')
|
|
26
|
+
.action(async () => {
|
|
27
|
+
await this.cli.showMenu();
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
this.program
|
|
31
|
+
.command('boards')
|
|
32
|
+
.description('List all your Trello boards')
|
|
33
|
+
.action(async () => {
|
|
34
|
+
try {
|
|
35
|
+
await this.cli.ensureAuthenticated();
|
|
36
|
+
await this.cli.initializeTrelloUseCases();
|
|
37
|
+
await this.cli.showBoards();
|
|
38
|
+
} catch (error) {
|
|
39
|
+
console.error('❌ Erro:', (error as Error).message);
|
|
40
|
+
}
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
this.program
|
|
44
|
+
.command('setup')
|
|
45
|
+
.description('Setup your Trello token')
|
|
46
|
+
.action(async () => {
|
|
47
|
+
await this.cli.setupToken();
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
async run(): Promise<void> {
|
|
52
|
+
// Fallback to interactive mode if no command specified
|
|
53
|
+
if (process.argv.length === 2) {
|
|
54
|
+
await this.cli.showMenu();
|
|
55
|
+
} else {
|
|
56
|
+
this.program.parse();
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
@@ -0,0 +1,408 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
ConfigRepository,
|
|
3
|
+
TrelloRepository,
|
|
4
|
+
} from '../../domain/repositories';
|
|
5
|
+
import inquirer from 'inquirer';
|
|
6
|
+
import {
|
|
7
|
+
AuthenticateUserUseCase,
|
|
8
|
+
CreateCardUseCase,
|
|
9
|
+
DeleteCardUseCase,
|
|
10
|
+
GetBoardsUseCase,
|
|
11
|
+
GetCardsUseCase,
|
|
12
|
+
GetListsUseCase,
|
|
13
|
+
MoveCardUseCase,
|
|
14
|
+
UpdateCardUseCase,
|
|
15
|
+
} from '../../application';
|
|
16
|
+
import { TrelloApiRepository } from '../../infrastructure/repositories';
|
|
17
|
+
import { CARD_ACTIONS, CONFIG_ACTIONS, MENU_ACTIONS } from '../../shared';
|
|
18
|
+
|
|
19
|
+
export class TrelloCliController {
|
|
20
|
+
private authenticateUseCase: AuthenticateUserUseCase;
|
|
21
|
+
private getBoardsUseCase?: GetBoardsUseCase;
|
|
22
|
+
private getListsUseCase?: GetListsUseCase;
|
|
23
|
+
private getCardsUseCase?: GetCardsUseCase;
|
|
24
|
+
private createCardUseCase?: CreateCardUseCase;
|
|
25
|
+
private updateCardUseCase?: UpdateCardUseCase;
|
|
26
|
+
private deleteCardUseCase?: DeleteCardUseCase;
|
|
27
|
+
private moveCardUseCase?: MoveCardUseCase;
|
|
28
|
+
|
|
29
|
+
constructor(private configRepository: ConfigRepository) {
|
|
30
|
+
this.authenticateUseCase = new AuthenticateUserUseCase(configRepository);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
async initializeTrelloUseCases(): Promise<void> {
|
|
34
|
+
const config = await this.authenticateUseCase.getConfig();
|
|
35
|
+
|
|
36
|
+
if (!config.hasValidToken()) {
|
|
37
|
+
throw new Error('Token não configurado');
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
const trelloRepository: TrelloRepository = new TrelloApiRepository(
|
|
41
|
+
config.apiKey,
|
|
42
|
+
config.token!,
|
|
43
|
+
);
|
|
44
|
+
|
|
45
|
+
this.getBoardsUseCase = new GetBoardsUseCase(trelloRepository);
|
|
46
|
+
this.getListsUseCase = new GetListsUseCase(trelloRepository);
|
|
47
|
+
this.getCardsUseCase = new GetCardsUseCase(trelloRepository);
|
|
48
|
+
this.createCardUseCase = new CreateCardUseCase(trelloRepository);
|
|
49
|
+
this.updateCardUseCase = new UpdateCardUseCase(trelloRepository);
|
|
50
|
+
this.deleteCardUseCase = new DeleteCardUseCase(trelloRepository);
|
|
51
|
+
this.moveCardUseCase = new MoveCardUseCase(trelloRepository);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
async ensureAuthenticated(): Promise<void> {
|
|
55
|
+
const result = await this.authenticateUseCase.execute();
|
|
56
|
+
if (!result.success) {
|
|
57
|
+
console.log(result.message);
|
|
58
|
+
await this.setupToken();
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
async setupToken(): Promise<void> {
|
|
63
|
+
const { token } = await inquirer.prompt([
|
|
64
|
+
{
|
|
65
|
+
type: 'input',
|
|
66
|
+
name: 'token',
|
|
67
|
+
message: 'Digite seu token do Trello (ATTA...):',
|
|
68
|
+
validate: input =>
|
|
69
|
+
input.startsWith('ATTA') || 'Token deve começar com ATTA',
|
|
70
|
+
},
|
|
71
|
+
]);
|
|
72
|
+
|
|
73
|
+
const result = await this.authenticateUseCase.execute(token);
|
|
74
|
+
console.log(result.message);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
async showMenu(): Promise<void> {
|
|
78
|
+
await this.ensureAuthenticated();
|
|
79
|
+
await this.initializeTrelloUseCases();
|
|
80
|
+
|
|
81
|
+
while (true) {
|
|
82
|
+
const { action } = await inquirer.prompt([
|
|
83
|
+
{
|
|
84
|
+
type: 'list',
|
|
85
|
+
name: 'action',
|
|
86
|
+
message: '🏠 Menu Principal - Trello CLI Unofficial',
|
|
87
|
+
choices: [
|
|
88
|
+
{ name: '📋 Ver meus quadros', value: MENU_ACTIONS.BOARDS },
|
|
89
|
+
{ name: '📝 Explorar quadro', value: MENU_ACTIONS.EXPLORE },
|
|
90
|
+
{ name: '➕ Criar cartão', value: MENU_ACTIONS.CREATE },
|
|
91
|
+
{ name: '⚙️ Configurações', value: MENU_ACTIONS.CONFIG },
|
|
92
|
+
{ name: '🚪 Sair', value: MENU_ACTIONS.EXIT },
|
|
93
|
+
],
|
|
94
|
+
},
|
|
95
|
+
]);
|
|
96
|
+
|
|
97
|
+
try {
|
|
98
|
+
switch (action) {
|
|
99
|
+
case MENU_ACTIONS.BOARDS:
|
|
100
|
+
await this.showBoards();
|
|
101
|
+
break;
|
|
102
|
+
case MENU_ACTIONS.EXPLORE:
|
|
103
|
+
await this.exploreBoard();
|
|
104
|
+
break;
|
|
105
|
+
case MENU_ACTIONS.CREATE:
|
|
106
|
+
await this.createCardInteractive();
|
|
107
|
+
break;
|
|
108
|
+
case MENU_ACTIONS.CONFIG:
|
|
109
|
+
await this.showConfigMenu();
|
|
110
|
+
break;
|
|
111
|
+
case MENU_ACTIONS.EXIT:
|
|
112
|
+
console.log('👋 Até logo!');
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
115
|
+
} catch (error) {
|
|
116
|
+
console.error('❌ Erro:', (error as Error).message);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
console.log(`\n${'='.repeat(50)}\n`);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
async showBoards(): Promise<void> {
|
|
124
|
+
if (!this.getBoardsUseCase) {
|
|
125
|
+
throw new Error('Use cases não inicializados');
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
const boards = await this.getBoardsUseCase.execute();
|
|
129
|
+
|
|
130
|
+
console.log('📋 Seus Quadros do Trello:');
|
|
131
|
+
boards.forEach((board, index) => {
|
|
132
|
+
console.log(`${index + 1}. ${board.name}`);
|
|
133
|
+
console.log(` 🔗 ${board.url}`);
|
|
134
|
+
console.log(` 🆔 ${board.id}\n`);
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
private async exploreBoard(): Promise<void> {
|
|
139
|
+
if (
|
|
140
|
+
!this.getBoardsUseCase
|
|
141
|
+
|| !this.getListsUseCase
|
|
142
|
+
|| !this.getCardsUseCase
|
|
143
|
+
) {
|
|
144
|
+
throw new Error('Use cases não inicializados');
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
const boards = await this.getBoardsUseCase.execute();
|
|
148
|
+
|
|
149
|
+
const { selectedBoard } = await inquirer.prompt([
|
|
150
|
+
{
|
|
151
|
+
type: 'list',
|
|
152
|
+
name: 'selectedBoard',
|
|
153
|
+
message: 'Selecione um quadro:',
|
|
154
|
+
choices: boards.map(board => ({ name: board.name, value: board.id })),
|
|
155
|
+
},
|
|
156
|
+
]);
|
|
157
|
+
|
|
158
|
+
const lists = await this.getListsUseCase.execute(selectedBoard);
|
|
159
|
+
|
|
160
|
+
const { selectedList } = await inquirer.prompt([
|
|
161
|
+
{
|
|
162
|
+
type: 'list',
|
|
163
|
+
name: 'selectedList',
|
|
164
|
+
message: 'Selecione uma lista:',
|
|
165
|
+
choices: lists.map(list => ({ name: list.name, value: list.id })),
|
|
166
|
+
},
|
|
167
|
+
]);
|
|
168
|
+
|
|
169
|
+
const cards = await this.getCardsUseCase.execute(selectedList);
|
|
170
|
+
|
|
171
|
+
if (cards.length === 0) {
|
|
172
|
+
console.log('📭 Esta lista está vazia.');
|
|
173
|
+
return;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
console.log(
|
|
177
|
+
`🃏 Cartões em "${lists.find(l => l.id === selectedList)?.name}":`,
|
|
178
|
+
);
|
|
179
|
+
cards.forEach((card, index) => {
|
|
180
|
+
console.log(`${index + 1}. ${card.name}`);
|
|
181
|
+
if (card.desc) {
|
|
182
|
+
const desc
|
|
183
|
+
= card.desc.length > 100
|
|
184
|
+
? `${card.desc.substring(0, 100)}...`
|
|
185
|
+
: card.desc;
|
|
186
|
+
console.log(` 📝 ${desc}`);
|
|
187
|
+
}
|
|
188
|
+
console.log(` 🔗 ${card.url}\n`);
|
|
189
|
+
});
|
|
190
|
+
|
|
191
|
+
// Opções adicionais
|
|
192
|
+
const { nextAction } = await inquirer.prompt([
|
|
193
|
+
{
|
|
194
|
+
type: 'list',
|
|
195
|
+
name: 'nextAction',
|
|
196
|
+
message: 'O que deseja fazer?',
|
|
197
|
+
choices: [
|
|
198
|
+
{ name: '⬅️ Voltar ao menu', value: CARD_ACTIONS.BACK },
|
|
199
|
+
{ name: '📝 Editar cartão', value: CARD_ACTIONS.EDIT },
|
|
200
|
+
{ name: '🗑️ Deletar cartão', value: CARD_ACTIONS.DELETE },
|
|
201
|
+
{ name: '📦 Mover cartão', value: CARD_ACTIONS.MOVE },
|
|
202
|
+
],
|
|
203
|
+
},
|
|
204
|
+
]);
|
|
205
|
+
|
|
206
|
+
if (nextAction !== CARD_ACTIONS.BACK) {
|
|
207
|
+
const { selectedCard } = await inquirer.prompt([
|
|
208
|
+
{
|
|
209
|
+
type: 'list',
|
|
210
|
+
name: 'selectedCard',
|
|
211
|
+
message: 'Selecione um cartão:',
|
|
212
|
+
choices: cards.map(card => ({ name: card.name, value: card.id })),
|
|
213
|
+
},
|
|
214
|
+
]);
|
|
215
|
+
|
|
216
|
+
const selectedCardEntity = cards.find(c => c.id === selectedCard)!;
|
|
217
|
+
|
|
218
|
+
switch (nextAction) {
|
|
219
|
+
case CARD_ACTIONS.EDIT:
|
|
220
|
+
await this.editCard(selectedCard, selectedCardEntity);
|
|
221
|
+
break;
|
|
222
|
+
case CARD_ACTIONS.DELETE:
|
|
223
|
+
await this.deleteCard(selectedCard, selectedCardEntity);
|
|
224
|
+
break;
|
|
225
|
+
case CARD_ACTIONS.MOVE:
|
|
226
|
+
await this.moveCard(selectedCard, selectedBoard, lists);
|
|
227
|
+
break;
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
private async createCardInteractive(): Promise<void> {
|
|
233
|
+
if (
|
|
234
|
+
!this.getBoardsUseCase
|
|
235
|
+
|| !this.getListsUseCase
|
|
236
|
+
|| !this.createCardUseCase
|
|
237
|
+
) {
|
|
238
|
+
throw new Error('Use cases não inicializados');
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
const boards = await this.getBoardsUseCase.execute();
|
|
242
|
+
|
|
243
|
+
const { selectedBoard } = await inquirer.prompt([
|
|
244
|
+
{
|
|
245
|
+
type: 'list',
|
|
246
|
+
name: 'selectedBoard',
|
|
247
|
+
message: 'Selecione o quadro:',
|
|
248
|
+
choices: boards.map(board => ({ name: board.name, value: board.id })),
|
|
249
|
+
},
|
|
250
|
+
]);
|
|
251
|
+
|
|
252
|
+
const lists = await this.getListsUseCase.execute(selectedBoard);
|
|
253
|
+
|
|
254
|
+
const { selectedList } = await inquirer.prompt([
|
|
255
|
+
{
|
|
256
|
+
type: 'list',
|
|
257
|
+
name: 'selectedList',
|
|
258
|
+
message: 'Selecione a lista:',
|
|
259
|
+
choices: lists.map(list => ({ name: list.name, value: list.id })),
|
|
260
|
+
},
|
|
261
|
+
]);
|
|
262
|
+
|
|
263
|
+
const { cardName, cardDesc } = await inquirer.prompt([
|
|
264
|
+
{
|
|
265
|
+
type: 'input',
|
|
266
|
+
name: 'cardName',
|
|
267
|
+
message: 'Nome do cartão:',
|
|
268
|
+
validate: input => input.length > 0 || 'Nome é obrigatório',
|
|
269
|
+
},
|
|
270
|
+
{
|
|
271
|
+
type: 'input',
|
|
272
|
+
name: 'cardDesc',
|
|
273
|
+
message: 'Descrição (opcional):',
|
|
274
|
+
},
|
|
275
|
+
]);
|
|
276
|
+
|
|
277
|
+
const newCard = await this.createCardUseCase.execute({
|
|
278
|
+
name: cardName,
|
|
279
|
+
desc: cardDesc,
|
|
280
|
+
listId: selectedList,
|
|
281
|
+
});
|
|
282
|
+
|
|
283
|
+
console.log('✅ Cartão criado com sucesso!');
|
|
284
|
+
console.log(`📝 Nome: ${newCard.name}`);
|
|
285
|
+
console.log(`🔗 URL: ${newCard.url}`);
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
private async editCard(cardId: string, card: any): Promise<void> {
|
|
289
|
+
if (!this.updateCardUseCase) {
|
|
290
|
+
throw new Error('Use cases não inicializados');
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
const { newName, newDesc } = await inquirer.prompt([
|
|
294
|
+
{
|
|
295
|
+
type: 'input',
|
|
296
|
+
name: 'newName',
|
|
297
|
+
message: 'Novo nome:',
|
|
298
|
+
default: card.name,
|
|
299
|
+
},
|
|
300
|
+
{
|
|
301
|
+
type: 'input',
|
|
302
|
+
name: 'newDesc',
|
|
303
|
+
message: 'Nova descrição:',
|
|
304
|
+
default: card.desc || '',
|
|
305
|
+
},
|
|
306
|
+
]);
|
|
307
|
+
|
|
308
|
+
await this.updateCardUseCase.execute(cardId, {
|
|
309
|
+
name: newName,
|
|
310
|
+
desc: newDesc,
|
|
311
|
+
});
|
|
312
|
+
console.log('✅ Cartão atualizado com sucesso!');
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
private async deleteCard(cardId: string, card: any): Promise<void> {
|
|
316
|
+
if (!this.deleteCardUseCase) {
|
|
317
|
+
throw new Error('Use cases não inicializados');
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
const { confirm } = await inquirer.prompt([
|
|
321
|
+
{
|
|
322
|
+
type: 'confirm',
|
|
323
|
+
name: 'confirm',
|
|
324
|
+
message: `Tem certeza que deseja deletar "${card.name}"?`,
|
|
325
|
+
default: false,
|
|
326
|
+
},
|
|
327
|
+
]);
|
|
328
|
+
|
|
329
|
+
if (confirm) {
|
|
330
|
+
await this.deleteCardUseCase.execute(cardId);
|
|
331
|
+
console.log('✅ Cartão deletado com sucesso!');
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
private async moveCard(
|
|
336
|
+
cardId: string,
|
|
337
|
+
currentBoardId: string,
|
|
338
|
+
lists: any[],
|
|
339
|
+
): Promise<void> {
|
|
340
|
+
if (!this.moveCardUseCase) {
|
|
341
|
+
throw new Error('Use cases não inicializados');
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
const { targetList } = await inquirer.prompt([
|
|
345
|
+
{
|
|
346
|
+
type: 'list',
|
|
347
|
+
name: 'targetList',
|
|
348
|
+
message: 'Mover para qual lista?',
|
|
349
|
+
choices: lists.map(list => ({ name: list.name, value: list.id })),
|
|
350
|
+
},
|
|
351
|
+
]);
|
|
352
|
+
|
|
353
|
+
await this.moveCardUseCase.execute(cardId, targetList);
|
|
354
|
+
console.log('✅ Cartão movido com sucesso!');
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
private async showConfigMenu(): Promise<void> {
|
|
358
|
+
while (true) {
|
|
359
|
+
const { configAction } = await inquirer.prompt([
|
|
360
|
+
{
|
|
361
|
+
type: 'list',
|
|
362
|
+
name: 'configAction',
|
|
363
|
+
message: '⚙️ Configurações',
|
|
364
|
+
choices: [
|
|
365
|
+
{ name: '🔑 Configurar token', value: CONFIG_ACTIONS.TOKEN },
|
|
366
|
+
{ name: '👀 Ver configuração atual', value: CONFIG_ACTIONS.VIEW },
|
|
367
|
+
{ name: '🔄 Resetar configuração', value: CONFIG_ACTIONS.RESET },
|
|
368
|
+
{ name: '⬅️ Voltar', value: CONFIG_ACTIONS.BACK },
|
|
369
|
+
],
|
|
370
|
+
},
|
|
371
|
+
]);
|
|
372
|
+
|
|
373
|
+
switch (configAction) {
|
|
374
|
+
case CONFIG_ACTIONS.TOKEN:
|
|
375
|
+
await this.setupToken();
|
|
376
|
+
await this.initializeTrelloUseCases(); // Re-initialize with new token
|
|
377
|
+
break;
|
|
378
|
+
case CONFIG_ACTIONS.VIEW:
|
|
379
|
+
const config = await this.authenticateUseCase.getConfig();
|
|
380
|
+
console.log('📋 Configuração atual:');
|
|
381
|
+
console.log(`API Key: ${config.apiKey}`);
|
|
382
|
+
console.log(
|
|
383
|
+
`Token configurado: ${config.hasValidToken() ? '✅ Sim' : '❌ Não'}`,
|
|
384
|
+
);
|
|
385
|
+
console.log(
|
|
386
|
+
`Arquivo de config: ~/.trello-cli-unofficial/config.json`,
|
|
387
|
+
);
|
|
388
|
+
break;
|
|
389
|
+
case CONFIG_ACTIONS.RESET:
|
|
390
|
+
const { confirm } = await inquirer.prompt([
|
|
391
|
+
{
|
|
392
|
+
type: 'confirm',
|
|
393
|
+
name: 'confirm',
|
|
394
|
+
message: 'Tem certeza que deseja resetar toda a configuração?',
|
|
395
|
+
default: false,
|
|
396
|
+
},
|
|
397
|
+
]);
|
|
398
|
+
if (confirm) {
|
|
399
|
+
// Reset logic would need to be implemented in the use case
|
|
400
|
+
console.log('✅ Configuração resetada!');
|
|
401
|
+
}
|
|
402
|
+
break;
|
|
403
|
+
case CONFIG_ACTIONS.BACK:
|
|
404
|
+
return;
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './cli';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './types';
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
export interface CliChoice<T = string> {
|
|
2
|
+
name: string;
|
|
3
|
+
value: T;
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
export interface MenuAction {
|
|
7
|
+
name: string;
|
|
8
|
+
value: string;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export const MENU_ACTIONS = {
|
|
12
|
+
BOARDS: 'boards',
|
|
13
|
+
EXPLORE: 'explore',
|
|
14
|
+
CREATE: 'create',
|
|
15
|
+
CONFIG: 'config',
|
|
16
|
+
EXIT: 'exit',
|
|
17
|
+
} as const;
|
|
18
|
+
|
|
19
|
+
export const CONFIG_ACTIONS = {
|
|
20
|
+
TOKEN: 'token',
|
|
21
|
+
VIEW: 'view',
|
|
22
|
+
RESET: 'reset',
|
|
23
|
+
BACK: 'back',
|
|
24
|
+
} as const;
|
|
25
|
+
|
|
26
|
+
export const CARD_ACTIONS = {
|
|
27
|
+
BACK: 'back',
|
|
28
|
+
EDIT: 'edit',
|
|
29
|
+
DELETE: 'delete',
|
|
30
|
+
MOVE: 'move',
|
|
31
|
+
} as const;
|