trello-cli-unofficial 0.11.6 → 0.12.1
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/CHANGELOG.md +14 -0
- package/README.md +7 -0
- package/dist/main.js +142 -37
- package/dist/trello-cli-unofficial-0.12.1.tgz +0 -0
- package/package.json +1 -1
- package/src/application/use-cases/GetCardUseCase.ts +10 -0
- package/src/application/use-cases/index.ts +1 -0
- package/src/domain/entities/Card.ts +23 -1
- package/src/domain/repositories/TrelloRepository.ts +1 -0
- package/src/i18n/locales/en.json +9 -0
- package/src/i18n/locales/pt-BR.json +9 -0
- package/src/infrastructure/repositories/TrelloApiRepository.ts +10 -1
- package/src/presentation/cli/CardController.ts +53 -0
- package/src/presentation/cli/CommandController.ts +84 -44
- package/dist/trello-cli-unofficial-0.11.6.tgz +0 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,17 @@
|
|
|
1
|
+
## [0.12.1](https://github.com/JaegerCaiser/trello-cli-unofficial/compare/v0.12.0...v0.12.1) (2025-11-17)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Bug Fixes
|
|
5
|
+
|
|
6
|
+
* **cli:** remove hardcoded version fallback in getVersion() ([72c04ef](https://github.com/JaegerCaiser/trello-cli-unofficial/commit/72c04ef59966efada5ba095f7e2c5282540015f6))
|
|
7
|
+
|
|
8
|
+
# [0.12.0](https://github.com/JaegerCaiser/trello-cli-unofficial/compare/v0.11.6...v0.12.0) (2025-11-17)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
### Features
|
|
12
|
+
|
|
13
|
+
* **cards:** add cards show command ([a98fa9f](https://github.com/JaegerCaiser/trello-cli-unofficial/commit/a98fa9fe2244bbd8ba754e725b867ee22cfd4c33))
|
|
14
|
+
|
|
1
15
|
## [0.11.6](https://github.com/JaegerCaiser/trello-cli-unofficial/compare/v0.11.5...v0.11.6) (2025-11-14)
|
|
2
16
|
|
|
3
17
|
|
package/README.md
CHANGED
|
@@ -252,6 +252,13 @@ tcu
|
|
|
252
252
|
- **Delete**: Confirm before removing
|
|
253
253
|
- **Move**: Select destination list
|
|
254
254
|
|
|
255
|
+
### Show Card Details
|
|
256
|
+
|
|
257
|
+
```bash
|
|
258
|
+
# Show detailed information about a card, including checklists, members, labels and attachments
|
|
259
|
+
tcu cards show <cardId>
|
|
260
|
+
```
|
|
261
|
+
|
|
255
262
|
## 🤖 CI/CD & Automation
|
|
256
263
|
|
|
257
264
|
This project uses automated CI/CD with semantic versioning based on **commit messages**:
|
package/dist/main.js
CHANGED
|
@@ -2588,6 +2588,12 @@ var require_en = __commonJS((exports, module) => {
|
|
|
2588
2588
|
delete: "\uD83D\uDDD1\uFE0F Delete Card",
|
|
2589
2589
|
back: "\u2B05\uFE0F Back",
|
|
2590
2590
|
moveCard: "\uD83D\uDCE6 Move card"
|
|
2591
|
+
},
|
|
2592
|
+
show: {
|
|
2593
|
+
labels: "\uD83C\uDFF7\uFE0F Labels:",
|
|
2594
|
+
members: "\uD83D\uDC65 Members:",
|
|
2595
|
+
checklists: "\u2705 Checklists:",
|
|
2596
|
+
attachments: "\uD83D\uDCCE Attachments:"
|
|
2591
2597
|
}
|
|
2592
2598
|
},
|
|
2593
2599
|
errors: {
|
|
@@ -2724,6 +2730,9 @@ var require_en = __commonJS((exports, module) => {
|
|
|
2724
2730
|
update: {
|
|
2725
2731
|
description: "Update an existing card"
|
|
2726
2732
|
},
|
|
2733
|
+
show: {
|
|
2734
|
+
description: "Show detailed information about a specific card"
|
|
2735
|
+
},
|
|
2727
2736
|
delete: {
|
|
2728
2737
|
description: "Delete a card"
|
|
2729
2738
|
}
|
|
@@ -2863,6 +2872,12 @@ var require_pt_BR = __commonJS((exports, module) => {
|
|
|
2863
2872
|
delete: "\uD83D\uDDD1\uFE0F Deletar Card",
|
|
2864
2873
|
back: "\u2B05\uFE0F Voltar",
|
|
2865
2874
|
moveCard: "\uD83D\uDCE6 Mover cart\xE3o"
|
|
2875
|
+
},
|
|
2876
|
+
show: {
|
|
2877
|
+
labels: "\uD83C\uDFF7\uFE0F Labels:",
|
|
2878
|
+
members: "\uD83D\uDC65 Membros:",
|
|
2879
|
+
checklists: "\u2705 Checklists:",
|
|
2880
|
+
attachments: "\uD83D\uDCCE Anexos:"
|
|
2866
2881
|
}
|
|
2867
2882
|
},
|
|
2868
2883
|
errors: {
|
|
@@ -2999,6 +3014,9 @@ var require_pt_BR = __commonJS((exports, module) => {
|
|
|
2999
3014
|
update: {
|
|
3000
3015
|
description: "Atualiza um card existente"
|
|
3001
3016
|
},
|
|
3017
|
+
show: {
|
|
3018
|
+
description: "Mostra informa\xE7\xF5es detalhadas sobre um card espec\xEDfico"
|
|
3019
|
+
},
|
|
3002
3020
|
delete: {
|
|
3003
3021
|
description: "Deleta um card"
|
|
3004
3022
|
}
|
|
@@ -3251,6 +3269,17 @@ class GetCardsUseCase {
|
|
|
3251
3269
|
}
|
|
3252
3270
|
}
|
|
3253
3271
|
|
|
3272
|
+
// src/application/use-cases/GetCardUseCase.ts
|
|
3273
|
+
class GetCardUseCase {
|
|
3274
|
+
trelloRepository;
|
|
3275
|
+
constructor(trelloRepository) {
|
|
3276
|
+
this.trelloRepository = trelloRepository;
|
|
3277
|
+
}
|
|
3278
|
+
async execute(cardId) {
|
|
3279
|
+
return await this.trelloRepository.getCard(cardId);
|
|
3280
|
+
}
|
|
3281
|
+
}
|
|
3282
|
+
|
|
3254
3283
|
// src/application/use-cases/GetListsUseCase.ts
|
|
3255
3284
|
class GetListsUseCase {
|
|
3256
3285
|
trelloRepository;
|
|
@@ -26134,6 +26163,7 @@ class CardController {
|
|
|
26134
26163
|
updateCardUseCase;
|
|
26135
26164
|
deleteCardUseCase;
|
|
26136
26165
|
moveCardUseCase;
|
|
26166
|
+
getCardUseCase;
|
|
26137
26167
|
constructor(trelloRepository, boardController, outputFormatter) {
|
|
26138
26168
|
this.trelloRepository = trelloRepository;
|
|
26139
26169
|
this.boardController = boardController;
|
|
@@ -26142,6 +26172,7 @@ class CardController {
|
|
|
26142
26172
|
this.updateCardUseCase = new UpdateCardUseCase(trelloRepository);
|
|
26143
26173
|
this.deleteCardUseCase = new DeleteCardUseCase(trelloRepository);
|
|
26144
26174
|
this.moveCardUseCase = new MoveCardUseCase(trelloRepository);
|
|
26175
|
+
this.getCardUseCase = new GetCardUseCase(trelloRepository);
|
|
26145
26176
|
}
|
|
26146
26177
|
async createCardInteractive() {
|
|
26147
26178
|
const boards = await this.boardController.getBoards();
|
|
@@ -26425,6 +26456,46 @@ class CardController {
|
|
|
26425
26456
|
console.log(t2("card.updated"));
|
|
26426
26457
|
console.log(t2("card.cardName", { name: updatedCard.name }));
|
|
26427
26458
|
}
|
|
26459
|
+
async showCard(cardId) {
|
|
26460
|
+
const card = await this.getCardUseCase.execute(cardId);
|
|
26461
|
+
const boards = await this.boardController.getBoards();
|
|
26462
|
+
let boardName;
|
|
26463
|
+
let listName;
|
|
26464
|
+
for (const board of boards) {
|
|
26465
|
+
const lists = await this.boardController.getLists(board.id);
|
|
26466
|
+
const list = lists.find((l) => l.id === card.idList);
|
|
26467
|
+
if (list) {
|
|
26468
|
+
boardName = board.name;
|
|
26469
|
+
listName = list.name;
|
|
26470
|
+
break;
|
|
26471
|
+
}
|
|
26472
|
+
}
|
|
26473
|
+
this.outputFormatter.message(t2("card.cardName", { name: card.name }));
|
|
26474
|
+
if (card.desc) {
|
|
26475
|
+
this.outputFormatter.message(t2("card.cardDescription", { description: card.desc }));
|
|
26476
|
+
}
|
|
26477
|
+
this.outputFormatter.message(t2("card.cardUrl", { url: card.url }));
|
|
26478
|
+
this.outputFormatter.message(t2("card.cardId", { id: card.id }));
|
|
26479
|
+
if (boardName && listName) {
|
|
26480
|
+
this.outputFormatter.message(`${t2("board.boardName", { name: boardName })} / ${t2("list.boardLists", { boardName: listName })}`);
|
|
26481
|
+
}
|
|
26482
|
+
if (card.labels && card.labels.length > 0) {
|
|
26483
|
+
this.outputFormatter.message(t2("card.show.labels"));
|
|
26484
|
+
this.outputFormatter.output(card.labels);
|
|
26485
|
+
}
|
|
26486
|
+
if (card.members && card.members.length > 0) {
|
|
26487
|
+
this.outputFormatter.message(t2("card.show.members"));
|
|
26488
|
+
this.outputFormatter.output(card.members);
|
|
26489
|
+
}
|
|
26490
|
+
if (card.checklists && card.checklists.length > 0) {
|
|
26491
|
+
this.outputFormatter.message(t2("card.show.checklists"));
|
|
26492
|
+
this.outputFormatter.output(card.checklists);
|
|
26493
|
+
}
|
|
26494
|
+
if (card.attachments && card.attachments.length > 0) {
|
|
26495
|
+
this.outputFormatter.message(t2("card.show.attachments"));
|
|
26496
|
+
this.outputFormatter.output(card.attachments);
|
|
26497
|
+
}
|
|
26498
|
+
}
|
|
26428
26499
|
async moveCardToList(cardId, targetListId) {
|
|
26429
26500
|
const boards = await this.trelloRepository.getBoards();
|
|
26430
26501
|
let card;
|
|
@@ -26494,15 +26565,23 @@ class CardEntity {
|
|
|
26494
26565
|
idList;
|
|
26495
26566
|
desc;
|
|
26496
26567
|
url;
|
|
26497
|
-
|
|
26568
|
+
labels;
|
|
26569
|
+
members;
|
|
26570
|
+
checklists;
|
|
26571
|
+
attachments;
|
|
26572
|
+
constructor(id, name, idList, desc, url, labels, members, checklists, attachments) {
|
|
26498
26573
|
this.id = id;
|
|
26499
26574
|
this.name = name;
|
|
26500
26575
|
this.idList = idList;
|
|
26501
26576
|
this.desc = desc;
|
|
26502
26577
|
this.url = url;
|
|
26578
|
+
this.labels = labels;
|
|
26579
|
+
this.members = members;
|
|
26580
|
+
this.checklists = checklists;
|
|
26581
|
+
this.attachments = attachments;
|
|
26503
26582
|
}
|
|
26504
26583
|
static fromApiResponse(data) {
|
|
26505
|
-
return new CardEntity(data.id, data.name, data.idList, data.desc, data.url);
|
|
26584
|
+
return new CardEntity(data.id, data.name, data.idList, data.desc, data.url, data.labels, data.members, data.checklists, data.attachments);
|
|
26506
26585
|
}
|
|
26507
26586
|
static create(data) {
|
|
26508
26587
|
return {
|
|
@@ -28688,7 +28767,8 @@ class TrelloApiRepository {
|
|
|
28688
28767
|
this.token = token;
|
|
28689
28768
|
}
|
|
28690
28769
|
async request(endpoint, options) {
|
|
28691
|
-
const
|
|
28770
|
+
const separator = endpoint.includes("?") ? "&" : "?";
|
|
28771
|
+
const url = `${this.baseUrl}${endpoint}${separator}key=${this.apiKey}&token=${this.token}`;
|
|
28692
28772
|
const response = await fetch(url, options);
|
|
28693
28773
|
if (!response.ok) {
|
|
28694
28774
|
const errorText = await response.text();
|
|
@@ -28829,6 +28909,11 @@ ${errorText}`);
|
|
|
28829
28909
|
async moveCard(cardId, targetListId) {
|
|
28830
28910
|
return this.updateCard(cardId, { idList: targetListId });
|
|
28831
28911
|
}
|
|
28912
|
+
async getCard(cardId) {
|
|
28913
|
+
const endpoint = `/cards/${cardId}?checklists=all&members=true&attachments=true`;
|
|
28914
|
+
const data = await this.request(endpoint);
|
|
28915
|
+
return CardEntity.fromApiResponse(data);
|
|
28916
|
+
}
|
|
28832
28917
|
}
|
|
28833
28918
|
var init_TrelloApiRepository = __esm(() => {
|
|
28834
28919
|
init_entities();
|
|
@@ -31138,37 +31223,40 @@ class CommandController {
|
|
|
31138
31223
|
authController;
|
|
31139
31224
|
boardController;
|
|
31140
31225
|
cardController;
|
|
31141
|
-
program
|
|
31226
|
+
program;
|
|
31142
31227
|
outputFormatter;
|
|
31143
31228
|
constructor() {
|
|
31144
31229
|
const configRepository = new FileConfigRepository;
|
|
31145
31230
|
this.authController = new AuthController(configRepository);
|
|
31231
|
+
this.program = new Command;
|
|
31146
31232
|
this.outputFormatter = new OutputFormatter;
|
|
31233
|
+
this.initializeProgram();
|
|
31234
|
+
this.setupCommands();
|
|
31147
31235
|
}
|
|
31148
|
-
|
|
31236
|
+
initializeProgram() {
|
|
31149
31237
|
if (!this.program) {
|
|
31150
31238
|
this.program = new Command;
|
|
31151
31239
|
}
|
|
31152
|
-
return this.program;
|
|
31153
31240
|
}
|
|
31154
31241
|
getVersion() {
|
|
31155
|
-
const cwdPackageJson = join(process.cwd(), "package.json");
|
|
31156
|
-
if (existsSync(cwdPackageJson)) {
|
|
31157
|
-
try {
|
|
31158
|
-
const packageJson = JSON.parse(readFileSync2(cwdPackageJson, "utf-8"));
|
|
31159
|
-
return packageJson.version;
|
|
31160
|
-
} catch {}
|
|
31161
|
-
}
|
|
31162
31242
|
try {
|
|
31163
31243
|
const currentFilePath = fileURLToPath2(import.meta.url);
|
|
31164
31244
|
const currentDir = dirname(currentFilePath);
|
|
31165
|
-
const
|
|
31166
|
-
|
|
31167
|
-
|
|
31168
|
-
|
|
31245
|
+
const possiblePaths = [
|
|
31246
|
+
join(currentDir, "..", "package.json"),
|
|
31247
|
+
join(currentDir, "..", "..", "..", "package.json")
|
|
31248
|
+
];
|
|
31249
|
+
for (const packagePath of possiblePaths) {
|
|
31250
|
+
if (existsSync(packagePath)) {
|
|
31251
|
+
const packageJson = JSON.parse(readFileSync2(packagePath, "utf-8"));
|
|
31252
|
+
if (packageJson.name === "trello-cli-unofficial") {
|
|
31253
|
+
return packageJson.version;
|
|
31254
|
+
}
|
|
31255
|
+
}
|
|
31169
31256
|
}
|
|
31170
31257
|
} catch {}
|
|
31171
|
-
|
|
31258
|
+
console.warn("\u26A0\uFE0F Could not determine trello-cli-unofficial version from package.json");
|
|
31259
|
+
return "0.0.0";
|
|
31172
31260
|
}
|
|
31173
31261
|
async initializeTrelloControllers() {
|
|
31174
31262
|
await this.authController.ensureAuthenticated();
|
|
@@ -31178,9 +31266,12 @@ class CommandController {
|
|
|
31178
31266
|
this.boardController = new BoardController(trelloRepository, this.outputFormatter);
|
|
31179
31267
|
this.cardController = new CardController(trelloRepository, this.boardController, this.outputFormatter);
|
|
31180
31268
|
}
|
|
31181
|
-
|
|
31269
|
+
setupCommands() {
|
|
31270
|
+
if (!this.program) {
|
|
31271
|
+
throw new Error(t2("errors.programNotInitialized"));
|
|
31272
|
+
}
|
|
31182
31273
|
const version = this.getVersion();
|
|
31183
|
-
this.
|
|
31274
|
+
this.program.name("trello-cli-unofficial").description(t2("commands.description")).version(version).option("-f, --format <format>", t2("commands.formatOption"), "table").option("-v", t2("commands.versionOption")).option("--verbose", t2("commands.verboseOption")).on("option:format", (format) => {
|
|
31184
31275
|
this.outputFormatter.setFormat(format);
|
|
31185
31276
|
}).on("option:v", () => {
|
|
31186
31277
|
console.log(version);
|
|
@@ -31188,15 +31279,15 @@ class CommandController {
|
|
|
31188
31279
|
}).on("option:verbose", () => {
|
|
31189
31280
|
process.env.VERBOSE_ERRORS = "true";
|
|
31190
31281
|
});
|
|
31191
|
-
this.
|
|
31282
|
+
this.program.command("interactive").alias("i").description(t2("commands.interactive.description")).action(async () => {
|
|
31192
31283
|
const configRepository = new FileConfigRepository;
|
|
31193
31284
|
const cli = new (await Promise.resolve().then(() => (init_TrelloCliController(), exports_TrelloCliController))).TrelloCliController(configRepository, this.outputFormatter);
|
|
31194
31285
|
await cli.run();
|
|
31195
31286
|
});
|
|
31196
|
-
this.
|
|
31287
|
+
this.program.command("setup").description(t2("commands.setup.description")).action(async () => {
|
|
31197
31288
|
await this.authController.setupToken();
|
|
31198
31289
|
});
|
|
31199
|
-
const boardsCmd = this.
|
|
31290
|
+
const boardsCmd = this.program.command("boards").description(t2("commands.boards.manage"));
|
|
31200
31291
|
boardsCmd.command("list").description(t2("commands.boards.description")).option("-f, --format <format>", t2("commands.formatOption"), "table").action(async (options) => {
|
|
31201
31292
|
try {
|
|
31202
31293
|
await this.initializeTrelloControllers();
|
|
@@ -31205,7 +31296,7 @@ class CommandController {
|
|
|
31205
31296
|
}
|
|
31206
31297
|
await this.boardController.showBoards();
|
|
31207
31298
|
} catch (error) {
|
|
31208
|
-
console.error(t2("commands.
|
|
31299
|
+
console.error(t2("commands.commandErrors.genericError"), error.message);
|
|
31209
31300
|
}
|
|
31210
31301
|
});
|
|
31211
31302
|
boardsCmd.command("show <boardId>").description(t2("commands.boards.show.description")).option("-f, --format <format>", t2("commands.formatOption"), "table").action(async (boardId, options) => {
|
|
@@ -31216,7 +31307,7 @@ class CommandController {
|
|
|
31216
31307
|
}
|
|
31217
31308
|
await this.boardController.showBoardDetails(boardId);
|
|
31218
31309
|
} catch (error) {
|
|
31219
|
-
console.error(t2("commands.
|
|
31310
|
+
console.error(t2("commands.commandErrors.genericError"), error.message);
|
|
31220
31311
|
}
|
|
31221
31312
|
});
|
|
31222
31313
|
boardsCmd.command("create <name>").description(t2("commands.boards.create.description")).option("-d, --desc <description>", t2("commands.boards.create.descOption")).action(async (name, options) => {
|
|
@@ -31227,7 +31318,7 @@ class CommandController {
|
|
|
31227
31318
|
console.error("\u274C Erro:", error.message);
|
|
31228
31319
|
}
|
|
31229
31320
|
});
|
|
31230
|
-
this.
|
|
31321
|
+
this.program.command("boards-legacy").description(t2("commands.deprecated.boardsLegacyDescription")).action(async () => {
|
|
31231
31322
|
console.warn(t2("commands.deprecated.boardsLegacyWarning"));
|
|
31232
31323
|
try {
|
|
31233
31324
|
await this.initializeTrelloControllers();
|
|
@@ -31236,7 +31327,7 @@ class CommandController {
|
|
|
31236
31327
|
console.error(t2("commands.deprecated.boardsLegacyError"), error.message);
|
|
31237
31328
|
}
|
|
31238
31329
|
});
|
|
31239
|
-
const listsCmd = this.
|
|
31330
|
+
const listsCmd = this.program.command("lists").description(t2("commands.lists.description"));
|
|
31240
31331
|
listsCmd.command("list <boardId>").description(t2("commands.lists.list.description")).option("-f, --format <format>", t2("commands.formatOption"), "table").action(async (boardId, options) => {
|
|
31241
31332
|
try {
|
|
31242
31333
|
await this.initializeTrelloControllers();
|
|
@@ -31245,7 +31336,7 @@ class CommandController {
|
|
|
31245
31336
|
}
|
|
31246
31337
|
await this.boardController.showListsById(boardId);
|
|
31247
31338
|
} catch (error) {
|
|
31248
|
-
console.error(t2("commands.
|
|
31339
|
+
console.error(t2("commands.commandErrors.genericError"), error.message);
|
|
31249
31340
|
}
|
|
31250
31341
|
});
|
|
31251
31342
|
listsCmd.command("create <boardId> <name>").description(t2("commands.lists.create.description")).action(async (boardId, name) => {
|
|
@@ -31272,7 +31363,7 @@ class CommandController {
|
|
|
31272
31363
|
console.error(t2("commands.commandErrors.genericError"), error.message);
|
|
31273
31364
|
}
|
|
31274
31365
|
});
|
|
31275
|
-
this.
|
|
31366
|
+
this.program.command("lists-legacy <boardName>").description(t2("commands.deprecated.listsLegacyDescription")).action(async (boardName) => {
|
|
31276
31367
|
console.warn(t2("commands.deprecated.listsLegacyWarning"));
|
|
31277
31368
|
try {
|
|
31278
31369
|
await this.initializeTrelloControllers();
|
|
@@ -31281,7 +31372,7 @@ class CommandController {
|
|
|
31281
31372
|
console.error(t2("commands.deprecated.listsLegacyError"), error.message);
|
|
31282
31373
|
}
|
|
31283
31374
|
});
|
|
31284
|
-
const cardsCmd = this.
|
|
31375
|
+
const cardsCmd = this.program.command("cards").description(t2("commands.cards.manage"));
|
|
31285
31376
|
cardsCmd.command("list <listId>").description(t2("commands.cards.list.description")).option("-f, --format <format>", t2("commands.formatOption"), "table").action(async (listId, options) => {
|
|
31286
31377
|
try {
|
|
31287
31378
|
await this.initializeTrelloControllers();
|
|
@@ -31290,7 +31381,7 @@ class CommandController {
|
|
|
31290
31381
|
}
|
|
31291
31382
|
await this.boardController.showCardsByListId(listId);
|
|
31292
31383
|
} catch (error) {
|
|
31293
|
-
console.error(t2("commands.
|
|
31384
|
+
console.error(t2("commands.commandErrors.genericError"), error.message);
|
|
31294
31385
|
}
|
|
31295
31386
|
});
|
|
31296
31387
|
cardsCmd.command("create <listId> <name>").description(t2("commands.cards.create.description")).option("-d, --desc <description>", t2("commands.options.cardDescription")).action(async (listId, name, options) => {
|
|
@@ -31325,7 +31416,18 @@ class CommandController {
|
|
|
31325
31416
|
console.error(t2("commands.commandErrors.genericError"), error.message);
|
|
31326
31417
|
}
|
|
31327
31418
|
});
|
|
31328
|
-
|
|
31419
|
+
cardsCmd.command("show <cardId>").description(t2("commands.cards.show.description")).option("-f, --format <format>", t2("commands.formatOption"), "table").action(async (cardId, options) => {
|
|
31420
|
+
try {
|
|
31421
|
+
await this.initializeTrelloControllers();
|
|
31422
|
+
if (options.format) {
|
|
31423
|
+
this.outputFormatter.setFormat(options.format);
|
|
31424
|
+
}
|
|
31425
|
+
await this.cardController.showCard(cardId);
|
|
31426
|
+
} catch (error) {
|
|
31427
|
+
console.error(t2("commands.commandErrors.genericError"), error.message);
|
|
31428
|
+
}
|
|
31429
|
+
});
|
|
31430
|
+
this.program.command("cards-legacy <boardName> <listName>").description(t2("commands.deprecated.cardsLegacyDescription")).action(async (boardName, listName) => {
|
|
31329
31431
|
console.warn(t2("commands.deprecated.cardsLegacyWarning"));
|
|
31330
31432
|
try {
|
|
31331
31433
|
await this.initializeTrelloControllers();
|
|
@@ -31334,7 +31436,7 @@ class CommandController {
|
|
|
31334
31436
|
console.error(t2("commands.deprecated.cardsLegacyError"), error.message);
|
|
31335
31437
|
}
|
|
31336
31438
|
});
|
|
31337
|
-
this.
|
|
31439
|
+
this.program.command("create-card-legacy <boardName> <listName> <cardName>").description(t2("commands.deprecated.createCardLegacyDescription")).option("-d, --desc <description>", t2("commands.options.cardDescription")).action(async (boardName, listName, cardName, options) => {
|
|
31338
31440
|
console.warn(t2("commands.deprecated.createCardLegacyWarning"));
|
|
31339
31441
|
try {
|
|
31340
31442
|
await this.initializeTrelloControllers();
|
|
@@ -31343,7 +31445,7 @@ class CommandController {
|
|
|
31343
31445
|
console.error(t2("commands.commandErrors.genericError"), error.message);
|
|
31344
31446
|
}
|
|
31345
31447
|
});
|
|
31346
|
-
this.
|
|
31448
|
+
this.program.command("move-card-legacy <cardId> <listName>").description(t2("commands.deprecated.moveCardLegacyDescription")).action(async (cardId, listName) => {
|
|
31347
31449
|
console.warn(t2("commands.deprecated.moveCardLegacyWarning"));
|
|
31348
31450
|
try {
|
|
31349
31451
|
await this.initializeTrelloControllers();
|
|
@@ -31352,7 +31454,7 @@ class CommandController {
|
|
|
31352
31454
|
console.error(t2("commands.commandErrors.genericError"), error.message);
|
|
31353
31455
|
}
|
|
31354
31456
|
});
|
|
31355
|
-
this.
|
|
31457
|
+
this.program.command("delete-card-legacy <cardId>").description(t2("commands.deprecated.deleteCardLegacyDescription")).action(async (cardId) => {
|
|
31356
31458
|
console.warn(t2("commands.deprecated.deleteCardLegacyWarning"));
|
|
31357
31459
|
try {
|
|
31358
31460
|
await this.initializeTrelloControllers();
|
|
@@ -31363,13 +31465,16 @@ class CommandController {
|
|
|
31363
31465
|
});
|
|
31364
31466
|
}
|
|
31365
31467
|
async run() {
|
|
31366
|
-
|
|
31468
|
+
if (!this.program) {
|
|
31469
|
+
this.initializeProgram();
|
|
31470
|
+
this.setupCommands();
|
|
31471
|
+
}
|
|
31367
31472
|
if (process.argv.length === 2) {
|
|
31368
31473
|
const configRepository = new FileConfigRepository;
|
|
31369
31474
|
const cli = new (await Promise.resolve().then(() => (init_TrelloCliController(), exports_TrelloCliController))).TrelloCliController(configRepository, this.outputFormatter);
|
|
31370
31475
|
await cli.run();
|
|
31371
31476
|
} else {
|
|
31372
|
-
|
|
31477
|
+
this.program.parse();
|
|
31373
31478
|
}
|
|
31374
31479
|
}
|
|
31375
31480
|
}
|
|
Binary file
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "trello-cli-unofficial",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.12.1",
|
|
5
5
|
"private": false,
|
|
6
6
|
"description": "Unofficial Trello CLI using Power-Up authentication, built with Bun for maximum performance",
|
|
7
7
|
"author": "Matheus Caiser <matheus.kaiser@gmail.com> (https://www.mrdeveloper.com.br/)",
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { CardEntity } from '@domain/entities';
|
|
2
|
+
import type { TrelloRepository } from '@domain/repositories';
|
|
3
|
+
|
|
4
|
+
export class GetCardUseCase {
|
|
5
|
+
constructor(private trelloRepository: TrelloRepository) {}
|
|
6
|
+
|
|
7
|
+
async execute(cardId: string): Promise<CardEntity> {
|
|
8
|
+
return await this.trelloRepository.getCard(cardId);
|
|
9
|
+
}
|
|
10
|
+
}
|
|
@@ -6,6 +6,7 @@ export * from './DeleteCardUseCase';
|
|
|
6
6
|
export * from './GetBoardDetailsUseCase';
|
|
7
7
|
export * from './GetBoardsUseCase';
|
|
8
8
|
export * from './GetCardsUseCase';
|
|
9
|
+
export * from './GetCardUseCase';
|
|
9
10
|
export * from './GetListsUseCase';
|
|
10
11
|
export * from './MoveCardUseCase';
|
|
11
12
|
export * from './UpdateCardUseCase';
|
|
@@ -4,6 +4,10 @@ export interface Card {
|
|
|
4
4
|
desc?: string;
|
|
5
5
|
idList: string;
|
|
6
6
|
url?: string;
|
|
7
|
+
labels?: Array<{ id: string; name?: string; color?: string }>;
|
|
8
|
+
members?: Array<{ id: string; username?: string; fullName?: string }>;
|
|
9
|
+
checklists?: Array<Record<string, unknown>>;
|
|
10
|
+
attachments?: Array<Record<string, unknown>>;
|
|
7
11
|
}
|
|
8
12
|
|
|
9
13
|
export interface CreateCardData {
|
|
@@ -26,6 +30,10 @@ interface TrelloCardResponse {
|
|
|
26
30
|
idList: string;
|
|
27
31
|
pos: number;
|
|
28
32
|
url?: string;
|
|
33
|
+
labels?: Array<{ id: string; name?: string; color?: string }>;
|
|
34
|
+
members?: Array<{ id: string; username?: string; fullName?: string }>;
|
|
35
|
+
checklists?: Array<Record<string, unknown>>;
|
|
36
|
+
attachments?: Array<Record<string, unknown>>;
|
|
29
37
|
[key: string]: unknown;
|
|
30
38
|
}
|
|
31
39
|
|
|
@@ -36,10 +44,24 @@ export class CardEntity implements Card {
|
|
|
36
44
|
public readonly idList: string,
|
|
37
45
|
public readonly desc?: string,
|
|
38
46
|
public readonly url?: string,
|
|
47
|
+
public readonly labels?: Array<{ id: string; name?: string; color?: string }>,
|
|
48
|
+
public readonly members?: Array<{ id: string; username?: string; fullName?: string }>,
|
|
49
|
+
public readonly checklists?: Array<Record<string, unknown>>,
|
|
50
|
+
public readonly attachments?: Array<Record<string, unknown>>,
|
|
39
51
|
) {}
|
|
40
52
|
|
|
41
53
|
static fromApiResponse(data: TrelloCardResponse): CardEntity {
|
|
42
|
-
return new CardEntity(
|
|
54
|
+
return new CardEntity(
|
|
55
|
+
data.id,
|
|
56
|
+
data.name,
|
|
57
|
+
data.idList,
|
|
58
|
+
data.desc,
|
|
59
|
+
data.url,
|
|
60
|
+
data.labels,
|
|
61
|
+
data.members,
|
|
62
|
+
data.checklists,
|
|
63
|
+
data.attachments,
|
|
64
|
+
);
|
|
43
65
|
}
|
|
44
66
|
|
|
45
67
|
static create(
|
|
@@ -14,6 +14,7 @@ export interface TrelloRepository {
|
|
|
14
14
|
deleteList: (listId: string) => Promise<void>;
|
|
15
15
|
moveList: (listId: string, position: number) => Promise<ListEntity>;
|
|
16
16
|
getCards: (listId: string) => Promise<CardEntity[]>;
|
|
17
|
+
getCard: (cardId: string) => Promise<CardEntity>;
|
|
17
18
|
createCard: (data: CreateCardData) => Promise<CardEntity>;
|
|
18
19
|
updateCard: (cardId: string, data: UpdateCardData) => Promise<CardEntity>;
|
|
19
20
|
deleteCard: (cardId: string) => Promise<void>;
|
package/src/i18n/locales/en.json
CHANGED
|
@@ -127,6 +127,12 @@
|
|
|
127
127
|
"delete": "🗑️ Delete Card",
|
|
128
128
|
"back": "⬅️ Back",
|
|
129
129
|
"moveCard": "📦 Move card"
|
|
130
|
+
},
|
|
131
|
+
"show": {
|
|
132
|
+
"labels": "🏷️ Labels:",
|
|
133
|
+
"members": "👥 Members:",
|
|
134
|
+
"checklists": "✅ Checklists:",
|
|
135
|
+
"attachments": "📎 Attachments:"
|
|
130
136
|
}
|
|
131
137
|
},
|
|
132
138
|
"errors": {
|
|
@@ -263,6 +269,9 @@
|
|
|
263
269
|
"update": {
|
|
264
270
|
"description": "Update an existing card"
|
|
265
271
|
},
|
|
272
|
+
"show": {
|
|
273
|
+
"description": "Show detailed information about a specific card"
|
|
274
|
+
},
|
|
266
275
|
"delete": {
|
|
267
276
|
"description": "Delete a card"
|
|
268
277
|
}
|
|
@@ -127,6 +127,12 @@
|
|
|
127
127
|
"delete": "🗑️ Deletar Card",
|
|
128
128
|
"back": "⬅️ Voltar",
|
|
129
129
|
"moveCard": "📦 Mover cartão"
|
|
130
|
+
},
|
|
131
|
+
"show": {
|
|
132
|
+
"labels": "🏷️ Labels:",
|
|
133
|
+
"members": "👥 Membros:",
|
|
134
|
+
"checklists": "✅ Checklists:",
|
|
135
|
+
"attachments": "📎 Anexos:"
|
|
130
136
|
}
|
|
131
137
|
},
|
|
132
138
|
"errors": {
|
|
@@ -263,6 +269,9 @@
|
|
|
263
269
|
"update": {
|
|
264
270
|
"description": "Atualiza um card existente"
|
|
265
271
|
},
|
|
272
|
+
"show": {
|
|
273
|
+
"description": "Mostra informações detalhadas sobre um card específico"
|
|
274
|
+
},
|
|
266
275
|
"delete": {
|
|
267
276
|
"description": "Deleta um card"
|
|
268
277
|
}
|
|
@@ -40,7 +40,9 @@ export class TrelloApiRepository implements TrelloRepository {
|
|
|
40
40
|
endpoint: string,
|
|
41
41
|
options?: RequestInit,
|
|
42
42
|
): Promise<unknown> {
|
|
43
|
-
|
|
43
|
+
// If the endpoint already contains query params, add key/token with & otherwise use ?
|
|
44
|
+
const separator = endpoint.includes('?') ? '&' : '?';
|
|
45
|
+
const url = `${this.baseUrl}${endpoint}${separator}key=${this.apiKey}&token=${this.token}`;
|
|
44
46
|
|
|
45
47
|
const response = await fetch(url, options);
|
|
46
48
|
|
|
@@ -235,4 +237,11 @@ export class TrelloApiRepository implements TrelloRepository {
|
|
|
235
237
|
async moveCard(cardId: string, targetListId: string): Promise<CardEntity> {
|
|
236
238
|
return this.updateCard(cardId, { idList: targetListId });
|
|
237
239
|
}
|
|
240
|
+
|
|
241
|
+
async getCard(cardId: string): Promise<CardEntity> {
|
|
242
|
+
// Request the card with details: members, checklists and attachments
|
|
243
|
+
const endpoint = `/cards/${cardId}?checklists=all&members=true&attachments=true`;
|
|
244
|
+
const data = await this.request(endpoint);
|
|
245
|
+
return CardEntity.fromApiResponse(data as TrelloCardResponse);
|
|
246
|
+
}
|
|
238
247
|
}
|
|
@@ -6,6 +6,7 @@ import type { OutputFormatter } from '@/shared';
|
|
|
6
6
|
import {
|
|
7
7
|
CreateCardUseCase,
|
|
8
8
|
DeleteCardUseCase,
|
|
9
|
+
GetCardUseCase,
|
|
9
10
|
MoveCardUseCase,
|
|
10
11
|
UpdateCardUseCase,
|
|
11
12
|
} from '@application/use-cases';
|
|
@@ -19,6 +20,7 @@ export class CardController {
|
|
|
19
20
|
private updateCardUseCase: UpdateCardUseCase;
|
|
20
21
|
private deleteCardUseCase: DeleteCardUseCase;
|
|
21
22
|
private moveCardUseCase: MoveCardUseCase;
|
|
23
|
+
private getCardUseCase: GetCardUseCase;
|
|
22
24
|
|
|
23
25
|
constructor(
|
|
24
26
|
private trelloRepository: TrelloRepository,
|
|
@@ -29,6 +31,7 @@ export class CardController {
|
|
|
29
31
|
this.updateCardUseCase = new UpdateCardUseCase(trelloRepository);
|
|
30
32
|
this.deleteCardUseCase = new DeleteCardUseCase(trelloRepository);
|
|
31
33
|
this.moveCardUseCase = new MoveCardUseCase(trelloRepository);
|
|
34
|
+
this.getCardUseCase = new GetCardUseCase(trelloRepository);
|
|
32
35
|
}
|
|
33
36
|
|
|
34
37
|
async createCardInteractive(): Promise<void> {
|
|
@@ -405,6 +408,56 @@ export class CardController {
|
|
|
405
408
|
console.log(t('card.cardName', { name: updatedCard.name }));
|
|
406
409
|
}
|
|
407
410
|
|
|
411
|
+
async showCard(cardId: string): Promise<void> {
|
|
412
|
+
// Get detailed card from the repository
|
|
413
|
+
const card = await this.getCardUseCase.execute(cardId);
|
|
414
|
+
|
|
415
|
+
// Try to find board and list names
|
|
416
|
+
const boards = await this.boardController.getBoards();
|
|
417
|
+
let boardName: string | undefined;
|
|
418
|
+
let listName: string | undefined;
|
|
419
|
+
for (const board of boards) {
|
|
420
|
+
const lists = await this.boardController.getLists(board.id);
|
|
421
|
+
const list = lists.find(l => l.id === card.idList);
|
|
422
|
+
if (list) {
|
|
423
|
+
boardName = board.name;
|
|
424
|
+
listName = list.name;
|
|
425
|
+
break;
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
this.outputFormatter.message(t('card.cardName', { name: card.name }));
|
|
430
|
+
if (card.desc) {
|
|
431
|
+
this.outputFormatter.message(t('card.cardDescription', { description: card.desc }));
|
|
432
|
+
}
|
|
433
|
+
this.outputFormatter.message(t('card.cardUrl', { url: card.url }));
|
|
434
|
+
this.outputFormatter.message(t('card.cardId', { id: card.id }));
|
|
435
|
+
if (boardName && listName) {
|
|
436
|
+
this.outputFormatter.message(`${t('board.boardName', { name: boardName })} / ${t('list.boardLists', { boardName: listName })}`);
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
// Show labels, members and checklists if present
|
|
440
|
+
if (card.labels && card.labels.length > 0) {
|
|
441
|
+
this.outputFormatter.message(t('card.show.labels'));
|
|
442
|
+
this.outputFormatter.output(card.labels);
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
if (card.members && card.members.length > 0) {
|
|
446
|
+
this.outputFormatter.message(t('card.show.members'));
|
|
447
|
+
this.outputFormatter.output(card.members);
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
if (card.checklists && card.checklists.length > 0) {
|
|
451
|
+
this.outputFormatter.message(t('card.show.checklists'));
|
|
452
|
+
this.outputFormatter.output(card.checklists);
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
if (card.attachments && card.attachments.length > 0) {
|
|
456
|
+
this.outputFormatter.message(t('card.show.attachments'));
|
|
457
|
+
this.outputFormatter.output(card.attachments);
|
|
458
|
+
}
|
|
459
|
+
}
|
|
460
|
+
|
|
408
461
|
async moveCardToList(cardId: string, targetListId: string): Promise<void> {
|
|
409
462
|
// Primeiro precisamos encontrar o cartão para mostrar informações
|
|
410
463
|
const boards = await this.trelloRepository.getBoards();
|
|
@@ -8,63 +8,72 @@ import {
|
|
|
8
8
|
FileConfigRepository,
|
|
9
9
|
TrelloApiRepository,
|
|
10
10
|
} from '@infrastructure/repositories';
|
|
11
|
-
|
|
12
11
|
import { Command } from 'commander';
|
|
12
|
+
|
|
13
13
|
import { t } from '@/i18n';
|
|
14
14
|
import { OutputFormatter } from '@/shared';
|
|
15
|
-
|
|
16
15
|
import { AuthController, BoardController, CardController } from './index';
|
|
17
16
|
|
|
18
17
|
export class CommandController {
|
|
19
18
|
private authController: AuthController;
|
|
20
19
|
private boardController!: BoardController;
|
|
21
20
|
private cardController!: CardController;
|
|
22
|
-
private program: Command
|
|
21
|
+
private program: Command;
|
|
23
22
|
private outputFormatter: OutputFormatter;
|
|
24
23
|
|
|
25
24
|
constructor() {
|
|
26
25
|
const configRepository = new FileConfigRepository();
|
|
27
26
|
this.authController = new AuthController(configRepository);
|
|
27
|
+
this.program = new Command();
|
|
28
28
|
this.outputFormatter = new OutputFormatter();
|
|
29
|
+
this.initializeProgram();
|
|
30
|
+
this.setupCommands();
|
|
29
31
|
}
|
|
30
32
|
|
|
31
|
-
private
|
|
33
|
+
private initializeProgram(): void {
|
|
34
|
+
// Ensure program is properly initialized
|
|
32
35
|
if (!this.program) {
|
|
33
36
|
this.program = new Command();
|
|
34
37
|
}
|
|
35
|
-
return this.program;
|
|
36
38
|
}
|
|
37
39
|
|
|
38
40
|
private getVersion(): string {
|
|
39
|
-
//
|
|
40
|
-
|
|
41
|
-
// 1. Try relative to current working directory (development)
|
|
42
|
-
const cwdPackageJson = join(process.cwd(), 'package.json');
|
|
43
|
-
if (existsSync(cwdPackageJson)) {
|
|
44
|
-
try {
|
|
45
|
-
const packageJson = JSON.parse(readFileSync(cwdPackageJson, 'utf-8'));
|
|
46
|
-
return packageJson.version;
|
|
47
|
-
} catch {
|
|
48
|
-
// Continue to next approach
|
|
49
|
-
}
|
|
50
|
-
}
|
|
41
|
+
// CRITICAL: Always get version from the CLI's package.json, not from user's cwd
|
|
42
|
+
// This prevents showing wrong version when running inside other Node projects
|
|
51
43
|
|
|
52
|
-
//
|
|
44
|
+
// Try relative to this file's directory (when installed globally or locally)
|
|
53
45
|
try {
|
|
54
46
|
const currentFilePath = fileURLToPath(import.meta.url);
|
|
55
47
|
const currentDir = dirname(currentFilePath);
|
|
56
|
-
const installedPackageJson = join(currentDir, '..', '..', 'package.json');
|
|
57
48
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
49
|
+
// When bundled, dist/main.js is at root level, package.json is one level up
|
|
50
|
+
// When unbundled, we're in src/presentation/cli, package.json is three levels up
|
|
51
|
+
const possiblePaths = [
|
|
52
|
+
join(currentDir, '..', 'package.json'), // dist/main.js -> package.json
|
|
53
|
+
join(currentDir, '..', '..', '..', 'package.json'), // src/presentation/cli -> package.json
|
|
54
|
+
];
|
|
55
|
+
|
|
56
|
+
for (const packagePath of possiblePaths) {
|
|
57
|
+
if (existsSync(packagePath)) {
|
|
58
|
+
const packageJson = JSON.parse(readFileSync(packagePath, 'utf-8'));
|
|
59
|
+
|
|
60
|
+
// Verify it's the right package.json by checking the name
|
|
61
|
+
if (packageJson.name === 'trello-cli-unofficial') {
|
|
62
|
+
return packageJson.version;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
61
65
|
}
|
|
62
|
-
}
|
|
66
|
+
}
|
|
67
|
+
catch {
|
|
63
68
|
// Continue to fallback
|
|
64
69
|
}
|
|
65
70
|
|
|
66
|
-
//
|
|
67
|
-
|
|
71
|
+
// Could not determine package version from installed CLI package.json.
|
|
72
|
+
// Remove hardcoded fallback to avoid showing incorrect versions when
|
|
73
|
+
// the CLI is executed inside other Node projects. Return a neutral
|
|
74
|
+
// unknown version string so callers can handle it explicitly.
|
|
75
|
+
console.warn('⚠️ Could not determine trello-cli-unofficial version from package.json');
|
|
76
|
+
return '0.0.0';
|
|
68
77
|
}
|
|
69
78
|
|
|
70
79
|
private async initializeTrelloControllers(): Promise<void> {
|
|
@@ -88,11 +97,16 @@ export class CommandController {
|
|
|
88
97
|
);
|
|
89
98
|
}
|
|
90
99
|
|
|
91
|
-
private
|
|
100
|
+
private setupCommands(): void {
|
|
101
|
+
// Ensure program is initialized
|
|
102
|
+
if (!this.program) {
|
|
103
|
+
throw new Error(t('errors.programNotInitialized'));
|
|
104
|
+
}
|
|
105
|
+
|
|
92
106
|
// Get version using robust method
|
|
93
107
|
const version = this.getVersion();
|
|
94
108
|
|
|
95
|
-
this.
|
|
109
|
+
this.program
|
|
96
110
|
.name('trello-cli-unofficial')
|
|
97
111
|
.description(t('commands.description'))
|
|
98
112
|
.version(version)
|
|
@@ -112,7 +126,7 @@ export class CommandController {
|
|
|
112
126
|
});
|
|
113
127
|
|
|
114
128
|
// Interactive mode
|
|
115
|
-
this.
|
|
129
|
+
this.program
|
|
116
130
|
.command('interactive')
|
|
117
131
|
.alias('i')
|
|
118
132
|
.description(t('commands.interactive.description'))
|
|
@@ -125,7 +139,7 @@ export class CommandController {
|
|
|
125
139
|
});
|
|
126
140
|
|
|
127
141
|
// Setup command
|
|
128
|
-
this.
|
|
142
|
+
this.program
|
|
129
143
|
.command('setup')
|
|
130
144
|
.description(t('commands.setup.description'))
|
|
131
145
|
.action(async () => {
|
|
@@ -133,7 +147,7 @@ export class CommandController {
|
|
|
133
147
|
});
|
|
134
148
|
|
|
135
149
|
// Boards subcommands
|
|
136
|
-
const boardsCmd = this.
|
|
150
|
+
const boardsCmd = this.program
|
|
137
151
|
.command('boards')
|
|
138
152
|
.description(t('commands.boards.manage'));
|
|
139
153
|
|
|
@@ -149,7 +163,10 @@ export class CommandController {
|
|
|
149
163
|
}
|
|
150
164
|
await this.boardController.showBoards();
|
|
151
165
|
} catch (error) {
|
|
152
|
-
console.error(
|
|
166
|
+
console.error(
|
|
167
|
+
t('commands.commandErrors.genericError'),
|
|
168
|
+
(error as Error).message,
|
|
169
|
+
);
|
|
153
170
|
}
|
|
154
171
|
});
|
|
155
172
|
|
|
@@ -165,7 +182,7 @@ export class CommandController {
|
|
|
165
182
|
}
|
|
166
183
|
await this.boardController.showBoardDetails(boardId);
|
|
167
184
|
} catch (error) {
|
|
168
|
-
console.error(t('commands.
|
|
185
|
+
console.error(t('commands.commandErrors.genericError'), (error as Error).message);
|
|
169
186
|
}
|
|
170
187
|
});
|
|
171
188
|
|
|
@@ -186,7 +203,7 @@ export class CommandController {
|
|
|
186
203
|
});
|
|
187
204
|
|
|
188
205
|
// Legacy boards command with deprecation warning
|
|
189
|
-
this.
|
|
206
|
+
this.program
|
|
190
207
|
.command('boards-legacy')
|
|
191
208
|
.description(t('commands.deprecated.boardsLegacyDescription'))
|
|
192
209
|
.action(async () => {
|
|
@@ -203,7 +220,7 @@ export class CommandController {
|
|
|
203
220
|
});
|
|
204
221
|
|
|
205
222
|
// Lists subcommands
|
|
206
|
-
const listsCmd = this.
|
|
223
|
+
const listsCmd = this.program
|
|
207
224
|
.command('lists')
|
|
208
225
|
.description(t('commands.lists.description'));
|
|
209
226
|
|
|
@@ -219,7 +236,7 @@ export class CommandController {
|
|
|
219
236
|
}
|
|
220
237
|
await this.boardController.showListsById(boardId);
|
|
221
238
|
} catch (error) {
|
|
222
|
-
console.error(t('commands.
|
|
239
|
+
console.error(t('commands.commandErrors.genericError'), (error as Error).message);
|
|
223
240
|
}
|
|
224
241
|
});
|
|
225
242
|
|
|
@@ -272,7 +289,7 @@ export class CommandController {
|
|
|
272
289
|
});
|
|
273
290
|
|
|
274
291
|
// Legacy lists command with deprecation warning
|
|
275
|
-
this.
|
|
292
|
+
this.program
|
|
276
293
|
.command('lists-legacy <boardName>')
|
|
277
294
|
.description(t('commands.deprecated.listsLegacyDescription'))
|
|
278
295
|
.action(async (boardName: string) => {
|
|
@@ -289,7 +306,7 @@ export class CommandController {
|
|
|
289
306
|
});
|
|
290
307
|
|
|
291
308
|
// Cards subcommands
|
|
292
|
-
const cardsCmd = this.
|
|
309
|
+
const cardsCmd = this.program
|
|
293
310
|
.command('cards')
|
|
294
311
|
.description(t('commands.cards.manage'));
|
|
295
312
|
|
|
@@ -305,7 +322,7 @@ export class CommandController {
|
|
|
305
322
|
}
|
|
306
323
|
await this.boardController.showCardsByListId(listId);
|
|
307
324
|
} catch (error) {
|
|
308
|
-
console.error(t('commands.
|
|
325
|
+
console.error(t('commands.commandErrors.genericError'), (error as Error).message);
|
|
309
326
|
}
|
|
310
327
|
});
|
|
311
328
|
|
|
@@ -388,8 +405,27 @@ export class CommandController {
|
|
|
388
405
|
},
|
|
389
406
|
);
|
|
390
407
|
|
|
408
|
+
cardsCmd
|
|
409
|
+
.command('show <cardId>')
|
|
410
|
+
.description(t('commands.cards.show.description'))
|
|
411
|
+
.option('-f, --format <format>', t('commands.formatOption'), 'table')
|
|
412
|
+
.action(async (cardId: string, options: { format?: string }) => {
|
|
413
|
+
try {
|
|
414
|
+
await this.initializeTrelloControllers();
|
|
415
|
+
if (options.format) {
|
|
416
|
+
this.outputFormatter.setFormat(options.format as OutputFormat);
|
|
417
|
+
}
|
|
418
|
+
await this.cardController.showCard(cardId);
|
|
419
|
+
} catch (error) {
|
|
420
|
+
console.error(
|
|
421
|
+
t('commands.commandErrors.genericError'),
|
|
422
|
+
(error as Error).message,
|
|
423
|
+
);
|
|
424
|
+
}
|
|
425
|
+
});
|
|
426
|
+
|
|
391
427
|
// Legacy commands with deprecation warnings
|
|
392
|
-
this.
|
|
428
|
+
this.program
|
|
393
429
|
.command('cards-legacy <boardName> <listName>')
|
|
394
430
|
.description(t('commands.deprecated.cardsLegacyDescription'))
|
|
395
431
|
.action(async (boardName: string, listName: string) => {
|
|
@@ -405,7 +441,7 @@ export class CommandController {
|
|
|
405
441
|
}
|
|
406
442
|
});
|
|
407
443
|
|
|
408
|
-
this.
|
|
444
|
+
this.program
|
|
409
445
|
.command('create-card-legacy <boardName> <listName> <cardName>')
|
|
410
446
|
.description(t('commands.deprecated.createCardLegacyDescription'))
|
|
411
447
|
.option('-d, --desc <description>', t('commands.options.cardDescription'))
|
|
@@ -434,7 +470,7 @@ export class CommandController {
|
|
|
434
470
|
},
|
|
435
471
|
);
|
|
436
472
|
|
|
437
|
-
this.
|
|
473
|
+
this.program
|
|
438
474
|
.command('move-card-legacy <cardId> <listName>')
|
|
439
475
|
.description(t('commands.deprecated.moveCardLegacyDescription'))
|
|
440
476
|
.action(async (cardId: string, listName: string) => {
|
|
@@ -450,7 +486,7 @@ export class CommandController {
|
|
|
450
486
|
}
|
|
451
487
|
});
|
|
452
488
|
|
|
453
|
-
this.
|
|
489
|
+
this.program
|
|
454
490
|
.command('delete-card-legacy <cardId>')
|
|
455
491
|
.description(t('commands.deprecated.deleteCardLegacyDescription'))
|
|
456
492
|
.action(async (cardId: string) => {
|
|
@@ -468,7 +504,11 @@ export class CommandController {
|
|
|
468
504
|
}
|
|
469
505
|
|
|
470
506
|
async run(): Promise<void> {
|
|
471
|
-
|
|
507
|
+
// Ensure program is initialized before parsing
|
|
508
|
+
if (!this.program) {
|
|
509
|
+
this.initializeProgram();
|
|
510
|
+
this.setupCommands();
|
|
511
|
+
}
|
|
472
512
|
|
|
473
513
|
// Fallback to interactive mode if no command specified
|
|
474
514
|
if (process.argv.length === 2) {
|
|
@@ -478,7 +518,7 @@ export class CommandController {
|
|
|
478
518
|
).TrelloCliController(configRepository, this.outputFormatter);
|
|
479
519
|
await cli.run();
|
|
480
520
|
} else {
|
|
481
|
-
|
|
521
|
+
this.program.parse();
|
|
482
522
|
}
|
|
483
523
|
}
|
|
484
524
|
}
|
|
Binary file
|