@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.
Files changed (127) hide show
  1. package/bin/index.js +71 -1
  2. package/bin/mcp.js +71 -1
  3. package/bin/serve.js +70 -0
  4. package/connectors/connect-asana/.env.example +11 -0
  5. package/connectors/connect-asana/CLAUDE.md +128 -0
  6. package/connectors/connect-asana/README.md +193 -0
  7. package/connectors/connect-asana/package.json +52 -0
  8. package/connectors/connect-asana/src/api/client.ts +119 -0
  9. package/connectors/connect-asana/src/api/index.ts +319 -0
  10. package/connectors/connect-asana/src/cli/index.ts +731 -0
  11. package/connectors/connect-asana/src/index.ts +19 -0
  12. package/connectors/connect-asana/src/types/index.ts +270 -0
  13. package/connectors/connect-asana/src/utils/config.ts +171 -0
  14. package/connectors/connect-asana/src/utils/output.ts +119 -0
  15. package/connectors/connect-asana/tsconfig.json +16 -0
  16. package/connectors/connect-clickup/.env.example +11 -0
  17. package/connectors/connect-clickup/CLAUDE.md +128 -0
  18. package/connectors/connect-clickup/README.md +193 -0
  19. package/connectors/connect-clickup/package.json +52 -0
  20. package/connectors/connect-clickup/src/api/client.ts +116 -0
  21. package/connectors/connect-clickup/src/api/index.ts +400 -0
  22. package/connectors/connect-clickup/src/cli/index.ts +625 -0
  23. package/connectors/connect-clickup/src/index.ts +19 -0
  24. package/connectors/connect-clickup/src/types/index.ts +591 -0
  25. package/connectors/connect-clickup/src/utils/config.ts +157 -0
  26. package/connectors/connect-clickup/src/utils/output.ts +119 -0
  27. package/connectors/connect-clickup/tsconfig.json +16 -0
  28. package/connectors/connect-confluence/.env.example +11 -0
  29. package/connectors/connect-confluence/CLAUDE.md +272 -0
  30. package/connectors/connect-confluence/README.md +193 -0
  31. package/connectors/connect-confluence/package.json +53 -0
  32. package/connectors/connect-confluence/scripts/release.ts +179 -0
  33. package/connectors/connect-confluence/src/api/client.ts +213 -0
  34. package/connectors/connect-confluence/src/api/example.ts +48 -0
  35. package/connectors/connect-confluence/src/api/index.ts +51 -0
  36. package/connectors/connect-confluence/src/cli/index.ts +254 -0
  37. package/connectors/connect-confluence/src/index.ts +103 -0
  38. package/connectors/connect-confluence/src/types/index.ts +237 -0
  39. package/connectors/connect-confluence/src/utils/auth.ts +274 -0
  40. package/connectors/connect-confluence/src/utils/bulk.ts +212 -0
  41. package/connectors/connect-confluence/src/utils/config.ts +326 -0
  42. package/connectors/connect-confluence/src/utils/output.ts +175 -0
  43. package/connectors/connect-confluence/src/utils/settings.ts +114 -0
  44. package/connectors/connect-confluence/src/utils/storage.ts +198 -0
  45. package/connectors/connect-confluence/tsconfig.json +16 -0
  46. package/connectors/connect-jira/.env.example +11 -0
  47. package/connectors/connect-jira/CLAUDE.md +128 -0
  48. package/connectors/connect-jira/README.md +193 -0
  49. package/connectors/connect-jira/package.json +53 -0
  50. package/connectors/connect-jira/src/api/client.ts +131 -0
  51. package/connectors/connect-jira/src/api/index.ts +266 -0
  52. package/connectors/connect-jira/src/cli/index.ts +653 -0
  53. package/connectors/connect-jira/src/index.ts +23 -0
  54. package/connectors/connect-jira/src/types/index.ts +448 -0
  55. package/connectors/connect-jira/src/utils/config.ts +179 -0
  56. package/connectors/connect-jira/src/utils/output.ts +119 -0
  57. package/connectors/connect-jira/tsconfig.json +16 -0
  58. package/connectors/connect-linear/CLAUDE.md +88 -0
  59. package/connectors/connect-linear/README.md +201 -0
  60. package/connectors/connect-linear/package.json +45 -0
  61. package/connectors/connect-linear/src/api/client.ts +62 -0
  62. package/connectors/connect-linear/src/api/index.ts +46 -0
  63. package/connectors/connect-linear/src/api/issues.ts +247 -0
  64. package/connectors/connect-linear/src/api/projects.ts +179 -0
  65. package/connectors/connect-linear/src/api/teams.ts +125 -0
  66. package/connectors/connect-linear/src/api/users.ts +112 -0
  67. package/connectors/connect-linear/src/cli/index.ts +560 -0
  68. package/connectors/connect-linear/src/index.ts +27 -0
  69. package/connectors/connect-linear/src/types/index.ts +275 -0
  70. package/connectors/connect-linear/src/utils/config.ts +249 -0
  71. package/connectors/connect-linear/src/utils/output.ts +119 -0
  72. package/connectors/connect-linear/tsconfig.json +16 -0
  73. package/connectors/connect-slack/.env.example +7 -0
  74. package/connectors/connect-slack/CLAUDE.md +69 -0
  75. package/connectors/connect-slack/README.md +150 -0
  76. package/connectors/connect-slack/package.json +44 -0
  77. package/connectors/connect-slack/src/api/channels.ts +112 -0
  78. package/connectors/connect-slack/src/api/client.ts +97 -0
  79. package/connectors/connect-slack/src/api/index.ts +42 -0
  80. package/connectors/connect-slack/src/api/messages.ts +127 -0
  81. package/connectors/connect-slack/src/api/users.ts +110 -0
  82. package/connectors/connect-slack/src/cli/index.ts +494 -0
  83. package/connectors/connect-slack/src/index.ts +21 -0
  84. package/connectors/connect-slack/src/types/index.ts +263 -0
  85. package/connectors/connect-slack/src/utils/config.ts +297 -0
  86. package/connectors/connect-slack/src/utils/output.ts +119 -0
  87. package/connectors/connect-slack/tsconfig.json +16 -0
  88. package/connectors/connect-telegram/.env.example +2 -0
  89. package/connectors/connect-telegram/package.json +49 -0
  90. package/connectors/connect-todoist/.env.example +11 -0
  91. package/connectors/connect-todoist/CLAUDE.md +104 -0
  92. package/connectors/connect-todoist/README.md +193 -0
  93. package/connectors/connect-todoist/package.json +52 -0
  94. package/connectors/connect-todoist/src/api/client.ts +117 -0
  95. package/connectors/connect-todoist/src/api/index.ts +188 -0
  96. package/connectors/connect-todoist/src/cli/index.ts +990 -0
  97. package/connectors/connect-todoist/src/index.ts +21 -0
  98. package/connectors/connect-todoist/src/types/index.ts +240 -0
  99. package/connectors/connect-todoist/src/utils/config.ts +157 -0
  100. package/connectors/connect-todoist/src/utils/output.ts +119 -0
  101. package/connectors/connect-todoist/tsconfig.json +16 -0
  102. package/connectors/connect-trello/.env.example +11 -0
  103. package/connectors/connect-trello/CLAUDE.md +128 -0
  104. package/connectors/connect-trello/README.md +193 -0
  105. package/connectors/connect-trello/package.json +53 -0
  106. package/connectors/connect-trello/src/api/client.ts +128 -0
  107. package/connectors/connect-trello/src/api/index.ts +278 -0
  108. package/connectors/connect-trello/src/cli/index.ts +737 -0
  109. package/connectors/connect-trello/src/index.ts +21 -0
  110. package/connectors/connect-trello/src/types/index.ts +314 -0
  111. package/connectors/connect-trello/src/utils/config.ts +182 -0
  112. package/connectors/connect-trello/src/utils/output.ts +119 -0
  113. package/connectors/connect-trello/tsconfig.json +16 -0
  114. package/connectors/connect-whatsapp/.env.example +11 -0
  115. package/connectors/connect-whatsapp/CLAUDE.md +113 -0
  116. package/connectors/connect-whatsapp/README.md +193 -0
  117. package/connectors/connect-whatsapp/package.json +53 -0
  118. package/connectors/connect-whatsapp/src/api/client.ts +133 -0
  119. package/connectors/connect-whatsapp/src/api/index.ts +365 -0
  120. package/connectors/connect-whatsapp/src/cli/index.ts +686 -0
  121. package/connectors/connect-whatsapp/src/index.ts +25 -0
  122. package/connectors/connect-whatsapp/src/types/index.ts +502 -0
  123. package/connectors/connect-whatsapp/src/utils/config.ts +179 -0
  124. package/connectors/connect-whatsapp/src/utils/output.ts +119 -0
  125. package/connectors/connect-whatsapp/tsconfig.json +16 -0
  126. package/dist/index.js +70 -0
  127. package/package.json +1 -1
@@ -0,0 +1,560 @@
1
+ #!/usr/bin/env bun
2
+ import { Command } from 'commander';
3
+ import chalk from 'chalk';
4
+ import { Linear } from '../api';
5
+ import type { OutputFormat, LinearPriority } from '../types';
6
+ import {
7
+ getApiKey,
8
+ setApiKey,
9
+ getDefaultTeamId,
10
+ setDefaultTeamId,
11
+ getCurrentProfile,
12
+ setCurrentProfile,
13
+ listProfiles,
14
+ createProfile,
15
+ deleteProfile,
16
+ profileExists,
17
+ clearConfig,
18
+ isAuthenticated,
19
+ setProfileOverride,
20
+ } from '../utils/config';
21
+ import { print, success, error, info, heading } from '../utils/output';
22
+
23
+ const program = new Command();
24
+
25
+ // Helper to get authenticated client
26
+ function getClient(): Linear {
27
+ const apiKey = getApiKey();
28
+ if (!apiKey) {
29
+ console.error(chalk.red('Error: No Linear API key configured.'));
30
+ console.error(chalk.yellow('Set API key with: connect-linear config set-api-key <key>'));
31
+ console.error(chalk.yellow('Or set LINEAR_API_KEY environment variable'));
32
+ process.exit(1);
33
+ }
34
+ return new Linear({ apiKey });
35
+ }
36
+
37
+ // Global options
38
+ program
39
+ .name('connect-linear')
40
+ .description('Linear API CLI')
41
+ .version('0.0.1')
42
+ .option('-p, --profile <name>', 'Use specific profile')
43
+ .option('-f, --format <format>', 'Output format: json, table, pretty', 'pretty')
44
+ .hook('preAction', (thisCommand) => {
45
+ const opts = thisCommand.opts();
46
+ if (opts.profile) {
47
+ setProfileOverride(opts.profile);
48
+ }
49
+ });
50
+
51
+ // ============================================
52
+ // Auth/Config Commands
53
+ // ============================================
54
+
55
+ const configCmd = program
56
+ .command('config')
57
+ .description('Configuration commands');
58
+
59
+ configCmd
60
+ .command('set-api-key <key>')
61
+ .description('Set API key for current profile')
62
+ .action((key: string) => {
63
+ setApiKey(key);
64
+ success(`API key saved to profile "${getCurrentProfile()}"`);
65
+ });
66
+
67
+ configCmd
68
+ .command('set-team <teamId>')
69
+ .description('Set default team ID')
70
+ .action((teamId: string) => {
71
+ setDefaultTeamId(teamId);
72
+ success(`Default team set to "${teamId}"`);
73
+ });
74
+
75
+ configCmd
76
+ .command('show')
77
+ .description('Show current configuration')
78
+ .action(() => {
79
+ const profile = getCurrentProfile();
80
+ const apiKey = getApiKey();
81
+ const teamId = getDefaultTeamId();
82
+
83
+ heading('Current Configuration');
84
+ print({
85
+ profile,
86
+ authenticated: isAuthenticated(),
87
+ apiKey: apiKey ? `${apiKey.substring(0, 10)}...` : 'Not set',
88
+ defaultTeamId: teamId || 'Not set',
89
+ });
90
+ });
91
+
92
+ configCmd
93
+ .command('clear')
94
+ .description('Clear configuration for current profile')
95
+ .action(() => {
96
+ clearConfig();
97
+ success('Configuration cleared');
98
+ });
99
+
100
+ // ============================================
101
+ // Profile Commands
102
+ // ============================================
103
+
104
+ const profileCmd = program
105
+ .command('profile')
106
+ .description('Profile management');
107
+
108
+ profileCmd
109
+ .command('list')
110
+ .description('List all profiles')
111
+ .action(() => {
112
+ const profiles = listProfiles();
113
+ const current = getCurrentProfile();
114
+
115
+ if (profiles.length === 0) {
116
+ info('No profiles found. Using default.');
117
+ return;
118
+ }
119
+
120
+ heading('Profiles');
121
+ profiles.forEach(p => {
122
+ const marker = p === current ? chalk.green(' (active)') : '';
123
+ console.log(` ${p}${marker}`);
124
+ });
125
+ });
126
+
127
+ profileCmd
128
+ .command('use <name>')
129
+ .description('Switch to a profile')
130
+ .action((name: string) => {
131
+ if (!profileExists(name)) {
132
+ error(`Profile "${name}" does not exist`);
133
+ process.exit(1);
134
+ }
135
+ setCurrentProfile(name);
136
+ success(`Switched to profile "${name}"`);
137
+ });
138
+
139
+ profileCmd
140
+ .command('create <name>')
141
+ .description('Create a new profile')
142
+ .action((name: string) => {
143
+ try {
144
+ createProfile(name);
145
+ success(`Profile "${name}" created`);
146
+ } catch (e) {
147
+ error((e as Error).message);
148
+ process.exit(1);
149
+ }
150
+ });
151
+
152
+ profileCmd
153
+ .command('delete <name>')
154
+ .description('Delete a profile')
155
+ .action((name: string) => {
156
+ try {
157
+ deleteProfile(name);
158
+ success(`Profile "${name}" deleted`);
159
+ } catch (e) {
160
+ error((e as Error).message);
161
+ process.exit(1);
162
+ }
163
+ });
164
+
165
+ profileCmd
166
+ .command('show')
167
+ .description('Show current profile name')
168
+ .action(() => {
169
+ console.log(getCurrentProfile());
170
+ });
171
+
172
+ // ============================================
173
+ // Test/Auth Commands
174
+ // ============================================
175
+
176
+ program
177
+ .command('test')
178
+ .alias('whoami')
179
+ .description('Test authentication and show current user')
180
+ .action(async () => {
181
+ try {
182
+ const client = getClient();
183
+ const result = await client.test();
184
+ print({
185
+ name: result.name,
186
+ displayName: result.displayName,
187
+ email: result.email,
188
+ admin: result.admin,
189
+ active: result.active,
190
+ });
191
+ } catch (e) {
192
+ error((e as Error).message);
193
+ process.exit(1);
194
+ }
195
+ });
196
+
197
+ // ============================================
198
+ // Issue Commands
199
+ // ============================================
200
+
201
+ const issuesCmd = program
202
+ .command('issues')
203
+ .description('Issue commands');
204
+
205
+ issuesCmd
206
+ .command('list')
207
+ .description('List issues')
208
+ .option('-t, --team <id>', 'Filter by team ID')
209
+ .option('-p, --project <id>', 'Filter by project ID')
210
+ .option('-a, --assignee <id>', 'Filter by assignee ID')
211
+ .option('-l, --limit <n>', 'Maximum number to return', '50')
212
+ .action(async (opts) => {
213
+ try {
214
+ const client = getClient();
215
+ const format = program.opts().format as OutputFormat;
216
+ const issues = await client.issues.list({
217
+ teamId: opts.team || getDefaultTeamId(),
218
+ projectId: opts.project,
219
+ assigneeId: opts.assignee,
220
+ first: parseInt(opts.limit, 10),
221
+ });
222
+
223
+ if (format === 'json') {
224
+ print(issues, format);
225
+ } else {
226
+ print(issues.map(i => ({
227
+ id: i.identifier,
228
+ title: i.title.substring(0, 50) + (i.title.length > 50 ? '...' : ''),
229
+ status: i.state?.name || 'Unknown',
230
+ priority: i.priorityLabel,
231
+ assignee: i.assignee?.displayName || 'Unassigned',
232
+ })), format);
233
+ }
234
+ } catch (e) {
235
+ error((e as Error).message);
236
+ process.exit(1);
237
+ }
238
+ });
239
+
240
+ issuesCmd
241
+ .command('get <id>')
242
+ .description('Get issue details')
243
+ .action(async (id: string) => {
244
+ try {
245
+ const client = getClient();
246
+ const format = program.opts().format as OutputFormat;
247
+ const issue = await client.issues.get(id);
248
+ print(issue, format);
249
+ } catch (e) {
250
+ error((e as Error).message);
251
+ process.exit(1);
252
+ }
253
+ });
254
+
255
+ issuesCmd
256
+ .command('create')
257
+ .description('Create a new issue')
258
+ .requiredOption('--title <title>', 'Issue title')
259
+ .requiredOption('--team <id>', 'Team ID')
260
+ .option('--description <text>', 'Issue description')
261
+ .option('--project <id>', 'Project ID')
262
+ .option('--assignee <id>', 'Assignee user ID')
263
+ .option('--priority <n>', 'Priority (0-4)', '0')
264
+ .action(async (opts) => {
265
+ try {
266
+ const client = getClient();
267
+ const format = program.opts().format as OutputFormat;
268
+ const issue = await client.issues.create({
269
+ title: opts.title,
270
+ teamId: opts.team || getDefaultTeamId()!,
271
+ description: opts.description,
272
+ projectId: opts.project,
273
+ assigneeId: opts.assignee,
274
+ priority: parseInt(opts.priority, 10) as LinearPriority,
275
+ });
276
+
277
+ success(`Issue created: ${issue.identifier}`);
278
+ print({
279
+ id: issue.identifier,
280
+ title: issue.title,
281
+ url: issue.url,
282
+ }, format);
283
+ } catch (e) {
284
+ error((e as Error).message);
285
+ process.exit(1);
286
+ }
287
+ });
288
+
289
+ issuesCmd
290
+ .command('update <id>')
291
+ .description('Update an issue')
292
+ .option('--title <title>', 'New title')
293
+ .option('--description <text>', 'New description')
294
+ .option('--state <id>', 'New state ID')
295
+ .option('--assignee <id>', 'New assignee ID')
296
+ .option('--priority <n>', 'New priority (0-4)')
297
+ .action(async (id: string, opts) => {
298
+ try {
299
+ const client = getClient();
300
+ const format = program.opts().format as OutputFormat;
301
+
302
+ const updates: Record<string, unknown> = {};
303
+ if (opts.title) updates.title = opts.title;
304
+ if (opts.description) updates.description = opts.description;
305
+ if (opts.state) updates.stateId = opts.state;
306
+ if (opts.assignee) updates.assigneeId = opts.assignee;
307
+ if (opts.priority) updates.priority = parseInt(opts.priority, 10);
308
+
309
+ const issue = await client.issues.update(id, updates);
310
+ success(`Issue updated: ${issue.identifier}`);
311
+ print({
312
+ id: issue.identifier,
313
+ title: issue.title,
314
+ status: issue.state?.name,
315
+ }, format);
316
+ } catch (e) {
317
+ error((e as Error).message);
318
+ process.exit(1);
319
+ }
320
+ });
321
+
322
+ issuesCmd
323
+ .command('archive <id>')
324
+ .description('Archive an issue')
325
+ .action(async (id: string) => {
326
+ try {
327
+ const client = getClient();
328
+ await client.issues.archive(id);
329
+ success(`Issue ${id} archived`);
330
+ } catch (e) {
331
+ error((e as Error).message);
332
+ process.exit(1);
333
+ }
334
+ });
335
+
336
+ issuesCmd
337
+ .command('search <query>')
338
+ .description('Search issues')
339
+ .option('-l, --limit <n>', 'Maximum results', '20')
340
+ .action(async (query: string, opts) => {
341
+ try {
342
+ const client = getClient();
343
+ const format = program.opts().format as OutputFormat;
344
+ const issues = await client.issues.search(query, parseInt(opts.limit, 10));
345
+
346
+ if (format === 'json') {
347
+ print(issues, format);
348
+ } else {
349
+ print(issues.map(i => ({
350
+ id: i.identifier,
351
+ title: i.title.substring(0, 50) + (i.title.length > 50 ? '...' : ''),
352
+ status: i.state?.name || 'Unknown',
353
+ team: i.team?.key || 'Unknown',
354
+ })), format);
355
+ }
356
+ } catch (e) {
357
+ error((e as Error).message);
358
+ process.exit(1);
359
+ }
360
+ });
361
+
362
+ // ============================================
363
+ // Project Commands
364
+ // ============================================
365
+
366
+ const projectsCmd = program
367
+ .command('projects')
368
+ .description('Project commands');
369
+
370
+ projectsCmd
371
+ .command('list')
372
+ .description('List projects')
373
+ .option('-l, --limit <n>', 'Maximum number to return', '50')
374
+ .action(async (opts) => {
375
+ try {
376
+ const client = getClient();
377
+ const format = program.opts().format as OutputFormat;
378
+ const projects = await client.projects.list({
379
+ first: parseInt(opts.limit, 10),
380
+ });
381
+
382
+ if (format === 'json') {
383
+ print(projects, format);
384
+ } else {
385
+ print(projects.map(p => ({
386
+ id: p.id,
387
+ name: p.name,
388
+ state: p.state,
389
+ progress: `${Math.round(p.progress * 100)}%`,
390
+ lead: p.lead?.displayName || 'None',
391
+ })), format);
392
+ }
393
+ } catch (e) {
394
+ error((e as Error).message);
395
+ process.exit(1);
396
+ }
397
+ });
398
+
399
+ projectsCmd
400
+ .command('get <id>')
401
+ .description('Get project details')
402
+ .action(async (id: string) => {
403
+ try {
404
+ const client = getClient();
405
+ const format = program.opts().format as OutputFormat;
406
+ const project = await client.projects.get(id);
407
+ print(project, format);
408
+ } catch (e) {
409
+ error((e as Error).message);
410
+ process.exit(1);
411
+ }
412
+ });
413
+
414
+ // ============================================
415
+ // Team Commands
416
+ // ============================================
417
+
418
+ const teamsCmd = program
419
+ .command('teams')
420
+ .description('Team commands');
421
+
422
+ teamsCmd
423
+ .command('list')
424
+ .description('List teams')
425
+ .action(async () => {
426
+ try {
427
+ const client = getClient();
428
+ const format = program.opts().format as OutputFormat;
429
+ const teams = await client.teams.list();
430
+
431
+ if (format === 'json') {
432
+ print(teams, format);
433
+ } else {
434
+ print(teams.map(t => ({
435
+ id: t.id,
436
+ key: t.key,
437
+ name: t.name,
438
+ private: t.private ? 'yes' : 'no',
439
+ })), format);
440
+ }
441
+ } catch (e) {
442
+ error((e as Error).message);
443
+ process.exit(1);
444
+ }
445
+ });
446
+
447
+ teamsCmd
448
+ .command('get <id>')
449
+ .description('Get team details')
450
+ .action(async (id: string) => {
451
+ try {
452
+ const client = getClient();
453
+ const format = program.opts().format as OutputFormat;
454
+ const team = await client.teams.get(id);
455
+ print(team, format);
456
+ } catch (e) {
457
+ error((e as Error).message);
458
+ process.exit(1);
459
+ }
460
+ });
461
+
462
+ teamsCmd
463
+ .command('states <teamId>')
464
+ .description('List workflow states for a team')
465
+ .action(async (teamId: string) => {
466
+ try {
467
+ const client = getClient();
468
+ const format = program.opts().format as OutputFormat;
469
+ const states = await client.teams.getWorkflowStates(teamId);
470
+
471
+ if (format === 'json') {
472
+ print(states, format);
473
+ } else {
474
+ print(states.map(s => ({
475
+ id: s.id,
476
+ name: s.name,
477
+ type: s.type,
478
+ color: s.color,
479
+ })), format);
480
+ }
481
+ } catch (e) {
482
+ error((e as Error).message);
483
+ process.exit(1);
484
+ }
485
+ });
486
+
487
+ // ============================================
488
+ // User Commands
489
+ // ============================================
490
+
491
+ const usersCmd = program
492
+ .command('users')
493
+ .description('User commands');
494
+
495
+ usersCmd
496
+ .command('list')
497
+ .description('List users')
498
+ .option('-l, --limit <n>', 'Maximum number to return', '100')
499
+ .option('--all', 'Include inactive users')
500
+ .action(async (opts) => {
501
+ try {
502
+ const client = getClient();
503
+ const format = program.opts().format as OutputFormat;
504
+
505
+ let users;
506
+ if (opts.all) {
507
+ users = await client.users.list({ first: parseInt(opts.limit, 10) });
508
+ } else {
509
+ users = await client.users.listActive({ first: parseInt(opts.limit, 10) });
510
+ }
511
+
512
+ if (format === 'json') {
513
+ print(users, format);
514
+ } else {
515
+ print(users.map(u => ({
516
+ id: u.id,
517
+ name: u.name,
518
+ displayName: u.displayName,
519
+ email: u.email,
520
+ admin: u.admin ? 'yes' : 'no',
521
+ active: u.active ? 'yes' : 'no',
522
+ })), format);
523
+ }
524
+ } catch (e) {
525
+ error((e as Error).message);
526
+ process.exit(1);
527
+ }
528
+ });
529
+
530
+ usersCmd
531
+ .command('get <id>')
532
+ .description('Get user details')
533
+ .action(async (id: string) => {
534
+ try {
535
+ const client = getClient();
536
+ const format = program.opts().format as OutputFormat;
537
+ const user = await client.users.get(id);
538
+ print(user, format);
539
+ } catch (e) {
540
+ error((e as Error).message);
541
+ process.exit(1);
542
+ }
543
+ });
544
+
545
+ usersCmd
546
+ .command('me')
547
+ .description('Show current authenticated user')
548
+ .action(async () => {
549
+ try {
550
+ const client = getClient();
551
+ const format = program.opts().format as OutputFormat;
552
+ const user = await client.users.me();
553
+ print(user, format);
554
+ } catch (e) {
555
+ error((e as Error).message);
556
+ process.exit(1);
557
+ }
558
+ });
559
+
560
+ program.parse();
@@ -0,0 +1,27 @@
1
+ // Main library exports
2
+ export { Linear, LinearClient, IssuesApi, ProjectsApi, TeamsApi, UsersApi } from './api';
3
+
4
+ // Type exports
5
+ export type {
6
+ LinearConfig,
7
+ LinearUser,
8
+ LinearTeam,
9
+ LinearIssue,
10
+ LinearProject,
11
+ LinearComment,
12
+ LinearCycle,
13
+ LinearLabel,
14
+ LinearWorkflowState,
15
+ LinearPriority,
16
+ GraphQLResponse,
17
+ Connection,
18
+ PageInfo,
19
+ ListOptions,
20
+ IssueListOptions,
21
+ IssueFilter,
22
+ CreateIssueInput,
23
+ UpdateIssueInput,
24
+ OutputFormat,
25
+ } from './types';
26
+
27
+ export { LinearApiError } from './types';