trello-cli-unofficial 0.7.6 → 0.8.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/README.md +27 -0
- package/bun.lock +225 -2
- package/dist/main.js +26490 -25401
- package/main.ts +6 -3
- package/package.json +15 -3
- package/src/application/use-cases/AuthenticateUserUseCase.ts +7 -6
- package/src/application/use-cases/CreateBoardUseCase.ts +19 -0
- package/src/application/use-cases/CreateCardUseCase.ts +2 -1
- package/src/application/use-cases/CreateListUseCase.ts +19 -0
- package/src/application/use-cases/GetBoardDetailsUseCase.ts +41 -0
- package/src/application/use-cases/UpdateCardUseCase.ts +2 -1
- package/src/application/use-cases/index.ts +3 -0
- package/src/domain/entities/Board.ts +10 -2
- package/src/domain/entities/Card.ts +12 -1
- package/src/domain/entities/Config.ts +3 -1
- package/src/domain/entities/List.ts +14 -2
- package/src/domain/repositories/TrelloRepository.ts +4 -0
- package/src/i18n/index.ts +62 -5
- package/src/i18n/locales/en.json +154 -17
- package/src/i18n/locales/pt-BR.json +154 -17
- package/src/infrastructure/repositories/FileConfigRepository.ts +6 -3
- package/src/infrastructure/repositories/TrelloApiRepository.ts +155 -10
- package/src/presentation/cli/AuthController.ts +2 -1
- package/src/presentation/cli/BoardController.ts +160 -17
- package/src/presentation/cli/CardController.ts +169 -45
- package/src/presentation/cli/CommandController.ts +293 -27
- package/src/presentation/cli/ConfigController.ts +4 -3
- package/src/presentation/cli/TrelloCliController.ts +10 -2
- package/src/shared/ErrorHandler.ts +233 -0
- package/src/shared/OutputFormatter.ts +210 -0
- package/src/shared/index.ts +2 -0
|
@@ -1,5 +1,7 @@
|
|
|
1
|
-
import type { CardEntity, ListEntity } from '@domain/entities';
|
|
1
|
+
import type { BoardEntity, CardEntity, ListEntity } from '@domain/entities';
|
|
2
2
|
import type { TrelloRepository } from '@domain/repositories';
|
|
3
|
+
import type { BoardController } from './BoardController';
|
|
4
|
+
import type { OutputFormatter } from '@/shared';
|
|
3
5
|
|
|
4
6
|
import {
|
|
5
7
|
CreateCardUseCase,
|
|
@@ -20,7 +22,8 @@ export class CardController {
|
|
|
20
22
|
|
|
21
23
|
constructor(
|
|
22
24
|
private trelloRepository: TrelloRepository,
|
|
23
|
-
private boardController:
|
|
25
|
+
private boardController: BoardController, // Will be injected to avoid circular dependency
|
|
26
|
+
private outputFormatter: OutputFormatter,
|
|
24
27
|
) {
|
|
25
28
|
this.createCardUseCase = new CreateCardUseCase(trelloRepository);
|
|
26
29
|
this.updateCardUseCase = new UpdateCardUseCase(trelloRepository);
|
|
@@ -29,28 +32,28 @@ export class CardController {
|
|
|
29
32
|
}
|
|
30
33
|
|
|
31
34
|
async createCardInteractive(): Promise<void> {
|
|
32
|
-
const boards = await
|
|
35
|
+
const boards = await this.boardController.getBoards();
|
|
33
36
|
|
|
34
37
|
const { selectedBoard } = await inquirer.prompt([
|
|
35
38
|
{
|
|
36
39
|
type: 'list',
|
|
37
40
|
name: 'selectedBoard',
|
|
38
41
|
message: t('card.selectBoard'),
|
|
39
|
-
choices: boards.map((board:
|
|
42
|
+
choices: boards.map((board: BoardEntity) => ({
|
|
40
43
|
name: board.name,
|
|
41
44
|
value: board.id,
|
|
42
45
|
})),
|
|
43
46
|
},
|
|
44
47
|
]);
|
|
45
48
|
|
|
46
|
-
const lists = await
|
|
49
|
+
const lists = await this.boardController.getLists(selectedBoard);
|
|
47
50
|
|
|
48
51
|
const { selectedList } = await inquirer.prompt([
|
|
49
52
|
{
|
|
50
53
|
type: 'list',
|
|
51
54
|
name: 'selectedList',
|
|
52
55
|
message: t('card.selectList'),
|
|
53
|
-
choices: lists.map((list:
|
|
56
|
+
choices: lists.map((list: ListEntity) => ({
|
|
54
57
|
name: list.name,
|
|
55
58
|
value: list.id,
|
|
56
59
|
})),
|
|
@@ -62,7 +65,8 @@ export class CardController {
|
|
|
62
65
|
type: 'input',
|
|
63
66
|
name: 'cardName',
|
|
64
67
|
message: t('card.enterName'),
|
|
65
|
-
validate: input =>
|
|
68
|
+
validate: input =>
|
|
69
|
+
input.length > 0 || t('card.validation.requiredName'),
|
|
66
70
|
},
|
|
67
71
|
{
|
|
68
72
|
type: 'input',
|
|
@@ -92,7 +96,7 @@ export class CardController {
|
|
|
92
96
|
},
|
|
93
97
|
]);
|
|
94
98
|
|
|
95
|
-
const cards = await
|
|
99
|
+
const cards = await this.boardController.getCards(selectedList);
|
|
96
100
|
|
|
97
101
|
if (cards.length === 0) {
|
|
98
102
|
console.log(t('card.emptyList'));
|
|
@@ -100,18 +104,20 @@ export class CardController {
|
|
|
100
104
|
}
|
|
101
105
|
|
|
102
106
|
console.log(
|
|
103
|
-
|
|
107
|
+
t('card.cardsInList', {
|
|
108
|
+
listName: lists.find(l => l.id === selectedList)?.name,
|
|
109
|
+
}),
|
|
104
110
|
);
|
|
105
|
-
cards.forEach((card:
|
|
111
|
+
cards.forEach((card: CardEntity, index: number) => {
|
|
106
112
|
console.log(`${index + 1}. ${card.name}`);
|
|
107
113
|
if (card.desc) {
|
|
108
114
|
const desc
|
|
109
115
|
= card.desc.length > 100
|
|
110
116
|
? `${card.desc.substring(0, 100)}...`
|
|
111
117
|
: card.desc;
|
|
112
|
-
console.log(
|
|
118
|
+
console.log(t('card.cardDescription', { description: desc }));
|
|
113
119
|
}
|
|
114
|
-
console.log(
|
|
120
|
+
console.log(`${t('card.cardUrl', { url: card.url })}\n`);
|
|
115
121
|
});
|
|
116
122
|
|
|
117
123
|
// Opções adicionais
|
|
@@ -124,7 +130,7 @@ export class CardController {
|
|
|
124
130
|
{ name: t('card.actions.back'), value: CARD_ACTIONS.BACK },
|
|
125
131
|
{ name: t('card.actions.edit'), value: CARD_ACTIONS.EDIT },
|
|
126
132
|
{ name: t('card.actions.delete'), value: CARD_ACTIONS.DELETE },
|
|
127
|
-
{ name: '
|
|
133
|
+
{ name: t('card.actions.moveCard'), value: CARD_ACTIONS.MOVE },
|
|
128
134
|
],
|
|
129
135
|
},
|
|
130
136
|
]);
|
|
@@ -135,14 +141,16 @@ export class CardController {
|
|
|
135
141
|
type: 'list',
|
|
136
142
|
name: 'selectedCard',
|
|
137
143
|
message: t('card.selectCard'),
|
|
138
|
-
choices: cards.map((card:
|
|
144
|
+
choices: cards.map((card: CardEntity) => ({
|
|
139
145
|
name: card.name,
|
|
140
146
|
value: card.id,
|
|
141
147
|
})),
|
|
142
148
|
},
|
|
143
149
|
]);
|
|
144
150
|
|
|
145
|
-
const selectedCardEntity = cards.find(
|
|
151
|
+
const selectedCardEntity = cards.find(
|
|
152
|
+
(c: CardEntity) => c.id === selectedCard,
|
|
153
|
+
)!;
|
|
146
154
|
|
|
147
155
|
switch (nextAction) {
|
|
148
156
|
case CARD_ACTIONS.EDIT:
|
|
@@ -195,7 +203,7 @@ export class CardController {
|
|
|
195
203
|
]);
|
|
196
204
|
|
|
197
205
|
if (confirm) {
|
|
198
|
-
await this.deleteCard(cardId
|
|
206
|
+
await this.deleteCard(cardId);
|
|
199
207
|
}
|
|
200
208
|
}
|
|
201
209
|
|
|
@@ -226,15 +234,15 @@ export class CardController {
|
|
|
226
234
|
cardName: string,
|
|
227
235
|
description?: string,
|
|
228
236
|
): Promise<void> {
|
|
229
|
-
const boards = await
|
|
230
|
-
const board = boards.find((b:
|
|
237
|
+
const boards = await this.boardController.getBoards();
|
|
238
|
+
const board = boards.find((b: BoardEntity) => b.name === boardName);
|
|
231
239
|
|
|
232
240
|
if (!board) {
|
|
233
241
|
throw new Error(t('board.notFound', { name: boardName }));
|
|
234
242
|
}
|
|
235
243
|
|
|
236
|
-
const lists = await
|
|
237
|
-
const list = lists.find((l:
|
|
244
|
+
const lists = await this.boardController.getLists(board.id);
|
|
245
|
+
const list = lists.find((l: ListEntity) => l.name === listName);
|
|
238
246
|
|
|
239
247
|
if (!list) {
|
|
240
248
|
throw new Error(t('list.notFound', { listName, boardName }));
|
|
@@ -255,20 +263,22 @@ export class CardController {
|
|
|
255
263
|
async moveCard(cardId: string, targetListName: string): Promise<void> {
|
|
256
264
|
// Primeiro precisamos encontrar em qual board o cartão está
|
|
257
265
|
// Para isso, vamos buscar todas as listas de todos os boards
|
|
258
|
-
const boards = await
|
|
266
|
+
const boards = await this.boardController.getBoards();
|
|
259
267
|
|
|
260
268
|
for (const board of boards) {
|
|
261
|
-
const lists = await
|
|
269
|
+
const lists = await this.boardController.getLists(board.id);
|
|
262
270
|
|
|
263
271
|
// Verificar se alguma lista contém o cartão
|
|
264
272
|
for (const list of lists) {
|
|
265
273
|
try {
|
|
266
|
-
const cards = await
|
|
267
|
-
const card = cards.find((c:
|
|
274
|
+
const cards = await this.boardController.getCards(list.id);
|
|
275
|
+
const card = cards.find((c: CardEntity) => c.id === cardId);
|
|
268
276
|
|
|
269
277
|
if (card) {
|
|
270
278
|
// Encontrou o cartão! Agora procurar a lista de destino
|
|
271
|
-
const targetList = lists.find(
|
|
279
|
+
const targetList = lists.find(
|
|
280
|
+
(l: ListEntity) => l.name === targetListName,
|
|
281
|
+
);
|
|
272
282
|
|
|
273
283
|
if (!targetList) {
|
|
274
284
|
throw new Error(
|
|
@@ -295,38 +305,152 @@ export class CardController {
|
|
|
295
305
|
throw new Error(t('card.notFound', { cardId }));
|
|
296
306
|
}
|
|
297
307
|
|
|
298
|
-
async deleteCard(cardId: string
|
|
299
|
-
//
|
|
308
|
+
async deleteCard(cardId: string): Promise<void> {
|
|
309
|
+
// Primeiro precisamos encontrar o cartão para mostrar informações
|
|
310
|
+
const boards = await this.trelloRepository.getBoards();
|
|
311
|
+
let card: CardEntity | undefined;
|
|
312
|
+
|
|
313
|
+
for (const board of boards) {
|
|
314
|
+
const lists = await this.trelloRepository.getLists(board.id);
|
|
315
|
+
|
|
316
|
+
for (const list of lists) {
|
|
317
|
+
try {
|
|
318
|
+
const cards = await this.trelloRepository.getCards(list.id);
|
|
319
|
+
card = cards.find((c: CardEntity) => c.id === cardId);
|
|
320
|
+
|
|
321
|
+
if (card) {
|
|
322
|
+
break;
|
|
323
|
+
}
|
|
324
|
+
} catch {
|
|
325
|
+
continue;
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
if (card) {
|
|
329
|
+
break;
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
|
|
300
333
|
if (!card) {
|
|
301
|
-
|
|
334
|
+
throw new Error(t('card.notFound', { cardId }));
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
await this.deleteCardUseCase.execute(cardId);
|
|
338
|
+
console.log(t('card.deleted'));
|
|
339
|
+
console.log(t('card.cardName', { name: card.name }));
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
async createCardByListId(
|
|
343
|
+
listId: string,
|
|
344
|
+
cardName: string,
|
|
345
|
+
description?: string,
|
|
346
|
+
): Promise<void> {
|
|
347
|
+
const newCard = await this.createCardUseCase.execute({
|
|
348
|
+
name: cardName,
|
|
349
|
+
desc: description || '',
|
|
350
|
+
listId,
|
|
351
|
+
});
|
|
352
|
+
|
|
353
|
+
console.log(t('card.created'));
|
|
354
|
+
console.log(t('card.cardName', { name: newCard.name }));
|
|
355
|
+
console.log(t('card.cardUrl', { url: newCard.url }));
|
|
356
|
+
console.log(t('card.cardId', { id: newCard.id }));
|
|
357
|
+
}
|
|
302
358
|
|
|
303
|
-
|
|
304
|
-
|
|
359
|
+
async updateCard(
|
|
360
|
+
cardId: string,
|
|
361
|
+
name?: string,
|
|
362
|
+
desc?: string,
|
|
363
|
+
): Promise<void> {
|
|
364
|
+
// Primeiro precisamos encontrar o cartão para mostrar informações
|
|
365
|
+
const boards = await this.trelloRepository.getBoards();
|
|
366
|
+
let card: CardEntity | undefined;
|
|
305
367
|
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
const cards = await (this.boardController as any).getCards(list.id);
|
|
309
|
-
card = cards.find((c: any) => c.id === cardId);
|
|
368
|
+
for (const board of boards) {
|
|
369
|
+
const lists = await this.trelloRepository.getLists(board.id);
|
|
310
370
|
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
371
|
+
for (const list of lists) {
|
|
372
|
+
try {
|
|
373
|
+
const cards = await this.trelloRepository.getCards(list.id);
|
|
374
|
+
card = cards.find((c: CardEntity) => c.id === cardId);
|
|
375
|
+
|
|
376
|
+
if (card) {
|
|
377
|
+
break;
|
|
316
378
|
}
|
|
379
|
+
} catch {
|
|
380
|
+
continue;
|
|
317
381
|
}
|
|
318
|
-
|
|
319
|
-
|
|
382
|
+
}
|
|
383
|
+
if (card) {
|
|
384
|
+
break;
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
if (!card) {
|
|
389
|
+
throw new Error(t('card.notFound', { cardId }));
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
const updateData: { name?: string; desc?: string } = {};
|
|
393
|
+
if (name !== undefined) {
|
|
394
|
+
updateData.name = name;
|
|
395
|
+
}
|
|
396
|
+
if (desc !== undefined) {
|
|
397
|
+
updateData.desc = desc;
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
const updatedCard = await this.updateCardUseCase.execute(
|
|
401
|
+
cardId,
|
|
402
|
+
updateData,
|
|
403
|
+
);
|
|
404
|
+
console.log(t('card.updated'));
|
|
405
|
+
console.log(t('card.cardName', { name: updatedCard.name }));
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
async moveCardToList(cardId: string, targetListId: string): Promise<void> {
|
|
409
|
+
// Primeiro precisamos encontrar o cartão para mostrar informações
|
|
410
|
+
const boards = await this.trelloRepository.getBoards();
|
|
411
|
+
let card: CardEntity | undefined;
|
|
412
|
+
|
|
413
|
+
for (const board of boards) {
|
|
414
|
+
const lists = await this.trelloRepository.getLists(board.id);
|
|
415
|
+
|
|
416
|
+
for (const list of lists) {
|
|
417
|
+
try {
|
|
418
|
+
const cards = await this.trelloRepository.getCards(list.id);
|
|
419
|
+
card = cards.find((c: CardEntity) => c.id === cardId);
|
|
420
|
+
|
|
421
|
+
if (card) {
|
|
422
|
+
break;
|
|
423
|
+
}
|
|
424
|
+
} catch {
|
|
425
|
+
continue;
|
|
320
426
|
}
|
|
321
427
|
}
|
|
428
|
+
if (card) {
|
|
429
|
+
break;
|
|
430
|
+
}
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
if (!card) {
|
|
434
|
+
throw new Error(t('card.notFound', { cardId }));
|
|
435
|
+
}
|
|
322
436
|
|
|
323
|
-
|
|
324
|
-
|
|
437
|
+
// Verificar se a lista de destino existe procurando em todos os boards
|
|
438
|
+
let targetList: ListEntity | undefined;
|
|
439
|
+
for (const board of boards) {
|
|
440
|
+
const lists = await this.trelloRepository.getLists(board.id);
|
|
441
|
+
targetList = lists.find((l: ListEntity) => l.id === targetListId);
|
|
442
|
+
if (targetList) {
|
|
443
|
+
break;
|
|
325
444
|
}
|
|
326
445
|
}
|
|
327
446
|
|
|
328
|
-
|
|
329
|
-
|
|
447
|
+
if (!targetList) {
|
|
448
|
+
throw new Error(t('list.notFound', { listId: targetListId }));
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
await this.moveCardUseCase.execute(cardId, targetListId);
|
|
452
|
+
console.log(t('card.moved'));
|
|
330
453
|
console.log(t('card.cardName', { name: card.name }));
|
|
454
|
+
console.log(t('card.movedTo', { listName: targetList.name }));
|
|
331
455
|
}
|
|
332
456
|
}
|