linear-cli-agents 0.2.1 → 0.4.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.
Files changed (79) hide show
  1. package/README.md +166 -3
  2. package/bin/dev.js +0 -0
  3. package/dist/commands/comments/add.d.ts +13 -0
  4. package/dist/commands/comments/add.js +89 -0
  5. package/dist/commands/comments/delete.d.ts +12 -0
  6. package/dist/commands/comments/delete.js +50 -0
  7. package/dist/commands/comments/list.d.ts +14 -0
  8. package/dist/commands/comments/list.js +103 -0
  9. package/dist/commands/comments/update.d.ts +13 -0
  10. package/dist/commands/comments/update.js +81 -0
  11. package/dist/commands/issues/add-labels.d.ts +13 -0
  12. package/dist/commands/issues/add-labels.js +90 -0
  13. package/dist/commands/issues/archive.d.ts +13 -0
  14. package/dist/commands/issues/archive.js +83 -0
  15. package/dist/commands/issues/remove-labels.d.ts +13 -0
  16. package/dist/commands/issues/remove-labels.js +90 -0
  17. package/dist/commands/labels/create.d.ts +14 -0
  18. package/dist/commands/labels/create.js +102 -0
  19. package/dist/commands/labels/delete.d.ts +12 -0
  20. package/dist/commands/labels/delete.js +50 -0
  21. package/dist/commands/labels/list.d.ts +12 -0
  22. package/dist/commands/labels/list.js +117 -0
  23. package/dist/commands/labels/update.d.ts +16 -0
  24. package/dist/commands/labels/update.js +109 -0
  25. package/dist/commands/me.js +1 -5
  26. package/dist/commands/milestones/create.d.ts +15 -0
  27. package/dist/commands/milestones/create.js +90 -0
  28. package/dist/commands/milestones/get.d.ts +12 -0
  29. package/dist/commands/milestones/get.js +74 -0
  30. package/dist/commands/milestones/list.d.ts +14 -0
  31. package/dist/commands/milestones/list.js +97 -0
  32. package/dist/commands/milestones/update.d.ts +15 -0
  33. package/dist/commands/milestones/update.js +94 -0
  34. package/dist/commands/project-updates/create.d.ts +14 -0
  35. package/dist/commands/project-updates/create.js +96 -0
  36. package/dist/commands/project-updates/get.d.ts +12 -0
  37. package/dist/commands/project-updates/get.js +80 -0
  38. package/dist/commands/project-updates/list.d.ts +14 -0
  39. package/dist/commands/project-updates/list.js +120 -0
  40. package/dist/commands/project-updates/update.d.ts +14 -0
  41. package/dist/commands/project-updates/update.js +96 -0
  42. package/dist/commands/projects/archive.d.ts +13 -0
  43. package/dist/commands/projects/archive.js +79 -0
  44. package/dist/commands/projects/create.d.ts +16 -0
  45. package/dist/commands/projects/create.js +115 -0
  46. package/dist/commands/projects/delete.d.ts +12 -0
  47. package/dist/commands/projects/delete.js +50 -0
  48. package/dist/commands/projects/get.d.ts +12 -0
  49. package/dist/commands/projects/get.js +102 -0
  50. package/dist/commands/projects/list.d.ts +13 -0
  51. package/dist/commands/projects/list.js +141 -0
  52. package/dist/commands/projects/update.d.ts +18 -0
  53. package/dist/commands/projects/update.js +125 -0
  54. package/dist/commands/relations/create.d.ts +14 -0
  55. package/dist/commands/relations/create.js +98 -0
  56. package/dist/commands/relations/delete.d.ts +12 -0
  57. package/dist/commands/relations/delete.js +47 -0
  58. package/dist/commands/relations/list.d.ts +12 -0
  59. package/dist/commands/relations/list.js +128 -0
  60. package/dist/commands/search.d.ts +15 -0
  61. package/dist/commands/search.js +102 -0
  62. package/dist/commands/states/list.d.ts +12 -0
  63. package/dist/commands/states/list.js +151 -0
  64. package/dist/commands/teams/list.js +1 -1
  65. package/dist/commands/templates/create.d.ts +14 -0
  66. package/dist/commands/templates/create.js +102 -0
  67. package/dist/commands/templates/get.d.ts +12 -0
  68. package/dist/commands/templates/get.js +84 -0
  69. package/dist/commands/templates/list.d.ts +12 -0
  70. package/dist/commands/templates/list.js +110 -0
  71. package/dist/commands/templates/update.d.ts +15 -0
  72. package/dist/commands/templates/update.js +101 -0
  73. package/dist/commands/users/get.d.ts +12 -0
  74. package/dist/commands/users/get.js +91 -0
  75. package/dist/commands/users/list.d.ts +12 -0
  76. package/dist/commands/users/list.js +99 -0
  77. package/dist/lib/config.js +1 -1
  78. package/oclif.manifest.json +2402 -189
  79. package/package.json +47 -17
@@ -0,0 +1,13 @@
1
+ import { Command } from '@oclif/core';
2
+ export default class IssuesArchive extends Command {
3
+ static description: string;
4
+ static examples: string[];
5
+ static args: {
6
+ id: import("@oclif/core/interfaces").Arg<string, Record<string, unknown>>;
7
+ };
8
+ static flags: {
9
+ format: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
10
+ unarchive: import("@oclif/core/interfaces").BooleanFlag<boolean>;
11
+ };
12
+ run(): Promise<void>;
13
+ }
@@ -0,0 +1,83 @@
1
+ import { Args, Command, Flags } from '@oclif/core';
2
+ import { getClient } from '../../lib/client.js';
3
+ import { success, print, printItem } from '../../lib/output.js';
4
+ import { handleError, CliError, ErrorCodes } from '../../lib/errors.js';
5
+ import { resolveIssueId } from '../../lib/issue-utils.js';
6
+ export default class IssuesArchive extends Command {
7
+ static description = 'Archive an issue';
8
+ static examples = [
9
+ '<%= config.bin %> issues archive ENG-123',
10
+ '<%= config.bin %> issues archive ENG-123 --unarchive',
11
+ ];
12
+ static args = {
13
+ id: Args.string({
14
+ description: 'Issue ID or identifier (e.g., ENG-123)',
15
+ required: true,
16
+ }),
17
+ };
18
+ static flags = {
19
+ format: Flags.string({
20
+ char: 'F',
21
+ description: 'Output format',
22
+ options: ['json', 'table', 'plain'],
23
+ default: 'json',
24
+ }),
25
+ unarchive: Flags.boolean({
26
+ char: 'u',
27
+ description: 'Unarchive instead of archive',
28
+ default: false,
29
+ }),
30
+ };
31
+ async run() {
32
+ try {
33
+ const { args, flags } = await this.parse(IssuesArchive);
34
+ const format = flags.format;
35
+ const client = getClient();
36
+ const issueId = await resolveIssueId(client, args.id);
37
+ let payload;
38
+ if (flags.unarchive) {
39
+ payload = await client.unarchiveIssue(issueId);
40
+ }
41
+ else {
42
+ payload = await client.archiveIssue(issueId);
43
+ }
44
+ if (!payload.success) {
45
+ const action = flags.unarchive ? 'unarchive' : 'archive';
46
+ throw new CliError(ErrorCodes.API_ERROR, `Failed to ${action} issue`);
47
+ }
48
+ const issue = await payload.issue;
49
+ if (!issue) {
50
+ throw new CliError(ErrorCodes.API_ERROR, 'Issue not found in response');
51
+ }
52
+ const action = flags.unarchive ? 'unarchived' : 'archived';
53
+ const data = {
54
+ id: issue.id,
55
+ identifier: issue.identifier,
56
+ title: issue.title,
57
+ action,
58
+ archivedAt: issue.archivedAt,
59
+ url: issue.url,
60
+ };
61
+ if (format === 'json') {
62
+ print(success(data));
63
+ }
64
+ else if (format === 'table') {
65
+ printItem({
66
+ id: data.id,
67
+ identifier: data.identifier,
68
+ title: data.title,
69
+ action: data.action,
70
+ archivedAt: data.archivedAt ?? 'N/A',
71
+ url: data.url,
72
+ }, format);
73
+ }
74
+ else {
75
+ console.log(data.identifier);
76
+ }
77
+ }
78
+ catch (err) {
79
+ handleError(err);
80
+ this.exit(1);
81
+ }
82
+ }
83
+ }
@@ -0,0 +1,13 @@
1
+ import { Command } from '@oclif/core';
2
+ export default class IssuesRemoveLabels extends Command {
3
+ static description: string;
4
+ static examples: string[];
5
+ static args: {
6
+ id: import("@oclif/core/interfaces").Arg<string, Record<string, unknown>>;
7
+ };
8
+ static flags: {
9
+ format: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
10
+ 'label-ids': import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
11
+ };
12
+ run(): Promise<void>;
13
+ }
@@ -0,0 +1,90 @@
1
+ import { Args, Command, Flags } from '@oclif/core';
2
+ import { getClient } from '../../lib/client.js';
3
+ import { success, print, printItem } from '../../lib/output.js';
4
+ import { handleError, CliError, ErrorCodes } from '../../lib/errors.js';
5
+ import { resolveIssueId } from '../../lib/issue-utils.js';
6
+ export default class IssuesRemoveLabels extends Command {
7
+ static description = 'Remove labels from an issue';
8
+ static examples = ['<%= config.bin %> issues remove-labels ENG-123 --label-ids LABEL_ID1,LABEL_ID2'];
9
+ static args = {
10
+ id: Args.string({
11
+ description: 'Issue ID or identifier (e.g., ENG-123)',
12
+ required: true,
13
+ }),
14
+ };
15
+ static flags = {
16
+ format: Flags.string({
17
+ char: 'F',
18
+ description: 'Output format',
19
+ options: ['json', 'table', 'plain'],
20
+ default: 'json',
21
+ }),
22
+ 'label-ids': Flags.string({
23
+ description: 'Comma-separated label IDs to remove',
24
+ required: true,
25
+ }),
26
+ };
27
+ async run() {
28
+ try {
29
+ const { args, flags } = await this.parse(IssuesRemoveLabels);
30
+ const format = flags.format;
31
+ const client = getClient();
32
+ const issueId = await resolveIssueId(client, args.id);
33
+ const issue = await client.issue(issueId);
34
+ if (!issue) {
35
+ throw new CliError(ErrorCodes.NOT_FOUND, `Issue ${args.id} not found`);
36
+ }
37
+ // Get existing labels
38
+ const existingLabels = await issue.labels();
39
+ const existingLabelIds = existingLabels.nodes.map((l) => l.id);
40
+ // Parse label IDs to remove
41
+ const labelIdsToRemove = flags['label-ids'].split(',').map((id) => id.trim());
42
+ // Filter out the labels to remove
43
+ const remainingLabelIds = existingLabelIds.filter((id) => !labelIdsToRemove.includes(id));
44
+ // Update the issue with remaining labels
45
+ const payload = await client.updateIssue(issueId, {
46
+ labelIds: remainingLabelIds,
47
+ });
48
+ if (!payload.success) {
49
+ throw new CliError(ErrorCodes.API_ERROR, 'Failed to remove labels from issue');
50
+ }
51
+ const updatedIssue = await payload.issue;
52
+ if (!updatedIssue) {
53
+ throw new CliError(ErrorCodes.API_ERROR, 'Issue not found in response');
54
+ }
55
+ const labels = await updatedIssue.labels();
56
+ const data = {
57
+ id: updatedIssue.id,
58
+ identifier: updatedIssue.identifier,
59
+ title: updatedIssue.title,
60
+ labels: labels.nodes.map((l) => ({
61
+ id: l.id,
62
+ name: l.name,
63
+ color: l.color,
64
+ })),
65
+ labelsRemoved: labelIdsToRemove.filter((id) => existingLabelIds.includes(id)),
66
+ url: updatedIssue.url,
67
+ };
68
+ if (format === 'json') {
69
+ print(success(data));
70
+ }
71
+ else if (format === 'table') {
72
+ printItem({
73
+ id: data.id,
74
+ identifier: data.identifier,
75
+ title: data.title,
76
+ labels: data.labels.map((l) => l.name).join(', ') || 'None',
77
+ labelsRemoved: data.labelsRemoved.length,
78
+ url: data.url,
79
+ }, format);
80
+ }
81
+ else {
82
+ console.log(data.identifier);
83
+ }
84
+ }
85
+ catch (err) {
86
+ handleError(err);
87
+ this.exit(1);
88
+ }
89
+ }
90
+ }
@@ -0,0 +1,14 @@
1
+ import { Command } from '@oclif/core';
2
+ export default class LabelsCreate extends Command {
3
+ static description: string;
4
+ static examples: string[];
5
+ static flags: {
6
+ format: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
7
+ name: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
8
+ color: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
9
+ description: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
10
+ 'team-id': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
11
+ 'parent-id': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
12
+ };
13
+ run(): Promise<void>;
14
+ }
@@ -0,0 +1,102 @@
1
+ import { Command, Flags } from '@oclif/core';
2
+ import { getClient } from '../../lib/client.js';
3
+ import { success, print, printItem } from '../../lib/output.js';
4
+ import { handleError, CliError, ErrorCodes } from '../../lib/errors.js';
5
+ export default class LabelsCreate extends Command {
6
+ static description = 'Create a label';
7
+ static examples = [
8
+ '<%= config.bin %> labels create --name "Bug" --color "#FF0000"',
9
+ '<%= config.bin %> labels create --name "Feature" --color "#00FF00" --description "New feature requests"',
10
+ '<%= config.bin %> labels create --name "Backend" --color "#0000FF" --team-id TEAM_ID',
11
+ '<%= config.bin %> labels create --name "API" --color "#FF00FF" --parent-id PARENT_LABEL_ID',
12
+ ];
13
+ static flags = {
14
+ format: Flags.string({
15
+ char: 'F',
16
+ description: 'Output format',
17
+ options: ['json', 'table', 'plain'],
18
+ default: 'json',
19
+ }),
20
+ name: Flags.string({
21
+ char: 'n',
22
+ description: 'Label name',
23
+ required: true,
24
+ }),
25
+ color: Flags.string({
26
+ char: 'c',
27
+ description: 'Label color (hex, e.g., #FF0000)',
28
+ required: true,
29
+ }),
30
+ description: Flags.string({
31
+ char: 'd',
32
+ description: 'Label description',
33
+ }),
34
+ 'team-id': Flags.string({
35
+ description: 'Team ID (for team-specific labels)',
36
+ }),
37
+ 'parent-id': Flags.string({
38
+ description: 'Parent label ID (for nested labels)',
39
+ }),
40
+ };
41
+ async run() {
42
+ try {
43
+ const { flags } = await this.parse(LabelsCreate);
44
+ const format = flags.format;
45
+ const client = getClient();
46
+ const payload = await client.createIssueLabel({
47
+ name: flags.name,
48
+ color: flags.color,
49
+ description: flags.description,
50
+ teamId: flags['team-id'],
51
+ parentId: flags['parent-id'],
52
+ });
53
+ if (!payload.success || !payload.issueLabel) {
54
+ throw new CliError(ErrorCodes.API_ERROR, 'Failed to create label');
55
+ }
56
+ const label = await payload.issueLabel;
57
+ const [team, parent] = await Promise.all([label.team, label.parent]);
58
+ const data = {
59
+ id: label.id,
60
+ name: label.name,
61
+ color: label.color,
62
+ description: label.description,
63
+ isGroup: label.isGroup,
64
+ team: team
65
+ ? {
66
+ id: team.id,
67
+ key: team.key,
68
+ name: team.name,
69
+ }
70
+ : null,
71
+ parent: parent
72
+ ? {
73
+ id: parent.id,
74
+ name: parent.name,
75
+ }
76
+ : null,
77
+ createdAt: label.createdAt,
78
+ };
79
+ if (format === 'json') {
80
+ print(success(data));
81
+ }
82
+ else if (format === 'table') {
83
+ printItem({
84
+ id: data.id,
85
+ name: data.name,
86
+ color: data.color,
87
+ description: data.description ?? 'N/A',
88
+ team: data.team?.key ?? 'Workspace',
89
+ parent: data.parent?.name ?? 'N/A',
90
+ createdAt: data.createdAt,
91
+ }, format);
92
+ }
93
+ else {
94
+ console.log(data.id);
95
+ }
96
+ }
97
+ catch (err) {
98
+ handleError(err);
99
+ this.exit(1);
100
+ }
101
+ }
102
+ }
@@ -0,0 +1,12 @@
1
+ import { Command } from '@oclif/core';
2
+ export default class LabelsDelete extends Command {
3
+ static description: string;
4
+ static examples: string[];
5
+ static args: {
6
+ id: import("@oclif/core/interfaces").Arg<string, Record<string, unknown>>;
7
+ };
8
+ static flags: {
9
+ format: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
10
+ };
11
+ run(): Promise<void>;
12
+ }
@@ -0,0 +1,50 @@
1
+ import { Args, Command, Flags } from '@oclif/core';
2
+ import { getClient } from '../../lib/client.js';
3
+ import { success, print } from '../../lib/output.js';
4
+ import { handleError, CliError, ErrorCodes } from '../../lib/errors.js';
5
+ export default class LabelsDelete extends Command {
6
+ static description = 'Delete a label';
7
+ static examples = ['<%= config.bin %> labels delete LABEL_ID'];
8
+ static args = {
9
+ id: Args.string({
10
+ description: 'Label ID',
11
+ required: true,
12
+ }),
13
+ };
14
+ static flags = {
15
+ format: Flags.string({
16
+ char: 'F',
17
+ description: 'Output format',
18
+ options: ['json', 'table', 'plain'],
19
+ default: 'json',
20
+ }),
21
+ };
22
+ async run() {
23
+ try {
24
+ const { args, flags } = await this.parse(LabelsDelete);
25
+ const format = flags.format;
26
+ const client = getClient();
27
+ const payload = await client.deleteIssueLabel(args.id);
28
+ if (!payload.success) {
29
+ throw new CliError(ErrorCodes.API_ERROR, 'Failed to delete label');
30
+ }
31
+ const data = {
32
+ id: args.id,
33
+ deleted: true,
34
+ };
35
+ if (format === 'json') {
36
+ print(success(data));
37
+ }
38
+ else if (format === 'table') {
39
+ console.log(`Label ${args.id} deleted successfully`);
40
+ }
41
+ else {
42
+ console.log(args.id);
43
+ }
44
+ }
45
+ catch (err) {
46
+ handleError(err);
47
+ this.exit(1);
48
+ }
49
+ }
50
+ }
@@ -0,0 +1,12 @@
1
+ import { Command } from '@oclif/core';
2
+ export default class LabelsList extends Command {
3
+ static description: string;
4
+ static examples: string[];
5
+ static flags: {
6
+ format: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
7
+ team: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
8
+ first: import("@oclif/core/interfaces").OptionFlag<number, import("@oclif/core/interfaces").CustomOptions>;
9
+ after: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
10
+ };
11
+ run(): Promise<void>;
12
+ }
@@ -0,0 +1,117 @@
1
+ import { Command, Flags } from '@oclif/core';
2
+ import { getClient } from '../../lib/client.js';
3
+ import { successList, print, printList } from '../../lib/output.js';
4
+ import { handleError } from '../../lib/errors.js';
5
+ import { colors, truncate } from '../../lib/formatter.js';
6
+ const COLUMNS = [
7
+ {
8
+ key: 'name',
9
+ header: 'NAME',
10
+ format: (value, row) => {
11
+ const name = String(value);
12
+ if (row.isGroup) {
13
+ return colors.bold(name) + colors.dim(' (group)');
14
+ }
15
+ return colors.bold(name);
16
+ },
17
+ },
18
+ {
19
+ key: 'color',
20
+ header: 'COLOR',
21
+ format: (value) => colors.dim(String(value)),
22
+ },
23
+ {
24
+ key: 'description',
25
+ header: 'DESCRIPTION',
26
+ format: (value) => truncate(String(value ?? ''), 40),
27
+ },
28
+ ];
29
+ export default class LabelsList extends Command {
30
+ static description = 'List labels in the workspace';
31
+ static examples = [
32
+ '<%= config.bin %> labels list',
33
+ '<%= config.bin %> labels list --format table',
34
+ '<%= config.bin %> labels list --team ENG',
35
+ ];
36
+ static flags = {
37
+ format: Flags.string({
38
+ char: 'F',
39
+ description: 'Output format',
40
+ options: ['json', 'table', 'plain'],
41
+ default: 'json',
42
+ }),
43
+ team: Flags.string({
44
+ char: 't',
45
+ description: 'Filter by team key (e.g., ENG)',
46
+ }),
47
+ first: Flags.integer({
48
+ description: 'Number of labels to fetch (default: 100)',
49
+ default: 100,
50
+ }),
51
+ after: Flags.string({
52
+ description: 'Cursor for pagination',
53
+ }),
54
+ };
55
+ async run() {
56
+ try {
57
+ const { flags } = await this.parse(LabelsList);
58
+ const format = flags.format;
59
+ const client = getClient();
60
+ let labels;
61
+ if (flags.team) {
62
+ // Fetch labels for a specific team
63
+ const teams = await client.teams({
64
+ filter: { key: { eq: flags.team } },
65
+ });
66
+ const team = teams.nodes[0];
67
+ if (!team) {
68
+ throw new Error(`Team ${flags.team} not found`);
69
+ }
70
+ labels = await team.labels({
71
+ first: flags.first,
72
+ after: flags.after,
73
+ });
74
+ }
75
+ else {
76
+ // Fetch all workspace labels (issueLabels returns workspace labels)
77
+ labels = await client.issueLabels({
78
+ first: flags.first,
79
+ after: flags.after,
80
+ });
81
+ }
82
+ const data = await Promise.all(labels.nodes.map(async (label) => {
83
+ const parent = await label.parent;
84
+ return {
85
+ id: label.id,
86
+ name: label.name,
87
+ color: label.color,
88
+ description: label.description ?? undefined,
89
+ isGroup: label.isGroup,
90
+ parentId: parent?.id,
91
+ createdAt: label.createdAt,
92
+ };
93
+ }));
94
+ const pageInfo = {
95
+ hasNextPage: labels.pageInfo.hasNextPage,
96
+ hasPreviousPage: labels.pageInfo.hasPreviousPage,
97
+ startCursor: labels.pageInfo.startCursor,
98
+ endCursor: labels.pageInfo.endCursor,
99
+ };
100
+ if (format === 'json') {
101
+ print(successList(data, pageInfo));
102
+ }
103
+ else {
104
+ printList(data, format, {
105
+ columns: COLUMNS,
106
+ primaryKey: 'name',
107
+ secondaryKey: 'description',
108
+ pageInfo,
109
+ });
110
+ }
111
+ }
112
+ catch (err) {
113
+ handleError(err);
114
+ this.exit(1);
115
+ }
116
+ }
117
+ }
@@ -0,0 +1,16 @@
1
+ import { Command } from '@oclif/core';
2
+ export default class LabelsUpdate extends Command {
3
+ static description: string;
4
+ static examples: string[];
5
+ static args: {
6
+ id: import("@oclif/core/interfaces").Arg<string, Record<string, unknown>>;
7
+ };
8
+ static flags: {
9
+ format: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
10
+ name: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
11
+ color: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
12
+ description: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
13
+ 'parent-id': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
14
+ };
15
+ run(): Promise<void>;
16
+ }
@@ -0,0 +1,109 @@
1
+ import { Args, Command, Flags } from '@oclif/core';
2
+ import { getClient } from '../../lib/client.js';
3
+ import { success, print, printItem } from '../../lib/output.js';
4
+ import { handleError, CliError, ErrorCodes } from '../../lib/errors.js';
5
+ export default class LabelsUpdate extends Command {
6
+ static description = 'Update a label';
7
+ static examples = [
8
+ '<%= config.bin %> labels update LABEL_ID --name "Updated Name"',
9
+ '<%= config.bin %> labels update LABEL_ID --color "#00FF00"',
10
+ '<%= config.bin %> labels update LABEL_ID --description "New description"',
11
+ ];
12
+ static args = {
13
+ id: Args.string({
14
+ description: 'Label ID',
15
+ required: true,
16
+ }),
17
+ };
18
+ static flags = {
19
+ format: Flags.string({
20
+ char: 'F',
21
+ description: 'Output format',
22
+ options: ['json', 'table', 'plain'],
23
+ default: 'json',
24
+ }),
25
+ name: Flags.string({
26
+ char: 'n',
27
+ description: 'Label name',
28
+ }),
29
+ color: Flags.string({
30
+ char: 'c',
31
+ description: 'Label color (hex, e.g., #FF0000)',
32
+ }),
33
+ description: Flags.string({
34
+ char: 'd',
35
+ description: 'Label description',
36
+ }),
37
+ 'parent-id': Flags.string({
38
+ description: 'Parent label ID',
39
+ }),
40
+ };
41
+ async run() {
42
+ try {
43
+ const { args, flags } = await this.parse(LabelsUpdate);
44
+ const format = flags.format;
45
+ const client = getClient();
46
+ const input = {};
47
+ if (flags.name)
48
+ input.name = flags.name;
49
+ if (flags.color)
50
+ input.color = flags.color;
51
+ if (flags.description)
52
+ input.description = flags.description;
53
+ if (flags['parent-id'])
54
+ input.parentId = flags['parent-id'];
55
+ if (Object.keys(input).length === 0) {
56
+ throw new CliError(ErrorCodes.INVALID_INPUT, 'At least one field to update is required');
57
+ }
58
+ const payload = await client.updateIssueLabel(args.id, input);
59
+ if (!payload.success || !payload.issueLabel) {
60
+ throw new CliError(ErrorCodes.API_ERROR, 'Failed to update label');
61
+ }
62
+ const label = await payload.issueLabel;
63
+ const [team, parent] = await Promise.all([label.team, label.parent]);
64
+ const data = {
65
+ id: label.id,
66
+ name: label.name,
67
+ color: label.color,
68
+ description: label.description,
69
+ isGroup: label.isGroup,
70
+ team: team
71
+ ? {
72
+ id: team.id,
73
+ key: team.key,
74
+ name: team.name,
75
+ }
76
+ : null,
77
+ parent: parent
78
+ ? {
79
+ id: parent.id,
80
+ name: parent.name,
81
+ }
82
+ : null,
83
+ createdAt: label.createdAt,
84
+ updatedAt: label.updatedAt,
85
+ };
86
+ if (format === 'json') {
87
+ print(success(data));
88
+ }
89
+ else if (format === 'table') {
90
+ printItem({
91
+ id: data.id,
92
+ name: data.name,
93
+ color: data.color,
94
+ description: data.description ?? 'N/A',
95
+ team: data.team?.key ?? 'Workspace',
96
+ parent: data.parent?.name ?? 'N/A',
97
+ updatedAt: data.updatedAt,
98
+ }, format);
99
+ }
100
+ else {
101
+ console.log(data.id);
102
+ }
103
+ }
104
+ catch (err) {
105
+ handleError(err);
106
+ this.exit(1);
107
+ }
108
+ }
109
+ }
@@ -5,11 +5,7 @@ import { handleError } from '../lib/errors.js';
5
5
  export default class Me extends Command {
6
6
  static description = 'Show current user information';
7
7
  static aliases = ['whoami'];
8
- static examples = [
9
- '<%= config.bin %> me',
10
- '<%= config.bin %> me --format table',
11
- '<%= config.bin %> whoami',
12
- ];
8
+ static examples = ['<%= config.bin %> me', '<%= config.bin %> me --format table', '<%= config.bin %> whoami'];
13
9
  static flags = {
14
10
  format: Flags.string({
15
11
  char: 'F',
@@ -0,0 +1,15 @@
1
+ import { Command } from '@oclif/core';
2
+ export default class MilestonesCreate extends Command {
3
+ static description: string;
4
+ static examples: string[];
5
+ static args: {
6
+ projectId: import("@oclif/core/interfaces").Arg<string, Record<string, unknown>>;
7
+ };
8
+ static flags: {
9
+ format: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
10
+ name: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
11
+ description: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
12
+ 'target-date': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
13
+ };
14
+ run(): Promise<void>;
15
+ }