@hasna/connectors 0.3.16 → 0.4.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/bin/index.js +71 -1
- package/bin/mcp.js +71 -1
- package/bin/serve.js +70 -0
- package/connectors/connect-asana/.env.example +11 -0
- package/connectors/connect-asana/CLAUDE.md +128 -0
- package/connectors/connect-asana/README.md +193 -0
- package/connectors/connect-asana/package.json +52 -0
- package/connectors/connect-asana/src/api/client.ts +119 -0
- package/connectors/connect-asana/src/api/index.ts +319 -0
- package/connectors/connect-asana/src/cli/index.ts +731 -0
- package/connectors/connect-asana/src/index.ts +19 -0
- package/connectors/connect-asana/src/types/index.ts +270 -0
- package/connectors/connect-asana/src/utils/config.ts +171 -0
- package/connectors/connect-asana/src/utils/output.ts +119 -0
- package/connectors/connect-asana/tsconfig.json +16 -0
- package/connectors/connect-clickup/.env.example +11 -0
- package/connectors/connect-clickup/CLAUDE.md +128 -0
- package/connectors/connect-clickup/README.md +193 -0
- package/connectors/connect-clickup/package.json +52 -0
- package/connectors/connect-clickup/src/api/client.ts +116 -0
- package/connectors/connect-clickup/src/api/index.ts +400 -0
- package/connectors/connect-clickup/src/cli/index.ts +625 -0
- package/connectors/connect-clickup/src/index.ts +19 -0
- package/connectors/connect-clickup/src/types/index.ts +591 -0
- package/connectors/connect-clickup/src/utils/config.ts +157 -0
- package/connectors/connect-clickup/src/utils/output.ts +119 -0
- package/connectors/connect-clickup/tsconfig.json +16 -0
- package/connectors/connect-confluence/.env.example +11 -0
- package/connectors/connect-confluence/CLAUDE.md +272 -0
- package/connectors/connect-confluence/README.md +193 -0
- package/connectors/connect-confluence/package.json +53 -0
- package/connectors/connect-confluence/scripts/release.ts +179 -0
- package/connectors/connect-confluence/src/api/client.ts +213 -0
- package/connectors/connect-confluence/src/api/example.ts +48 -0
- package/connectors/connect-confluence/src/api/index.ts +51 -0
- package/connectors/connect-confluence/src/cli/index.ts +254 -0
- package/connectors/connect-confluence/src/index.ts +103 -0
- package/connectors/connect-confluence/src/types/index.ts +237 -0
- package/connectors/connect-confluence/src/utils/auth.ts +274 -0
- package/connectors/connect-confluence/src/utils/bulk.ts +212 -0
- package/connectors/connect-confluence/src/utils/config.ts +326 -0
- package/connectors/connect-confluence/src/utils/output.ts +175 -0
- package/connectors/connect-confluence/src/utils/settings.ts +114 -0
- package/connectors/connect-confluence/src/utils/storage.ts +198 -0
- package/connectors/connect-confluence/tsconfig.json +16 -0
- package/connectors/connect-jira/.env.example +11 -0
- package/connectors/connect-jira/CLAUDE.md +128 -0
- package/connectors/connect-jira/README.md +193 -0
- package/connectors/connect-jira/package.json +53 -0
- package/connectors/connect-jira/src/api/client.ts +131 -0
- package/connectors/connect-jira/src/api/index.ts +266 -0
- package/connectors/connect-jira/src/cli/index.ts +653 -0
- package/connectors/connect-jira/src/index.ts +23 -0
- package/connectors/connect-jira/src/types/index.ts +448 -0
- package/connectors/connect-jira/src/utils/config.ts +179 -0
- package/connectors/connect-jira/src/utils/output.ts +119 -0
- package/connectors/connect-jira/tsconfig.json +16 -0
- package/connectors/connect-linear/CLAUDE.md +88 -0
- package/connectors/connect-linear/README.md +201 -0
- package/connectors/connect-linear/package.json +45 -0
- package/connectors/connect-linear/src/api/client.ts +62 -0
- package/connectors/connect-linear/src/api/index.ts +46 -0
- package/connectors/connect-linear/src/api/issues.ts +247 -0
- package/connectors/connect-linear/src/api/projects.ts +179 -0
- package/connectors/connect-linear/src/api/teams.ts +125 -0
- package/connectors/connect-linear/src/api/users.ts +112 -0
- package/connectors/connect-linear/src/cli/index.ts +560 -0
- package/connectors/connect-linear/src/index.ts +27 -0
- package/connectors/connect-linear/src/types/index.ts +275 -0
- package/connectors/connect-linear/src/utils/config.ts +249 -0
- package/connectors/connect-linear/src/utils/output.ts +119 -0
- package/connectors/connect-linear/tsconfig.json +16 -0
- package/connectors/connect-slack/.env.example +7 -0
- package/connectors/connect-slack/CLAUDE.md +69 -0
- package/connectors/connect-slack/README.md +150 -0
- package/connectors/connect-slack/package.json +44 -0
- package/connectors/connect-slack/src/api/channels.ts +112 -0
- package/connectors/connect-slack/src/api/client.ts +97 -0
- package/connectors/connect-slack/src/api/index.ts +42 -0
- package/connectors/connect-slack/src/api/messages.ts +127 -0
- package/connectors/connect-slack/src/api/users.ts +110 -0
- package/connectors/connect-slack/src/cli/index.ts +494 -0
- package/connectors/connect-slack/src/index.ts +21 -0
- package/connectors/connect-slack/src/types/index.ts +263 -0
- package/connectors/connect-slack/src/utils/config.ts +297 -0
- package/connectors/connect-slack/src/utils/output.ts +119 -0
- package/connectors/connect-slack/tsconfig.json +16 -0
- package/connectors/connect-telegram/.env.example +2 -0
- package/connectors/connect-telegram/package.json +49 -0
- package/connectors/connect-todoist/.env.example +11 -0
- package/connectors/connect-todoist/CLAUDE.md +104 -0
- package/connectors/connect-todoist/README.md +193 -0
- package/connectors/connect-todoist/package.json +52 -0
- package/connectors/connect-todoist/src/api/client.ts +117 -0
- package/connectors/connect-todoist/src/api/index.ts +188 -0
- package/connectors/connect-todoist/src/cli/index.ts +990 -0
- package/connectors/connect-todoist/src/index.ts +21 -0
- package/connectors/connect-todoist/src/types/index.ts +240 -0
- package/connectors/connect-todoist/src/utils/config.ts +157 -0
- package/connectors/connect-todoist/src/utils/output.ts +119 -0
- package/connectors/connect-todoist/tsconfig.json +16 -0
- package/connectors/connect-trello/.env.example +11 -0
- package/connectors/connect-trello/CLAUDE.md +128 -0
- package/connectors/connect-trello/README.md +193 -0
- package/connectors/connect-trello/package.json +53 -0
- package/connectors/connect-trello/src/api/client.ts +128 -0
- package/connectors/connect-trello/src/api/index.ts +278 -0
- package/connectors/connect-trello/src/cli/index.ts +737 -0
- package/connectors/connect-trello/src/index.ts +21 -0
- package/connectors/connect-trello/src/types/index.ts +314 -0
- package/connectors/connect-trello/src/utils/config.ts +182 -0
- package/connectors/connect-trello/src/utils/output.ts +119 -0
- package/connectors/connect-trello/tsconfig.json +16 -0
- package/connectors/connect-whatsapp/.env.example +11 -0
- package/connectors/connect-whatsapp/CLAUDE.md +113 -0
- package/connectors/connect-whatsapp/README.md +193 -0
- package/connectors/connect-whatsapp/package.json +53 -0
- package/connectors/connect-whatsapp/src/api/client.ts +133 -0
- package/connectors/connect-whatsapp/src/api/index.ts +365 -0
- package/connectors/connect-whatsapp/src/cli/index.ts +686 -0
- package/connectors/connect-whatsapp/src/index.ts +25 -0
- package/connectors/connect-whatsapp/src/types/index.ts +502 -0
- package/connectors/connect-whatsapp/src/utils/config.ts +179 -0
- package/connectors/connect-whatsapp/src/utils/output.ts +119 -0
- package/connectors/connect-whatsapp/tsconfig.json +16 -0
- package/dist/index.js +70 -0
- package/package.json +1 -1
|
@@ -0,0 +1,737 @@
|
|
|
1
|
+
#!/usr/bin/env bun
|
|
2
|
+
import { Command } from 'commander';
|
|
3
|
+
import chalk from 'chalk';
|
|
4
|
+
import { Trello } from '../api';
|
|
5
|
+
import {
|
|
6
|
+
getApiKey,
|
|
7
|
+
setApiKey,
|
|
8
|
+
getToken,
|
|
9
|
+
setToken,
|
|
10
|
+
clearConfig,
|
|
11
|
+
getConfigDir,
|
|
12
|
+
setProfileOverride,
|
|
13
|
+
getCurrentProfile,
|
|
14
|
+
setCurrentProfile,
|
|
15
|
+
listProfiles,
|
|
16
|
+
createProfile,
|
|
17
|
+
deleteProfile,
|
|
18
|
+
profileExists,
|
|
19
|
+
loadProfile,
|
|
20
|
+
} from '../utils/config';
|
|
21
|
+
import type { OutputFormat } from '../utils/output';
|
|
22
|
+
import { success, error, info, print, warn } from '../utils/output';
|
|
23
|
+
|
|
24
|
+
const CONNECTOR_NAME = 'connect-trello';
|
|
25
|
+
const VERSION = '0.0.1';
|
|
26
|
+
|
|
27
|
+
const program = new Command();
|
|
28
|
+
|
|
29
|
+
program
|
|
30
|
+
.name(CONNECTOR_NAME)
|
|
31
|
+
.description('Trello connector - Boards, lists, cards, and checklists management')
|
|
32
|
+
.version(VERSION)
|
|
33
|
+
.option('-k, --api-key <key>', 'API key (overrides config)')
|
|
34
|
+
.option('-t, --token <token>', 'Token (overrides config)')
|
|
35
|
+
.option('-f, --format <format>', 'Output format (json, pretty)', 'pretty')
|
|
36
|
+
.option('-p, --profile <profile>', 'Use a specific profile')
|
|
37
|
+
.hook('preAction', (thisCommand) => {
|
|
38
|
+
const opts = thisCommand.opts();
|
|
39
|
+
if (opts.profile) {
|
|
40
|
+
if (!profileExists(opts.profile)) {
|
|
41
|
+
error(`Profile "${opts.profile}" does not exist. Create it with "${CONNECTOR_NAME} profile create ${opts.profile}"`);
|
|
42
|
+
process.exit(1);
|
|
43
|
+
}
|
|
44
|
+
setProfileOverride(opts.profile);
|
|
45
|
+
}
|
|
46
|
+
if (opts.apiKey) {
|
|
47
|
+
process.env.TRELLO_API_KEY = opts.apiKey;
|
|
48
|
+
}
|
|
49
|
+
if (opts.token) {
|
|
50
|
+
process.env.TRELLO_TOKEN = opts.token;
|
|
51
|
+
}
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
function getFormat(cmd: Command): OutputFormat {
|
|
55
|
+
const parent = cmd.parent;
|
|
56
|
+
return (parent?.opts().format || 'pretty') as OutputFormat;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
function getClient(): Trello {
|
|
60
|
+
const apiKey = getApiKey();
|
|
61
|
+
const token = getToken();
|
|
62
|
+
if (!apiKey) {
|
|
63
|
+
error(`No API key configured. Run "${CONNECTOR_NAME} config set-key <key>" or set TRELLO_API_KEY environment variable.`);
|
|
64
|
+
process.exit(1);
|
|
65
|
+
}
|
|
66
|
+
if (!token) {
|
|
67
|
+
error(`No token configured. Run "${CONNECTOR_NAME} config set-token <token>" or set TRELLO_TOKEN environment variable.`);
|
|
68
|
+
process.exit(1);
|
|
69
|
+
}
|
|
70
|
+
return new Trello({ apiKey, token });
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// ============================================
|
|
74
|
+
// Profile Commands
|
|
75
|
+
// ============================================
|
|
76
|
+
const profileCmd = program
|
|
77
|
+
.command('profile')
|
|
78
|
+
.description('Manage configuration profiles');
|
|
79
|
+
|
|
80
|
+
profileCmd
|
|
81
|
+
.command('list')
|
|
82
|
+
.description('List all profiles')
|
|
83
|
+
.action(() => {
|
|
84
|
+
const profiles = listProfiles();
|
|
85
|
+
const current = getCurrentProfile();
|
|
86
|
+
|
|
87
|
+
if (profiles.length === 0) {
|
|
88
|
+
info('No profiles found. Use "profile create <name>" to create one.');
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
success(`Profiles:`);
|
|
93
|
+
profiles.forEach(p => {
|
|
94
|
+
const isActive = p === current ? chalk.green(' (active)') : '';
|
|
95
|
+
console.log(` ${p}${isActive}`);
|
|
96
|
+
});
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
profileCmd
|
|
100
|
+
.command('use <name>')
|
|
101
|
+
.description('Switch to a profile')
|
|
102
|
+
.action((name: string) => {
|
|
103
|
+
if (!profileExists(name)) {
|
|
104
|
+
error(`Profile "${name}" does not exist. Create it with "profile create ${name}"`);
|
|
105
|
+
process.exit(1);
|
|
106
|
+
}
|
|
107
|
+
setCurrentProfile(name);
|
|
108
|
+
success(`Switched to profile: ${name}`);
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
profileCmd
|
|
112
|
+
.command('create <name>')
|
|
113
|
+
.description('Create a new profile')
|
|
114
|
+
.option('--api-key <key>', 'API key')
|
|
115
|
+
.option('--token <token>', 'Token')
|
|
116
|
+
.option('--use', 'Switch to this profile after creation')
|
|
117
|
+
.action((name: string, opts) => {
|
|
118
|
+
if (profileExists(name)) {
|
|
119
|
+
error(`Profile "${name}" already exists`);
|
|
120
|
+
process.exit(1);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
createProfile(name, {
|
|
124
|
+
apiKey: opts.apiKey,
|
|
125
|
+
token: opts.token,
|
|
126
|
+
});
|
|
127
|
+
success(`Profile "${name}" created`);
|
|
128
|
+
|
|
129
|
+
if (opts.use) {
|
|
130
|
+
setCurrentProfile(name);
|
|
131
|
+
info(`Switched to profile: ${name}`);
|
|
132
|
+
}
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
profileCmd
|
|
136
|
+
.command('delete <name>')
|
|
137
|
+
.description('Delete a profile')
|
|
138
|
+
.action((name: string) => {
|
|
139
|
+
if (name === 'default') {
|
|
140
|
+
error('Cannot delete the default profile');
|
|
141
|
+
process.exit(1);
|
|
142
|
+
}
|
|
143
|
+
if (deleteProfile(name)) {
|
|
144
|
+
success(`Profile "${name}" deleted`);
|
|
145
|
+
} else {
|
|
146
|
+
error(`Profile "${name}" not found`);
|
|
147
|
+
process.exit(1);
|
|
148
|
+
}
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
profileCmd
|
|
152
|
+
.command('show [name]')
|
|
153
|
+
.description('Show profile configuration')
|
|
154
|
+
.action((name?: string) => {
|
|
155
|
+
const profileName = name || getCurrentProfile();
|
|
156
|
+
const config = loadProfile(profileName);
|
|
157
|
+
const active = getCurrentProfile();
|
|
158
|
+
|
|
159
|
+
console.log(chalk.bold(`Profile: ${profileName}${profileName === active ? chalk.green(' (active)') : ''}`));
|
|
160
|
+
info(`API Key: ${config.apiKey ? `${config.apiKey.substring(0, 8)}...` : chalk.gray('not set')}`);
|
|
161
|
+
info(`Token: ${config.token ? `${config.token.substring(0, 8)}...` : chalk.gray('not set')}`);
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
// ============================================
|
|
165
|
+
// Config Commands
|
|
166
|
+
// ============================================
|
|
167
|
+
const configCmd = program
|
|
168
|
+
.command('config')
|
|
169
|
+
.description('Manage CLI configuration (for active profile)');
|
|
170
|
+
|
|
171
|
+
configCmd
|
|
172
|
+
.command('set-key <apiKey>')
|
|
173
|
+
.description('Set API key')
|
|
174
|
+
.action((apiKey: string) => {
|
|
175
|
+
setApiKey(apiKey);
|
|
176
|
+
success(`API key saved to profile: ${getCurrentProfile()}`);
|
|
177
|
+
});
|
|
178
|
+
|
|
179
|
+
configCmd
|
|
180
|
+
.command('set-token <token>')
|
|
181
|
+
.description('Set token')
|
|
182
|
+
.action((token: string) => {
|
|
183
|
+
setToken(token);
|
|
184
|
+
success(`Token saved to profile: ${getCurrentProfile()}`);
|
|
185
|
+
});
|
|
186
|
+
|
|
187
|
+
configCmd
|
|
188
|
+
.command('show')
|
|
189
|
+
.description('Show current configuration')
|
|
190
|
+
.action(() => {
|
|
191
|
+
const profileName = getCurrentProfile();
|
|
192
|
+
const apiKey = getApiKey();
|
|
193
|
+
const token = getToken();
|
|
194
|
+
|
|
195
|
+
console.log(chalk.bold(`Active Profile: ${profileName}`));
|
|
196
|
+
info(`Config directory: ${getConfigDir()}`);
|
|
197
|
+
info(`API Key: ${apiKey ? `${apiKey.substring(0, 8)}...` : chalk.gray('not set')}`);
|
|
198
|
+
info(`Token: ${token ? `${token.substring(0, 8)}...` : chalk.gray('not set')}`);
|
|
199
|
+
});
|
|
200
|
+
|
|
201
|
+
configCmd
|
|
202
|
+
.command('clear')
|
|
203
|
+
.description('Clear configuration for active profile')
|
|
204
|
+
.action(() => {
|
|
205
|
+
clearConfig();
|
|
206
|
+
success(`Configuration cleared for profile: ${getCurrentProfile()}`);
|
|
207
|
+
});
|
|
208
|
+
|
|
209
|
+
// ============================================
|
|
210
|
+
// Member Commands
|
|
211
|
+
// ============================================
|
|
212
|
+
const memberCmd = program
|
|
213
|
+
.command('member')
|
|
214
|
+
.description('Member management');
|
|
215
|
+
|
|
216
|
+
memberCmd
|
|
217
|
+
.command('me')
|
|
218
|
+
.description('Get current member')
|
|
219
|
+
.action(async () => {
|
|
220
|
+
try {
|
|
221
|
+
const client = getClient();
|
|
222
|
+
const result = await client.getMe();
|
|
223
|
+
print(result, getFormat(memberCmd));
|
|
224
|
+
} catch (err) {
|
|
225
|
+
error(String(err));
|
|
226
|
+
process.exit(1);
|
|
227
|
+
}
|
|
228
|
+
});
|
|
229
|
+
|
|
230
|
+
memberCmd
|
|
231
|
+
.command('get <idOrUsername>')
|
|
232
|
+
.description('Get a member by ID or username')
|
|
233
|
+
.action(async (idOrUsername: string) => {
|
|
234
|
+
try {
|
|
235
|
+
const client = getClient();
|
|
236
|
+
const result = await client.getMember(idOrUsername);
|
|
237
|
+
print(result, getFormat(memberCmd));
|
|
238
|
+
} catch (err) {
|
|
239
|
+
error(String(err));
|
|
240
|
+
process.exit(1);
|
|
241
|
+
}
|
|
242
|
+
});
|
|
243
|
+
|
|
244
|
+
memberCmd
|
|
245
|
+
.command('boards')
|
|
246
|
+
.description('List boards for a member')
|
|
247
|
+
.option('--member <idOrUsername>', 'Member ID or username', 'me')
|
|
248
|
+
.action(async (opts) => {
|
|
249
|
+
try {
|
|
250
|
+
const client = getClient();
|
|
251
|
+
const result = await client.getMemberBoards(opts.member);
|
|
252
|
+
print(result, getFormat(memberCmd));
|
|
253
|
+
} catch (err) {
|
|
254
|
+
error(String(err));
|
|
255
|
+
process.exit(1);
|
|
256
|
+
}
|
|
257
|
+
});
|
|
258
|
+
|
|
259
|
+
// ============================================
|
|
260
|
+
// Board Commands
|
|
261
|
+
// ============================================
|
|
262
|
+
const boardCmd = program
|
|
263
|
+
.command('board')
|
|
264
|
+
.description('Board management');
|
|
265
|
+
|
|
266
|
+
boardCmd
|
|
267
|
+
.command('list')
|
|
268
|
+
.description('List all boards for current user')
|
|
269
|
+
.action(async () => {
|
|
270
|
+
try {
|
|
271
|
+
const client = getClient();
|
|
272
|
+
const result = await client.getMemberBoards('me');
|
|
273
|
+
print(result, getFormat(boardCmd));
|
|
274
|
+
} catch (err) {
|
|
275
|
+
error(String(err));
|
|
276
|
+
process.exit(1);
|
|
277
|
+
}
|
|
278
|
+
});
|
|
279
|
+
|
|
280
|
+
boardCmd
|
|
281
|
+
.command('get <id>')
|
|
282
|
+
.description('Get a board by ID')
|
|
283
|
+
.action(async (id: string) => {
|
|
284
|
+
try {
|
|
285
|
+
const client = getClient();
|
|
286
|
+
const result = await client.getBoard(id);
|
|
287
|
+
print(result, getFormat(boardCmd));
|
|
288
|
+
} catch (err) {
|
|
289
|
+
error(String(err));
|
|
290
|
+
process.exit(1);
|
|
291
|
+
}
|
|
292
|
+
});
|
|
293
|
+
|
|
294
|
+
boardCmd
|
|
295
|
+
.command('create')
|
|
296
|
+
.description('Create a new board')
|
|
297
|
+
.requiredOption('--name <name>', 'Board name')
|
|
298
|
+
.option('--desc <desc>', 'Board description')
|
|
299
|
+
.action(async (opts) => {
|
|
300
|
+
try {
|
|
301
|
+
const client = getClient();
|
|
302
|
+
const result = await client.createBoard({
|
|
303
|
+
name: opts.name,
|
|
304
|
+
desc: opts.desc,
|
|
305
|
+
});
|
|
306
|
+
success('Board created!');
|
|
307
|
+
print(result, getFormat(boardCmd));
|
|
308
|
+
} catch (err) {
|
|
309
|
+
error(String(err));
|
|
310
|
+
process.exit(1);
|
|
311
|
+
}
|
|
312
|
+
});
|
|
313
|
+
|
|
314
|
+
boardCmd
|
|
315
|
+
.command('delete <id>')
|
|
316
|
+
.description('Delete a board')
|
|
317
|
+
.action(async (id: string) => {
|
|
318
|
+
try {
|
|
319
|
+
const client = getClient();
|
|
320
|
+
await client.deleteBoard(id);
|
|
321
|
+
success(`Board ${id} deleted`);
|
|
322
|
+
} catch (err) {
|
|
323
|
+
error(String(err));
|
|
324
|
+
process.exit(1);
|
|
325
|
+
}
|
|
326
|
+
});
|
|
327
|
+
|
|
328
|
+
boardCmd
|
|
329
|
+
.command('lists <boardId>')
|
|
330
|
+
.description('Get lists on a board')
|
|
331
|
+
.option('--filter <filter>', 'Filter (all, open, closed)', 'open')
|
|
332
|
+
.action(async (boardId: string, opts) => {
|
|
333
|
+
try {
|
|
334
|
+
const client = getClient();
|
|
335
|
+
const result = await client.getBoardLists(boardId, opts.filter);
|
|
336
|
+
print(result, getFormat(boardCmd));
|
|
337
|
+
} catch (err) {
|
|
338
|
+
error(String(err));
|
|
339
|
+
process.exit(1);
|
|
340
|
+
}
|
|
341
|
+
});
|
|
342
|
+
|
|
343
|
+
boardCmd
|
|
344
|
+
.command('cards <boardId>')
|
|
345
|
+
.description('Get cards on a board')
|
|
346
|
+
.option('--filter <filter>', 'Filter (all, open, closed, visible)', 'open')
|
|
347
|
+
.action(async (boardId: string, opts) => {
|
|
348
|
+
try {
|
|
349
|
+
const client = getClient();
|
|
350
|
+
const result = await client.getBoardCards(boardId, opts.filter);
|
|
351
|
+
print(result, getFormat(boardCmd));
|
|
352
|
+
} catch (err) {
|
|
353
|
+
error(String(err));
|
|
354
|
+
process.exit(1);
|
|
355
|
+
}
|
|
356
|
+
});
|
|
357
|
+
|
|
358
|
+
boardCmd
|
|
359
|
+
.command('labels <boardId>')
|
|
360
|
+
.description('Get labels on a board')
|
|
361
|
+
.action(async (boardId: string) => {
|
|
362
|
+
try {
|
|
363
|
+
const client = getClient();
|
|
364
|
+
const result = await client.getBoardLabels(boardId);
|
|
365
|
+
print(result, getFormat(boardCmd));
|
|
366
|
+
} catch (err) {
|
|
367
|
+
error(String(err));
|
|
368
|
+
process.exit(1);
|
|
369
|
+
}
|
|
370
|
+
});
|
|
371
|
+
|
|
372
|
+
// ============================================
|
|
373
|
+
// List Commands
|
|
374
|
+
// ============================================
|
|
375
|
+
const listCmd = program
|
|
376
|
+
.command('list')
|
|
377
|
+
.description('List management');
|
|
378
|
+
|
|
379
|
+
listCmd
|
|
380
|
+
.command('get <id>')
|
|
381
|
+
.description('Get a list by ID')
|
|
382
|
+
.action(async (id: string) => {
|
|
383
|
+
try {
|
|
384
|
+
const client = getClient();
|
|
385
|
+
const result = await client.getList(id);
|
|
386
|
+
print(result, getFormat(listCmd));
|
|
387
|
+
} catch (err) {
|
|
388
|
+
error(String(err));
|
|
389
|
+
process.exit(1);
|
|
390
|
+
}
|
|
391
|
+
});
|
|
392
|
+
|
|
393
|
+
listCmd
|
|
394
|
+
.command('create')
|
|
395
|
+
.description('Create a new list')
|
|
396
|
+
.requiredOption('--name <name>', 'List name')
|
|
397
|
+
.requiredOption('--board <boardId>', 'Board ID')
|
|
398
|
+
.option('--pos <pos>', 'Position (top, bottom, or number)')
|
|
399
|
+
.action(async (opts) => {
|
|
400
|
+
try {
|
|
401
|
+
const client = getClient();
|
|
402
|
+
const result = await client.createList({
|
|
403
|
+
name: opts.name,
|
|
404
|
+
idBoard: opts.board,
|
|
405
|
+
pos: opts.pos,
|
|
406
|
+
});
|
|
407
|
+
success('List created!');
|
|
408
|
+
print(result, getFormat(listCmd));
|
|
409
|
+
} catch (err) {
|
|
410
|
+
error(String(err));
|
|
411
|
+
process.exit(1);
|
|
412
|
+
}
|
|
413
|
+
});
|
|
414
|
+
|
|
415
|
+
listCmd
|
|
416
|
+
.command('archive <id>')
|
|
417
|
+
.description('Archive a list')
|
|
418
|
+
.action(async (id: string) => {
|
|
419
|
+
try {
|
|
420
|
+
const client = getClient();
|
|
421
|
+
await client.archiveList(id);
|
|
422
|
+
success(`List ${id} archived`);
|
|
423
|
+
} catch (err) {
|
|
424
|
+
error(String(err));
|
|
425
|
+
process.exit(1);
|
|
426
|
+
}
|
|
427
|
+
});
|
|
428
|
+
|
|
429
|
+
listCmd
|
|
430
|
+
.command('cards <listId>')
|
|
431
|
+
.description('Get cards in a list')
|
|
432
|
+
.action(async (listId: string) => {
|
|
433
|
+
try {
|
|
434
|
+
const client = getClient();
|
|
435
|
+
const result = await client.getListCards(listId);
|
|
436
|
+
print(result, getFormat(listCmd));
|
|
437
|
+
} catch (err) {
|
|
438
|
+
error(String(err));
|
|
439
|
+
process.exit(1);
|
|
440
|
+
}
|
|
441
|
+
});
|
|
442
|
+
|
|
443
|
+
// ============================================
|
|
444
|
+
// Card Commands
|
|
445
|
+
// ============================================
|
|
446
|
+
const cardCmd = program
|
|
447
|
+
.command('card')
|
|
448
|
+
.description('Card management');
|
|
449
|
+
|
|
450
|
+
cardCmd
|
|
451
|
+
.command('get <id>')
|
|
452
|
+
.description('Get a card by ID')
|
|
453
|
+
.action(async (id: string) => {
|
|
454
|
+
try {
|
|
455
|
+
const client = getClient();
|
|
456
|
+
const result = await client.getCard(id);
|
|
457
|
+
print(result, getFormat(cardCmd));
|
|
458
|
+
} catch (err) {
|
|
459
|
+
error(String(err));
|
|
460
|
+
process.exit(1);
|
|
461
|
+
}
|
|
462
|
+
});
|
|
463
|
+
|
|
464
|
+
cardCmd
|
|
465
|
+
.command('create')
|
|
466
|
+
.description('Create a new card')
|
|
467
|
+
.requiredOption('--name <name>', 'Card name')
|
|
468
|
+
.requiredOption('--list <listId>', 'List ID')
|
|
469
|
+
.option('--desc <desc>', 'Card description')
|
|
470
|
+
.option('--due <date>', 'Due date')
|
|
471
|
+
.option('--pos <pos>', 'Position (top, bottom, or number)')
|
|
472
|
+
.action(async (opts) => {
|
|
473
|
+
try {
|
|
474
|
+
const client = getClient();
|
|
475
|
+
const result = await client.createCard({
|
|
476
|
+
name: opts.name,
|
|
477
|
+
idList: opts.list,
|
|
478
|
+
desc: opts.desc,
|
|
479
|
+
due: opts.due,
|
|
480
|
+
pos: opts.pos,
|
|
481
|
+
});
|
|
482
|
+
success('Card created!');
|
|
483
|
+
print(result, getFormat(cardCmd));
|
|
484
|
+
} catch (err) {
|
|
485
|
+
error(String(err));
|
|
486
|
+
process.exit(1);
|
|
487
|
+
}
|
|
488
|
+
});
|
|
489
|
+
|
|
490
|
+
cardCmd
|
|
491
|
+
.command('update <id>')
|
|
492
|
+
.description('Update a card')
|
|
493
|
+
.option('--name <name>', 'Card name')
|
|
494
|
+
.option('--desc <desc>', 'Card description')
|
|
495
|
+
.option('--due <date>', 'Due date')
|
|
496
|
+
.option('--closed', 'Archive the card')
|
|
497
|
+
.action(async (id: string, opts) => {
|
|
498
|
+
try {
|
|
499
|
+
const client = getClient();
|
|
500
|
+
const result = await client.updateCard(id, {
|
|
501
|
+
name: opts.name,
|
|
502
|
+
desc: opts.desc,
|
|
503
|
+
due: opts.due,
|
|
504
|
+
closed: opts.closed,
|
|
505
|
+
});
|
|
506
|
+
success('Card updated!');
|
|
507
|
+
print(result, getFormat(cardCmd));
|
|
508
|
+
} catch (err) {
|
|
509
|
+
error(String(err));
|
|
510
|
+
process.exit(1);
|
|
511
|
+
}
|
|
512
|
+
});
|
|
513
|
+
|
|
514
|
+
cardCmd
|
|
515
|
+
.command('delete <id>')
|
|
516
|
+
.description('Delete a card')
|
|
517
|
+
.action(async (id: string) => {
|
|
518
|
+
try {
|
|
519
|
+
const client = getClient();
|
|
520
|
+
await client.deleteCard(id);
|
|
521
|
+
success(`Card ${id} deleted`);
|
|
522
|
+
} catch (err) {
|
|
523
|
+
error(String(err));
|
|
524
|
+
process.exit(1);
|
|
525
|
+
}
|
|
526
|
+
});
|
|
527
|
+
|
|
528
|
+
cardCmd
|
|
529
|
+
.command('move <id>')
|
|
530
|
+
.description('Move a card to another list')
|
|
531
|
+
.requiredOption('--list <listId>', 'Destination list ID')
|
|
532
|
+
.option('--pos <pos>', 'Position (top, bottom, or number)')
|
|
533
|
+
.action(async (id: string, opts) => {
|
|
534
|
+
try {
|
|
535
|
+
const client = getClient();
|
|
536
|
+
const result = await client.moveCard(id, opts.list, opts.pos);
|
|
537
|
+
success('Card moved!');
|
|
538
|
+
print(result, getFormat(cardCmd));
|
|
539
|
+
} catch (err) {
|
|
540
|
+
error(String(err));
|
|
541
|
+
process.exit(1);
|
|
542
|
+
}
|
|
543
|
+
});
|
|
544
|
+
|
|
545
|
+
cardCmd
|
|
546
|
+
.command('archive <id>')
|
|
547
|
+
.description('Archive a card')
|
|
548
|
+
.action(async (id: string) => {
|
|
549
|
+
try {
|
|
550
|
+
const client = getClient();
|
|
551
|
+
await client.archiveCard(id);
|
|
552
|
+
success(`Card ${id} archived`);
|
|
553
|
+
} catch (err) {
|
|
554
|
+
error(String(err));
|
|
555
|
+
process.exit(1);
|
|
556
|
+
}
|
|
557
|
+
});
|
|
558
|
+
|
|
559
|
+
// ============================================
|
|
560
|
+
// Checklist Commands
|
|
561
|
+
// ============================================
|
|
562
|
+
const checklistCmd = program
|
|
563
|
+
.command('checklist')
|
|
564
|
+
.description('Checklist management');
|
|
565
|
+
|
|
566
|
+
checklistCmd
|
|
567
|
+
.command('get <id>')
|
|
568
|
+
.description('Get a checklist by ID')
|
|
569
|
+
.action(async (id: string) => {
|
|
570
|
+
try {
|
|
571
|
+
const client = getClient();
|
|
572
|
+
const result = await client.getChecklist(id);
|
|
573
|
+
print(result, getFormat(checklistCmd));
|
|
574
|
+
} catch (err) {
|
|
575
|
+
error(String(err));
|
|
576
|
+
process.exit(1);
|
|
577
|
+
}
|
|
578
|
+
});
|
|
579
|
+
|
|
580
|
+
checklistCmd
|
|
581
|
+
.command('create')
|
|
582
|
+
.description('Create a new checklist')
|
|
583
|
+
.requiredOption('--name <name>', 'Checklist name')
|
|
584
|
+
.requiredOption('--card <cardId>', 'Card ID')
|
|
585
|
+
.action(async (opts) => {
|
|
586
|
+
try {
|
|
587
|
+
const client = getClient();
|
|
588
|
+
const result = await client.createChecklist({
|
|
589
|
+
name: opts.name,
|
|
590
|
+
idCard: opts.card,
|
|
591
|
+
});
|
|
592
|
+
success('Checklist created!');
|
|
593
|
+
print(result, getFormat(checklistCmd));
|
|
594
|
+
} catch (err) {
|
|
595
|
+
error(String(err));
|
|
596
|
+
process.exit(1);
|
|
597
|
+
}
|
|
598
|
+
});
|
|
599
|
+
|
|
600
|
+
checklistCmd
|
|
601
|
+
.command('delete <id>')
|
|
602
|
+
.description('Delete a checklist')
|
|
603
|
+
.action(async (id: string) => {
|
|
604
|
+
try {
|
|
605
|
+
const client = getClient();
|
|
606
|
+
await client.deleteChecklist(id);
|
|
607
|
+
success(`Checklist ${id} deleted`);
|
|
608
|
+
} catch (err) {
|
|
609
|
+
error(String(err));
|
|
610
|
+
process.exit(1);
|
|
611
|
+
}
|
|
612
|
+
});
|
|
613
|
+
|
|
614
|
+
checklistCmd
|
|
615
|
+
.command('items <checklistId>')
|
|
616
|
+
.description('Get items in a checklist')
|
|
617
|
+
.action(async (checklistId: string) => {
|
|
618
|
+
try {
|
|
619
|
+
const client = getClient();
|
|
620
|
+
const result = await client.getChecklistItems(checklistId);
|
|
621
|
+
print(result, getFormat(checklistCmd));
|
|
622
|
+
} catch (err) {
|
|
623
|
+
error(String(err));
|
|
624
|
+
process.exit(1);
|
|
625
|
+
}
|
|
626
|
+
});
|
|
627
|
+
|
|
628
|
+
checklistCmd
|
|
629
|
+
.command('add-item')
|
|
630
|
+
.description('Add an item to a checklist')
|
|
631
|
+
.requiredOption('--checklist <checklistId>', 'Checklist ID')
|
|
632
|
+
.requiredOption('--name <name>', 'Item name')
|
|
633
|
+
.action(async (opts) => {
|
|
634
|
+
try {
|
|
635
|
+
const client = getClient();
|
|
636
|
+
const result = await client.createCheckItem(opts.checklist, { name: opts.name });
|
|
637
|
+
success('Check item added!');
|
|
638
|
+
print(result, getFormat(checklistCmd));
|
|
639
|
+
} catch (err) {
|
|
640
|
+
error(String(err));
|
|
641
|
+
process.exit(1);
|
|
642
|
+
}
|
|
643
|
+
});
|
|
644
|
+
|
|
645
|
+
// ============================================
|
|
646
|
+
// Comment Commands
|
|
647
|
+
// ============================================
|
|
648
|
+
const commentCmd = program
|
|
649
|
+
.command('comment')
|
|
650
|
+
.description('Comment management');
|
|
651
|
+
|
|
652
|
+
commentCmd
|
|
653
|
+
.command('add')
|
|
654
|
+
.description('Add a comment to a card')
|
|
655
|
+
.requiredOption('--card <cardId>', 'Card ID')
|
|
656
|
+
.requiredOption('--text <text>', 'Comment text')
|
|
657
|
+
.action(async (opts) => {
|
|
658
|
+
try {
|
|
659
|
+
const client = getClient();
|
|
660
|
+
const result = await client.addComment(opts.card, opts.text);
|
|
661
|
+
success('Comment added!');
|
|
662
|
+
print(result, getFormat(commentCmd));
|
|
663
|
+
} catch (err) {
|
|
664
|
+
error(String(err));
|
|
665
|
+
process.exit(1);
|
|
666
|
+
}
|
|
667
|
+
});
|
|
668
|
+
|
|
669
|
+
// ============================================
|
|
670
|
+
// Label Commands
|
|
671
|
+
// ============================================
|
|
672
|
+
const labelCmd = program
|
|
673
|
+
.command('label')
|
|
674
|
+
.description('Label management');
|
|
675
|
+
|
|
676
|
+
labelCmd
|
|
677
|
+
.command('create')
|
|
678
|
+
.description('Create a new label')
|
|
679
|
+
.requiredOption('--name <name>', 'Label name')
|
|
680
|
+
.requiredOption('--color <color>', 'Label color')
|
|
681
|
+
.requiredOption('--board <boardId>', 'Board ID')
|
|
682
|
+
.action(async (opts) => {
|
|
683
|
+
try {
|
|
684
|
+
const client = getClient();
|
|
685
|
+
const result = await client.createLabel({
|
|
686
|
+
name: opts.name,
|
|
687
|
+
color: opts.color,
|
|
688
|
+
idBoard: opts.board,
|
|
689
|
+
});
|
|
690
|
+
success('Label created!');
|
|
691
|
+
print(result, getFormat(labelCmd));
|
|
692
|
+
} catch (err) {
|
|
693
|
+
error(String(err));
|
|
694
|
+
process.exit(1);
|
|
695
|
+
}
|
|
696
|
+
});
|
|
697
|
+
|
|
698
|
+
labelCmd
|
|
699
|
+
.command('delete <id>')
|
|
700
|
+
.description('Delete a label')
|
|
701
|
+
.action(async (id: string) => {
|
|
702
|
+
try {
|
|
703
|
+
const client = getClient();
|
|
704
|
+
await client.deleteLabel(id);
|
|
705
|
+
success(`Label ${id} deleted`);
|
|
706
|
+
} catch (err) {
|
|
707
|
+
error(String(err));
|
|
708
|
+
process.exit(1);
|
|
709
|
+
}
|
|
710
|
+
});
|
|
711
|
+
|
|
712
|
+
// ============================================
|
|
713
|
+
// Search Commands
|
|
714
|
+
// ============================================
|
|
715
|
+
const searchCmd = program
|
|
716
|
+
.command('search')
|
|
717
|
+
.description('Search Trello');
|
|
718
|
+
|
|
719
|
+
searchCmd
|
|
720
|
+
.command('query <query>')
|
|
721
|
+
.description('Search for boards, cards, members')
|
|
722
|
+
.option('--boards <boardIds>', 'Limit to specific boards (comma-separated)')
|
|
723
|
+
.action(async (query: string, opts) => {
|
|
724
|
+
try {
|
|
725
|
+
const client = getClient();
|
|
726
|
+
const result = await client.search(query, {
|
|
727
|
+
idBoards: opts.boards,
|
|
728
|
+
});
|
|
729
|
+
print(result, getFormat(searchCmd));
|
|
730
|
+
} catch (err) {
|
|
731
|
+
error(String(err));
|
|
732
|
+
process.exit(1);
|
|
733
|
+
}
|
|
734
|
+
});
|
|
735
|
+
|
|
736
|
+
// Parse and execute
|
|
737
|
+
program.parse();
|