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.
Files changed (31) hide show
  1. package/README.md +27 -0
  2. package/bun.lock +225 -2
  3. package/dist/main.js +26490 -25401
  4. package/main.ts +6 -3
  5. package/package.json +15 -3
  6. package/src/application/use-cases/AuthenticateUserUseCase.ts +7 -6
  7. package/src/application/use-cases/CreateBoardUseCase.ts +19 -0
  8. package/src/application/use-cases/CreateCardUseCase.ts +2 -1
  9. package/src/application/use-cases/CreateListUseCase.ts +19 -0
  10. package/src/application/use-cases/GetBoardDetailsUseCase.ts +41 -0
  11. package/src/application/use-cases/UpdateCardUseCase.ts +2 -1
  12. package/src/application/use-cases/index.ts +3 -0
  13. package/src/domain/entities/Board.ts +10 -2
  14. package/src/domain/entities/Card.ts +12 -1
  15. package/src/domain/entities/Config.ts +3 -1
  16. package/src/domain/entities/List.ts +14 -2
  17. package/src/domain/repositories/TrelloRepository.ts +4 -0
  18. package/src/i18n/index.ts +62 -5
  19. package/src/i18n/locales/en.json +154 -17
  20. package/src/i18n/locales/pt-BR.json +154 -17
  21. package/src/infrastructure/repositories/FileConfigRepository.ts +6 -3
  22. package/src/infrastructure/repositories/TrelloApiRepository.ts +155 -10
  23. package/src/presentation/cli/AuthController.ts +2 -1
  24. package/src/presentation/cli/BoardController.ts +160 -17
  25. package/src/presentation/cli/CardController.ts +169 -45
  26. package/src/presentation/cli/CommandController.ts +293 -27
  27. package/src/presentation/cli/ConfigController.ts +4 -3
  28. package/src/presentation/cli/TrelloCliController.ts +10 -2
  29. package/src/shared/ErrorHandler.ts +233 -0
  30. package/src/shared/OutputFormatter.ts +210 -0
  31. package/src/shared/index.ts +2 -0
@@ -1,9 +1,14 @@
1
+ import type { OutputFormat } from '@/shared';
2
+
1
3
  import { AuthenticationService } from '@domain/services';
2
4
  import {
3
5
  FileConfigRepository,
4
6
  TrelloApiRepository,
5
7
  } from '@infrastructure/repositories';
6
8
  import { Command } from 'commander';
9
+
10
+ import { t } from '@/i18n';
11
+ import { ErrorHandler, OutputFormatter } from '@/shared';
7
12
  import { AuthController, BoardController, CardController } from './index';
8
13
 
9
14
  export class CommandController {
@@ -11,11 +16,13 @@ export class CommandController {
11
16
  private boardController!: BoardController;
12
17
  private cardController!: CardController;
13
18
  private program: Command;
19
+ private outputFormatter: OutputFormatter;
14
20
 
15
21
  constructor() {
16
22
  const configRepository = new FileConfigRepository();
17
23
  this.authController = new AuthController(configRepository);
18
24
  this.program = new Command();
25
+ this.outputFormatter = new OutputFormatter();
19
26
  this.setupCommands();
20
27
  }
21
28
 
@@ -29,78 +36,325 @@ export class CommandController {
29
36
  config.token!,
30
37
  );
31
38
 
32
- this.boardController = new BoardController(trelloRepository);
39
+ this.boardController = new BoardController(
40
+ trelloRepository,
41
+ this.outputFormatter,
42
+ );
33
43
  this.cardController = new CardController(
34
44
  trelloRepository,
35
45
  this.boardController,
46
+ this.outputFormatter,
36
47
  );
37
48
  }
38
49
 
39
50
  private setupCommands(): void {
40
51
  this.program
41
52
  .name('trello-cli-unofficial')
42
- .description('Unofficial Trello CLI using Power-Up authentication')
43
- .version('1.0.0');
53
+ .description(t('commands.description'))
54
+ .version('1.0.0')
55
+ .option('-f, --format <format>', t('commands.formatOption'), 'table')
56
+ .on('option:format', (format) => {
57
+ this.outputFormatter.setFormat(format as OutputFormat);
58
+ });
44
59
 
60
+ // Interactive mode
45
61
  this.program
46
62
  .command('interactive')
47
63
  .alias('i')
48
- .description('Start interactive mode')
64
+ .description(t('commands.interactive.description'))
49
65
  .action(async () => {
50
66
  const configRepository = new FileConfigRepository();
51
67
  const cli = new (
52
68
  await import('./TrelloCliController')
53
- ).TrelloCliController(configRepository);
69
+ ).TrelloCliController(configRepository, this.outputFormatter);
54
70
  await cli.run();
55
71
  });
56
72
 
73
+ // Setup command
57
74
  this.program
58
- .command('boards')
59
- .description('List all your Trello boards')
75
+ .command('setup')
76
+ .description(t('commands.setup.description'))
60
77
  .action(async () => {
78
+ await this.authController.setupToken();
79
+ });
80
+
81
+ // Boards subcommands
82
+ const boardsCmd = this.program
83
+ .command('boards')
84
+ .description(t('commands.boards.manage'));
85
+
86
+ boardsCmd
87
+ .command('list')
88
+ .description(t('commands.boards.description'))
89
+ .option('-f, --format <format>', t('commands.formatOption'), 'table')
90
+ .action(async (options: { format?: string }) => {
61
91
  try {
62
92
  await this.initializeTrelloControllers();
93
+ if (options.format) {
94
+ this.outputFormatter.setFormat(options.format as OutputFormat);
95
+ }
63
96
  await this.boardController.showBoards();
97
+ } catch (error) {
98
+ ErrorHandler.handle(error, 'boards list');
99
+ }
100
+ });
101
+
102
+ boardsCmd
103
+ .command('show <boardId>')
104
+ .description(t('commands.boards.show.description'))
105
+ .option('-f, --format <format>', t('commands.formatOption'), 'table')
106
+ .action(async (boardId: string, options: { format?: string }) => {
107
+ try {
108
+ await this.initializeTrelloControllers();
109
+ if (options.format) {
110
+ this.outputFormatter.setFormat(options.format as OutputFormat);
111
+ }
112
+ await this.boardController.showBoardDetails(boardId);
113
+ } catch (error) {
114
+ ErrorHandler.handle(error, 'boards show');
115
+ }
116
+ });
117
+
118
+ boardsCmd
119
+ .command('create <name>')
120
+ .description(t('commands.boards.create.description'))
121
+ .option(
122
+ '-d, --desc <description>',
123
+ t('commands.boards.create.descOption'),
124
+ )
125
+ .action(async (name: string, options: { desc?: string }) => {
126
+ try {
127
+ await this.initializeTrelloControllers();
128
+ await this.boardController.createBoard(name, options.desc);
64
129
  } catch (error) {
65
130
  console.error('❌ Erro:', (error as Error).message);
66
131
  }
67
132
  });
68
133
 
134
+ // Legacy boards command with deprecation warning
69
135
  this.program
70
- .command('setup')
71
- .description('Setup your Trello token')
136
+ .command('boards-legacy')
137
+ .description(t('commands.deprecated.boardsLegacyDescription'))
72
138
  .action(async () => {
73
- await this.authController.setupToken();
139
+ console.warn(t('commands.deprecated.boardsLegacyWarning'));
140
+ try {
141
+ await this.initializeTrelloControllers();
142
+ await this.boardController.showBoards();
143
+ } catch (error) {
144
+ console.error(
145
+ t('commands.deprecated.boardsLegacyError'),
146
+ (error as Error).message,
147
+ );
148
+ }
149
+ });
150
+
151
+ // Lists subcommands
152
+ const listsCmd = this.program
153
+ .command('lists')
154
+ .description(t('commands.lists.description'));
155
+
156
+ listsCmd
157
+ .command('list <boardId>')
158
+ .description(t('commands.lists.list.description'))
159
+ .option('-f, --format <format>', t('commands.formatOption'), 'table')
160
+ .action(async (boardId: string, options: { format?: string }) => {
161
+ try {
162
+ await this.initializeTrelloControllers();
163
+ if (options.format) {
164
+ this.outputFormatter.setFormat(options.format as OutputFormat);
165
+ }
166
+ await this.boardController.showListsById(boardId);
167
+ } catch (error) {
168
+ ErrorHandler.handle(error, 'lists list');
169
+ }
170
+ });
171
+
172
+ listsCmd
173
+ .command('create <boardId> <name>')
174
+ .description(t('commands.lists.create.description'))
175
+ .action(async (boardId: string, name: string) => {
176
+ try {
177
+ await this.initializeTrelloControllers();
178
+ await this.boardController.createList(boardId, name);
179
+ } catch (error) {
180
+ console.error(
181
+ t('commands.commandErrors.genericError'),
182
+ (error as Error).message,
183
+ );
184
+ }
185
+ });
186
+
187
+ listsCmd
188
+ .command('delete <listId>')
189
+ .description(t('commands.lists.delete.description'))
190
+ .action(async (listId: string) => {
191
+ try {
192
+ await this.initializeTrelloControllers();
193
+ await this.boardController.deleteList(listId);
194
+ } catch (error) {
195
+ console.error(
196
+ t('commands.commandErrors.genericError'),
197
+ (error as Error).message,
198
+ );
199
+ }
200
+ });
201
+
202
+ listsCmd
203
+ .command('move <listId> <position>')
204
+ .description(t('commands.lists.move.description'))
205
+ .action(async (listId: string, position: string) => {
206
+ try {
207
+ await this.initializeTrelloControllers();
208
+ await this.boardController.moveList(
209
+ listId,
210
+ Number.parseInt(position),
211
+ );
212
+ } catch (error) {
213
+ console.error(
214
+ t('commands.commandErrors.genericError'),
215
+ (error as Error).message,
216
+ );
217
+ }
74
218
  });
75
219
 
220
+ // Legacy lists command with deprecation warning
76
221
  this.program
77
- .command('lists <boardName>')
78
- .description('List all lists in a specific board')
222
+ .command('lists-legacy <boardName>')
223
+ .description(t('commands.deprecated.listsLegacyDescription'))
79
224
  .action(async (boardName: string) => {
225
+ console.warn(t('commands.deprecated.listsLegacyWarning'));
80
226
  try {
81
227
  await this.initializeTrelloControllers();
82
228
  await this.boardController.showLists(boardName);
83
229
  } catch (error) {
84
- console.error('❌ Erro:', (error as Error).message);
230
+ console.error(
231
+ t('commands.deprecated.listsLegacyError'),
232
+ (error as Error).message,
233
+ );
234
+ }
235
+ });
236
+
237
+ // Cards subcommands
238
+ const cardsCmd = this.program
239
+ .command('cards')
240
+ .description(t('commands.cards.manage'));
241
+
242
+ cardsCmd
243
+ .command('list <listId>')
244
+ .description(t('commands.cards.list.description'))
245
+ .option('-f, --format <format>', t('commands.formatOption'), 'table')
246
+ .action(async (listId: string, options: { format?: string }) => {
247
+ try {
248
+ await this.initializeTrelloControllers();
249
+ if (options.format) {
250
+ this.outputFormatter.setFormat(options.format as OutputFormat);
251
+ }
252
+ await this.boardController.showCardsByListId(listId);
253
+ } catch (error) {
254
+ ErrorHandler.handle(error, 'cards list');
255
+ }
256
+ });
257
+
258
+ cardsCmd
259
+ .command('create <listId> <name>')
260
+ .description(t('commands.cards.create.description'))
261
+ .option('-d, --desc <description>', t('commands.options.cardDescription'))
262
+ .action(
263
+ async (listId: string, name: string, options: { desc?: string }) => {
264
+ try {
265
+ await this.initializeTrelloControllers();
266
+ await this.cardController.createCardByListId(
267
+ listId,
268
+ name,
269
+ options.desc,
270
+ );
271
+ } catch (error) {
272
+ console.error(
273
+ t('commands.commandErrors.genericError'),
274
+ (error as Error).message,
275
+ );
276
+ }
277
+ },
278
+ );
279
+
280
+ cardsCmd
281
+ .command('move <cardId>')
282
+ .description(t('commands.cards.move.description'))
283
+ .requiredOption('-t, --to <listId>', t('commands.options.targetListId'))
284
+ .action(async (cardId: string, options: { to: string }) => {
285
+ try {
286
+ await this.initializeTrelloControllers();
287
+ await this.cardController.moveCardToList(cardId, options.to);
288
+ } catch (error) {
289
+ console.error(
290
+ t('commands.commandErrors.genericError'),
291
+ (error as Error).message,
292
+ );
293
+ }
294
+ });
295
+
296
+ cardsCmd
297
+ .command('delete <cardId>')
298
+ .description(t('commands.cards.delete.description'))
299
+ .action(async (cardId: string) => {
300
+ try {
301
+ await this.initializeTrelloControllers();
302
+ await this.cardController.deleteCard(cardId);
303
+ } catch (error) {
304
+ console.error(
305
+ t('commands.commandErrors.genericError'),
306
+ (error as Error).message,
307
+ );
85
308
  }
86
309
  });
87
310
 
311
+ cardsCmd
312
+ .command('update <cardId>')
313
+ .description(t('commands.cards.update.description'))
314
+ .option('-n, --name <name>', t('commands.options.newCardName'))
315
+ .option(
316
+ '-d, --desc <description>',
317
+ t('commands.options.newCardDescription'),
318
+ )
319
+ .action(
320
+ async (cardId: string, options: { name?: string; desc?: string }) => {
321
+ try {
322
+ await this.initializeTrelloControllers();
323
+ await this.cardController.updateCard(
324
+ cardId,
325
+ options.name,
326
+ options.desc,
327
+ );
328
+ } catch (error) {
329
+ console.error(
330
+ t('commands.commandErrors.genericError'),
331
+ (error as Error).message,
332
+ );
333
+ }
334
+ },
335
+ );
336
+
337
+ // Legacy commands with deprecation warnings
88
338
  this.program
89
- .command('cards <boardName> <listName>')
90
- .description('List all cards in a specific list')
339
+ .command('cards-legacy <boardName> <listName>')
340
+ .description(t('commands.deprecated.cardsLegacyDescription'))
91
341
  .action(async (boardName: string, listName: string) => {
342
+ console.warn(t('commands.deprecated.cardsLegacyWarning'));
92
343
  try {
93
344
  await this.initializeTrelloControllers();
94
345
  await this.boardController.showCards(boardName, listName);
95
346
  } catch (error) {
96
- console.error('❌ Erro:', (error as Error).message);
347
+ console.error(
348
+ t('commands.deprecated.cardsLegacyError'),
349
+ (error as Error).message,
350
+ );
97
351
  }
98
352
  });
99
353
 
100
354
  this.program
101
- .command('create-card <boardName> <listName> <cardName>')
102
- .description('Create a new card in a specific board and list')
103
- .option('-d, --desc <description>', 'Card description')
355
+ .command('create-card-legacy <boardName> <listName> <cardName>')
356
+ .description(t('commands.deprecated.createCardLegacyDescription'))
357
+ .option('-d, --desc <description>', t('commands.options.cardDescription'))
104
358
  .action(
105
359
  async (
106
360
  boardName: string,
@@ -108,6 +362,7 @@ export class CommandController {
108
362
  cardName: string,
109
363
  options: { desc?: string },
110
364
  ) => {
365
+ console.warn(t('commands.deprecated.createCardLegacyWarning'));
111
366
  try {
112
367
  await this.initializeTrelloControllers();
113
368
  await this.cardController.createCard(
@@ -117,32 +372,43 @@ export class CommandController {
117
372
  options.desc,
118
373
  );
119
374
  } catch (error) {
120
- console.error('❌ Erro:', (error as Error).message);
375
+ console.error(
376
+ t('commands.commandErrors.genericError'),
377
+ (error as Error).message,
378
+ );
121
379
  }
122
380
  },
123
381
  );
124
382
 
125
383
  this.program
126
- .command('move-card <cardId> <listName>')
127
- .description('Move a card to a different list')
384
+ .command('move-card-legacy <cardId> <listName>')
385
+ .description(t('commands.deprecated.moveCardLegacyDescription'))
128
386
  .action(async (cardId: string, listName: string) => {
387
+ console.warn(t('commands.deprecated.moveCardLegacyWarning'));
129
388
  try {
130
389
  await this.initializeTrelloControllers();
131
390
  await this.cardController.moveCard(cardId, listName);
132
391
  } catch (error) {
133
- console.error('❌ Erro:', (error as Error).message);
392
+ console.error(
393
+ t('commands.commandErrors.genericError'),
394
+ (error as Error).message,
395
+ );
134
396
  }
135
397
  });
136
398
 
137
399
  this.program
138
- .command('delete-card <cardId>')
139
- .description('Delete a card by its ID')
400
+ .command('delete-card-legacy <cardId>')
401
+ .description(t('commands.deprecated.deleteCardLegacyDescription'))
140
402
  .action(async (cardId: string) => {
403
+ console.warn(t('commands.deprecated.deleteCardLegacyWarning'));
141
404
  try {
142
405
  await this.initializeTrelloControllers();
143
406
  await this.cardController.deleteCard(cardId);
144
407
  } catch (error) {
145
- console.error('❌ Erro:', (error as Error).message);
408
+ console.error(
409
+ t('commands.commandErrors.genericError'),
410
+ (error as Error).message,
411
+ );
146
412
  }
147
413
  });
148
414
  }
@@ -153,7 +419,7 @@ export class CommandController {
153
419
  const configRepository = new FileConfigRepository();
154
420
  const cli = new (
155
421
  await import('./TrelloCliController')
156
- ).TrelloCliController(configRepository);
422
+ ).TrelloCliController(configRepository, this.outputFormatter);
157
423
  await cli.run();
158
424
  } else {
159
425
  this.program.parse();
@@ -1,10 +1,11 @@
1
+ import type { AuthController } from './AuthController';
1
2
  import { CONFIG_ACTIONS } from '@shared/types';
2
3
 
3
4
  import inquirer from 'inquirer';
4
5
  import { t } from '@/i18n';
5
6
 
6
7
  export class ConfigController {
7
- constructor(private authController: { getConfig: () => Promise<unknown>; setupToken: () => Promise<void> }) {}
8
+ constructor(private authController: AuthController) {}
8
9
 
9
10
  async showConfigMenu(): Promise<void> {
10
11
  while (true) {
@@ -27,9 +28,9 @@ export class ConfigController {
27
28
  await this.authController.setupToken();
28
29
  break;
29
30
  case CONFIG_ACTIONS.VIEW:
30
- const config = await this.authController.getConfig() as any;
31
+ const config = await this.authController.getConfig();
31
32
  console.log(t('menu.currentConfig'));
32
- console.log(`API Key: ${config.apiKey}`);
33
+ console.log(`${t('menu.apiKey')} ${config.apiKey}`);
33
34
  const tokenStatus = config.hasValidToken()
34
35
  ? `✅ ${t('common.yes')}`
35
36
  : `❌ ${t('common.no')}`;
@@ -1,4 +1,5 @@
1
1
  import type { ConfigRepository } from '@domain/repositories';
2
+ import type { OutputFormatter } from '@/shared';
2
3
  import { AuthenticationService } from '@domain/services';
3
4
  import { TrelloApiRepository } from '@infrastructure/repositories';
4
5
  import {
@@ -16,7 +17,10 @@ export class TrelloCliController {
16
17
  private configController!: ConfigController;
17
18
  private mainMenuController!: MainMenuController;
18
19
 
19
- constructor(private configRepository: ConfigRepository) {
20
+ constructor(
21
+ private configRepository: ConfigRepository,
22
+ private outputFormatter: OutputFormatter,
23
+ ) {
20
24
  this.initializeControllers();
21
25
  }
22
26
 
@@ -33,10 +37,14 @@ export class TrelloCliController {
33
37
  config.token!,
34
38
  );
35
39
 
36
- this.boardController = new BoardController(trelloRepository);
40
+ this.boardController = new BoardController(
41
+ trelloRepository,
42
+ this.outputFormatter,
43
+ );
37
44
  this.cardController = new CardController(
38
45
  trelloRepository,
39
46
  this.boardController,
47
+ this.outputFormatter,
40
48
  );
41
49
  this.configController = new ConfigController(this.authController);
42
50
  this.mainMenuController = new MainMenuController(