import type { Command } from "commander"; import { attachmentForm } from "../../util/attachment.ts"; import { getClient, parseJsonFlag, parseKvPairs } from "../context.ts"; import { rootOpts, run } from "./run.ts"; export function registerCardCommands(program: Command): void { const cards = program.command("cards").description("Card operations"); cards .command("get ") .option("--fields ", "Comma-separated fields") .action((id, opts, cmd) => run(cmd, async () => { const { client } = getClient(rootOpts(cmd).profile); return client.cardGet(id, { fields: opts.fields }); }), ); cards .command("list") .description("List cards on a list") .requiredOption("--list ", "List id") .action((opts, cmd) => run(cmd, async () => { const { client } = getClient(rootOpts(cmd).profile); return client.listCards(opts.list); }), ); cards .command("create") .requiredOption("--list ", "Target list") .requiredOption("--name ", "Card name") .option("--desc ", "Description") .option("--due ", "Due date ISO8601") .option("--pos ", "Position") .option("--params ", "Extra key=value params") .action((opts, cmd) => run(cmd, async () => { const { client } = getClient(rootOpts(cmd).profile); return client.cardCreate({ idList: opts.list, name: opts.name, desc: opts.desc, due: opts.due, pos: opts.pos, ...parseKvPairs(opts.params), }); }), ); cards .command("update ") .option("--params ", "key=value params") .option("--json ", "JSON body") .action((id, opts, cmd) => run(cmd, async () => { const { client } = getClient(rootOpts(cmd).profile); return client.cardUpdate(id, { ...parseKvPairs(opts.params), ...(parseJsonFlag(opts.json, "--json") as object), }); }), ); cards .command("move ") .description("Move card to another list") .requiredOption("--list ", "Destination list") .option("--pos ", "Position") .action((id, opts, cmd) => run(cmd, async () => { const { client } = getClient(rootOpts(cmd).profile); return client.cardUpdate(id, { idList: opts.list, pos: opts.pos }); }), ); cards .command("comments ") .description("List comments on a card") .option("--limit ", "Max comments", "50") .action((id, opts, cmd) => run(cmd, async () => { const { client } = getClient(rootOpts(cmd).profile); return client.cardComments(id, { limit: opts.limit }); }), ); cards .command("comment ") .requiredOption("--text ", "Comment body") .action((id, opts, cmd) => run(cmd, async () => { const { client } = getClient(rootOpts(cmd).profile); return client.cardComment(id, opts.text); }), ); cards .command("edit-comment ") .description("Edit a comment on a card") .requiredOption("--text ", "New comment body") .action((id, commentId, opts, cmd) => run(cmd, async () => { const { client } = getClient(rootOpts(cmd).profile); return client.cardEditComment(id, commentId, opts.text); }), ); cards .command("delete-comment ") .description("Permanently delete a comment — irreversible") .action((id, commentId, _opts, cmd) => run(cmd, async () => { const { client } = getClient(rootOpts(cmd).profile); return client.cardDeleteComment(id, commentId); }), ); cards .command("archive ") .description("Close (archive) a card — reversible in Trello UI") .action((id, _opts, cmd) => run(cmd, async () => { const { client } = getClient(rootOpts(cmd).profile); return client.cardArchive(id); }), ); cards .command("delete ") .description("Permanently delete a card — irreversible") .action((id, _opts, cmd) => run(cmd, async () => { const { client } = getClient(rootOpts(cmd).profile); return client.cardDelete(id); }), ); cards.command("members ").action((id, _opts, cmd) => run(cmd, async () => { const { client } = getClient(rootOpts(cmd).profile); return client.cardMembers(id); }), ); cards.command("add-member ").action((id, memberId, _opts, cmd) => run(cmd, async () => { const { client } = getClient(rootOpts(cmd).profile); return client.cardAddMember(id, memberId); }), ); cards.command("remove-member ").action((id, memberId, _opts, cmd) => run(cmd, async () => { const { client } = getClient(rootOpts(cmd).profile); return client.cardRemoveMember(id, memberId); }), ); cards.command("labels ").action((id, _opts, cmd) => run(cmd, async () => { const { client } = getClient(rootOpts(cmd).profile); return client.cardLabels(id); }), ); cards.command("add-label ").action((id, labelId, _opts, cmd) => run(cmd, async () => { const { client } = getClient(rootOpts(cmd).profile); return client.cardAddLabel(id, labelId); }), ); cards.command("remove-label ").action((id, labelId, _opts, cmd) => run(cmd, async () => { const { client } = getClient(rootOpts(cmd).profile); return client.cardRemoveLabel(id, labelId); }), ); cards .command("actions ") .option("--limit ", "Max actions", "50") .action((id, opts, cmd) => run(cmd, async () => { const { client } = getClient(rootOpts(cmd).profile); return client.cardActions(id, { limit: opts.limit }); }), ); cards.command("attachments ").action((id, _opts, cmd) => run(cmd, async () => { const { client } = getClient(rootOpts(cmd).profile); return client.cardAttachments(id); }), ); cards .command("add-attachment ") .option("--url ", "Attachment URL") .option("--file ", "Local file to upload") .option("--name ", "Attachment name") .action((id, opts, cmd) => run(cmd, async () => { const { client } = getClient(rootOpts(cmd).profile); if (!opts.url === !opts.file) { throw new Error("Pass exactly one of --url or --file"); } if (opts.file) { return client.cardUploadAttachment(id, attachmentForm(opts.file, opts.name)); } return client.cardAddAttachment(id, { url: opts.url, name: opts.name }); }), ); cards .command("delete-attachment ") .description("Delete an attachment from a card") .action((id, attachmentId, _opts, cmd) => run(cmd, async () => { const { client } = getClient(rootOpts(cmd).profile); return client.cardDeleteAttachment(id, attachmentId); }), ); cards.command("custom-fields ").action((id, _opts, cmd) => run(cmd, async () => { const { client } = getClient(rootOpts(cmd).profile); return client.cardCustomFieldItems(id); }), ); }