linear-cli-agents 0.2.0 → 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/README.md +253 -5
- package/bin/dev.js +0 -0
- package/dist/commands/comments/add.d.ts +13 -0
- package/dist/commands/comments/add.js +89 -0
- package/dist/commands/comments/delete.d.ts +12 -0
- package/dist/commands/comments/delete.js +50 -0
- package/dist/commands/comments/list.d.ts +14 -0
- package/dist/commands/comments/list.js +103 -0
- package/dist/commands/comments/update.d.ts +13 -0
- package/dist/commands/comments/update.js +81 -0
- package/dist/commands/issues/add-labels.d.ts +13 -0
- package/dist/commands/issues/add-labels.js +90 -0
- package/dist/commands/issues/archive.d.ts +13 -0
- package/dist/commands/issues/archive.js +83 -0
- package/dist/commands/issues/remove-labels.d.ts +13 -0
- package/dist/commands/issues/remove-labels.js +90 -0
- package/dist/commands/labels/create.d.ts +14 -0
- package/dist/commands/labels/create.js +102 -0
- package/dist/commands/labels/delete.d.ts +12 -0
- package/dist/commands/labels/delete.js +50 -0
- package/dist/commands/labels/list.d.ts +12 -0
- package/dist/commands/labels/list.js +117 -0
- package/dist/commands/labels/update.d.ts +16 -0
- package/dist/commands/labels/update.js +109 -0
- package/dist/commands/me.js +1 -5
- package/dist/commands/milestones/create.d.ts +15 -0
- package/dist/commands/milestones/create.js +90 -0
- package/dist/commands/milestones/get.d.ts +12 -0
- package/dist/commands/milestones/get.js +74 -0
- package/dist/commands/milestones/list.d.ts +14 -0
- package/dist/commands/milestones/list.js +97 -0
- package/dist/commands/milestones/update.d.ts +15 -0
- package/dist/commands/milestones/update.js +94 -0
- package/dist/commands/project-updates/create.d.ts +14 -0
- package/dist/commands/project-updates/create.js +96 -0
- package/dist/commands/project-updates/get.d.ts +12 -0
- package/dist/commands/project-updates/get.js +80 -0
- package/dist/commands/project-updates/list.d.ts +14 -0
- package/dist/commands/project-updates/list.js +120 -0
- package/dist/commands/project-updates/update.d.ts +14 -0
- package/dist/commands/project-updates/update.js +96 -0
- package/dist/commands/projects/archive.d.ts +13 -0
- package/dist/commands/projects/archive.js +79 -0
- package/dist/commands/projects/create.d.ts +16 -0
- package/dist/commands/projects/create.js +115 -0
- package/dist/commands/projects/delete.d.ts +12 -0
- package/dist/commands/projects/delete.js +50 -0
- package/dist/commands/projects/get.d.ts +12 -0
- package/dist/commands/projects/get.js +102 -0
- package/dist/commands/projects/list.d.ts +13 -0
- package/dist/commands/projects/list.js +141 -0
- package/dist/commands/projects/update.d.ts +18 -0
- package/dist/commands/projects/update.js +125 -0
- package/dist/commands/relations/create.d.ts +14 -0
- package/dist/commands/relations/create.js +98 -0
- package/dist/commands/relations/delete.d.ts +12 -0
- package/dist/commands/relations/delete.js +47 -0
- package/dist/commands/relations/list.d.ts +12 -0
- package/dist/commands/relations/list.js +128 -0
- package/dist/commands/search.d.ts +15 -0
- package/dist/commands/search.js +102 -0
- package/dist/commands/states/list.d.ts +12 -0
- package/dist/commands/states/list.js +151 -0
- package/dist/commands/templates/create.d.ts +14 -0
- package/dist/commands/templates/create.js +102 -0
- package/dist/commands/templates/get.d.ts +12 -0
- package/dist/commands/templates/get.js +84 -0
- package/dist/commands/templates/list.d.ts +12 -0
- package/dist/commands/templates/list.js +110 -0
- package/dist/commands/templates/update.d.ts +15 -0
- package/dist/commands/templates/update.js +101 -0
- package/dist/commands/users/get.d.ts +12 -0
- package/dist/commands/users/get.js +91 -0
- package/dist/commands/users/list.d.ts +12 -0
- package/dist/commands/users/list.js +99 -0
- package/dist/lib/config.js +1 -1
- package/oclif.manifest.json +2397 -184
- package/package.json +47 -17
|
@@ -0,0 +1,80 @@
|
|
|
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 ProjectUpdatesGet extends Command {
|
|
6
|
+
static description = 'Get a project update by ID';
|
|
7
|
+
static examples = [
|
|
8
|
+
'<%= config.bin %> project-updates get UPDATE_ID',
|
|
9
|
+
'<%= config.bin %> project-updates get UPDATE_ID --format table',
|
|
10
|
+
];
|
|
11
|
+
static args = {
|
|
12
|
+
id: Args.string({
|
|
13
|
+
description: 'Project update ID',
|
|
14
|
+
required: true,
|
|
15
|
+
}),
|
|
16
|
+
};
|
|
17
|
+
static flags = {
|
|
18
|
+
format: Flags.string({
|
|
19
|
+
char: 'F',
|
|
20
|
+
description: 'Output format',
|
|
21
|
+
options: ['json', 'table', 'plain'],
|
|
22
|
+
default: 'json',
|
|
23
|
+
}),
|
|
24
|
+
};
|
|
25
|
+
async run() {
|
|
26
|
+
try {
|
|
27
|
+
const { args, flags } = await this.parse(ProjectUpdatesGet);
|
|
28
|
+
const format = flags.format;
|
|
29
|
+
const client = getClient();
|
|
30
|
+
const update = await client.projectUpdate(args.id);
|
|
31
|
+
if (!update) {
|
|
32
|
+
throw new CliError(ErrorCodes.NOT_FOUND, `Project update ${args.id} not found`);
|
|
33
|
+
}
|
|
34
|
+
const [project, user] = await Promise.all([update.project, update.user]);
|
|
35
|
+
const data = {
|
|
36
|
+
id: update.id,
|
|
37
|
+
body: update.body,
|
|
38
|
+
health: update.health,
|
|
39
|
+
url: update.url,
|
|
40
|
+
project: project
|
|
41
|
+
? {
|
|
42
|
+
id: project.id,
|
|
43
|
+
name: project.name,
|
|
44
|
+
}
|
|
45
|
+
: null,
|
|
46
|
+
user: user
|
|
47
|
+
? {
|
|
48
|
+
id: user.id,
|
|
49
|
+
name: user.name,
|
|
50
|
+
email: user.email,
|
|
51
|
+
}
|
|
52
|
+
: null,
|
|
53
|
+
createdAt: update.createdAt,
|
|
54
|
+
updatedAt: update.updatedAt,
|
|
55
|
+
};
|
|
56
|
+
if (format === 'json') {
|
|
57
|
+
print(success(data));
|
|
58
|
+
}
|
|
59
|
+
else if (format === 'table') {
|
|
60
|
+
printItem({
|
|
61
|
+
id: data.id,
|
|
62
|
+
project: data.project?.name ?? 'N/A',
|
|
63
|
+
health: data.health,
|
|
64
|
+
body: data.body,
|
|
65
|
+
user: data.user?.name ?? 'Unknown',
|
|
66
|
+
url: data.url,
|
|
67
|
+
createdAt: data.createdAt,
|
|
68
|
+
updatedAt: data.updatedAt,
|
|
69
|
+
}, format);
|
|
70
|
+
}
|
|
71
|
+
else {
|
|
72
|
+
console.log(data.id);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
catch (err) {
|
|
76
|
+
handleError(err);
|
|
77
|
+
this.exit(1);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { Command } from '@oclif/core';
|
|
2
|
+
export default class ProjectUpdatesList 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
|
+
first: import("@oclif/core/interfaces").OptionFlag<number, import("@oclif/core/interfaces").CustomOptions>;
|
|
11
|
+
after: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
12
|
+
};
|
|
13
|
+
run(): Promise<void>;
|
|
14
|
+
}
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import { Args, Command, Flags } from '@oclif/core';
|
|
2
|
+
import { getClient } from '../../lib/client.js';
|
|
3
|
+
import { successList, print, printList } from '../../lib/output.js';
|
|
4
|
+
import { handleError, CliError, ErrorCodes } from '../../lib/errors.js';
|
|
5
|
+
import { colors, truncate } from '../../lib/formatter.js';
|
|
6
|
+
const formatHealth = (health) => {
|
|
7
|
+
switch (health) {
|
|
8
|
+
case 'onTrack':
|
|
9
|
+
return colors.green('On Track');
|
|
10
|
+
case 'atRisk':
|
|
11
|
+
return colors.yellow('At Risk');
|
|
12
|
+
case 'offTrack':
|
|
13
|
+
return colors.red('Off Track');
|
|
14
|
+
default:
|
|
15
|
+
return health;
|
|
16
|
+
}
|
|
17
|
+
};
|
|
18
|
+
const COLUMNS = [
|
|
19
|
+
{
|
|
20
|
+
key: 'projectName',
|
|
21
|
+
header: 'PROJECT',
|
|
22
|
+
format: (value) => colors.cyan(truncate(String(value), 20)),
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
key: 'health',
|
|
26
|
+
header: 'HEALTH',
|
|
27
|
+
format: (value) => formatHealth(String(value)),
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
key: 'userName',
|
|
31
|
+
header: 'BY',
|
|
32
|
+
format: (value) => colors.dim(String(value)),
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
key: 'createdAt',
|
|
36
|
+
header: 'DATE',
|
|
37
|
+
format: (value) => {
|
|
38
|
+
const date = new Date(value);
|
|
39
|
+
return colors.dim(date.toLocaleDateString());
|
|
40
|
+
},
|
|
41
|
+
},
|
|
42
|
+
];
|
|
43
|
+
export default class ProjectUpdatesList extends Command {
|
|
44
|
+
static description = 'List project updates';
|
|
45
|
+
static examples = [
|
|
46
|
+
'<%= config.bin %> project-updates list PROJECT_ID',
|
|
47
|
+
'<%= config.bin %> project-updates list PROJECT_ID --format table',
|
|
48
|
+
];
|
|
49
|
+
static args = {
|
|
50
|
+
projectId: Args.string({
|
|
51
|
+
description: 'Project ID',
|
|
52
|
+
required: true,
|
|
53
|
+
}),
|
|
54
|
+
};
|
|
55
|
+
static flags = {
|
|
56
|
+
format: Flags.string({
|
|
57
|
+
char: 'F',
|
|
58
|
+
description: 'Output format',
|
|
59
|
+
options: ['json', 'table', 'plain'],
|
|
60
|
+
default: 'json',
|
|
61
|
+
}),
|
|
62
|
+
first: Flags.integer({
|
|
63
|
+
description: 'Number of updates to fetch (default: 20)',
|
|
64
|
+
default: 20,
|
|
65
|
+
}),
|
|
66
|
+
after: Flags.string({
|
|
67
|
+
description: 'Cursor for pagination',
|
|
68
|
+
}),
|
|
69
|
+
};
|
|
70
|
+
async run() {
|
|
71
|
+
try {
|
|
72
|
+
const { args, flags } = await this.parse(ProjectUpdatesList);
|
|
73
|
+
const format = flags.format;
|
|
74
|
+
const client = getClient();
|
|
75
|
+
const project = await client.project(args.projectId);
|
|
76
|
+
if (!project) {
|
|
77
|
+
throw new CliError(ErrorCodes.NOT_FOUND, `Project ${args.projectId} not found`);
|
|
78
|
+
}
|
|
79
|
+
const updates = await project.projectUpdates({
|
|
80
|
+
first: flags.first,
|
|
81
|
+
after: flags.after,
|
|
82
|
+
});
|
|
83
|
+
const data = await Promise.all(updates.nodes.map(async (update) => {
|
|
84
|
+
const user = await update.user;
|
|
85
|
+
return {
|
|
86
|
+
id: update.id,
|
|
87
|
+
body: update.body,
|
|
88
|
+
health: update.health,
|
|
89
|
+
projectId: project.id,
|
|
90
|
+
projectName: project.name,
|
|
91
|
+
userId: user?.id ?? '',
|
|
92
|
+
userName: user?.name ?? 'Unknown',
|
|
93
|
+
createdAt: update.createdAt,
|
|
94
|
+
updatedAt: update.updatedAt,
|
|
95
|
+
};
|
|
96
|
+
}));
|
|
97
|
+
const pageInfo = {
|
|
98
|
+
hasNextPage: updates.pageInfo.hasNextPage,
|
|
99
|
+
hasPreviousPage: updates.pageInfo.hasPreviousPage,
|
|
100
|
+
startCursor: updates.pageInfo.startCursor,
|
|
101
|
+
endCursor: updates.pageInfo.endCursor,
|
|
102
|
+
};
|
|
103
|
+
if (format === 'json') {
|
|
104
|
+
print(successList(data, pageInfo));
|
|
105
|
+
}
|
|
106
|
+
else {
|
|
107
|
+
printList(data, format, {
|
|
108
|
+
columns: COLUMNS,
|
|
109
|
+
primaryKey: 'id',
|
|
110
|
+
secondaryKey: 'body',
|
|
111
|
+
pageInfo,
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
catch (err) {
|
|
116
|
+
handleError(err);
|
|
117
|
+
this.exit(1);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { Command } from '@oclif/core';
|
|
2
|
+
export default class ProjectUpdatesUpdate 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
|
+
body: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
11
|
+
health: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
12
|
+
};
|
|
13
|
+
run(): Promise<void>;
|
|
14
|
+
}
|
|
@@ -0,0 +1,96 @@
|
|
|
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
|
+
const HEALTH_OPTIONS = ['onTrack', 'atRisk', 'offTrack'];
|
|
6
|
+
export default class ProjectUpdatesUpdate extends Command {
|
|
7
|
+
static description = 'Update a project update';
|
|
8
|
+
static examples = [
|
|
9
|
+
'<%= config.bin %> project-updates update UPDATE_ID --body "Updated status"',
|
|
10
|
+
'<%= config.bin %> project-updates update UPDATE_ID --health offTrack',
|
|
11
|
+
];
|
|
12
|
+
static args = {
|
|
13
|
+
id: Args.string({
|
|
14
|
+
description: 'Project update 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
|
+
body: Flags.string({
|
|
26
|
+
char: 'b',
|
|
27
|
+
description: 'Update body (supports markdown)',
|
|
28
|
+
}),
|
|
29
|
+
health: Flags.string({
|
|
30
|
+
char: 'h',
|
|
31
|
+
description: 'Project health status',
|
|
32
|
+
options: [...HEALTH_OPTIONS],
|
|
33
|
+
}),
|
|
34
|
+
};
|
|
35
|
+
async run() {
|
|
36
|
+
try {
|
|
37
|
+
const { args, flags } = await this.parse(ProjectUpdatesUpdate);
|
|
38
|
+
const format = flags.format;
|
|
39
|
+
const client = getClient();
|
|
40
|
+
const input = {};
|
|
41
|
+
if (flags.body)
|
|
42
|
+
input.body = flags.body;
|
|
43
|
+
if (flags.health)
|
|
44
|
+
input.health = flags.health;
|
|
45
|
+
if (Object.keys(input).length === 0) {
|
|
46
|
+
throw new CliError(ErrorCodes.INVALID_INPUT, 'At least one field to update is required');
|
|
47
|
+
}
|
|
48
|
+
const payload = await client.updateProjectUpdate(args.id, input);
|
|
49
|
+
if (!payload.success || !payload.projectUpdate) {
|
|
50
|
+
throw new CliError(ErrorCodes.API_ERROR, 'Failed to update project update');
|
|
51
|
+
}
|
|
52
|
+
const update = await payload.projectUpdate;
|
|
53
|
+
const [project, user] = await Promise.all([update.project, update.user]);
|
|
54
|
+
const data = {
|
|
55
|
+
id: update.id,
|
|
56
|
+
body: update.body,
|
|
57
|
+
health: update.health,
|
|
58
|
+
url: update.url,
|
|
59
|
+
project: project
|
|
60
|
+
? {
|
|
61
|
+
id: project.id,
|
|
62
|
+
name: project.name,
|
|
63
|
+
}
|
|
64
|
+
: null,
|
|
65
|
+
user: user
|
|
66
|
+
? {
|
|
67
|
+
id: user.id,
|
|
68
|
+
name: user.name,
|
|
69
|
+
}
|
|
70
|
+
: null,
|
|
71
|
+
createdAt: update.createdAt,
|
|
72
|
+
updatedAt: update.updatedAt,
|
|
73
|
+
};
|
|
74
|
+
if (format === 'json') {
|
|
75
|
+
print(success(data));
|
|
76
|
+
}
|
|
77
|
+
else if (format === 'table') {
|
|
78
|
+
printItem({
|
|
79
|
+
id: data.id,
|
|
80
|
+
project: data.project?.name ?? 'N/A',
|
|
81
|
+
health: data.health,
|
|
82
|
+
body: data.body,
|
|
83
|
+
user: data.user?.name ?? 'Unknown',
|
|
84
|
+
updatedAt: data.updatedAt,
|
|
85
|
+
}, format);
|
|
86
|
+
}
|
|
87
|
+
else {
|
|
88
|
+
console.log(data.id);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
catch (err) {
|
|
92
|
+
handleError(err);
|
|
93
|
+
this.exit(1);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { Command } from '@oclif/core';
|
|
2
|
+
export default class ProjectsArchive 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,79 @@
|
|
|
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 ProjectsArchive extends Command {
|
|
6
|
+
static description = 'Archive a project';
|
|
7
|
+
static examples = [
|
|
8
|
+
'<%= config.bin %> projects archive PROJECT_ID',
|
|
9
|
+
'<%= config.bin %> projects archive PROJECT_ID --unarchive',
|
|
10
|
+
];
|
|
11
|
+
static args = {
|
|
12
|
+
id: Args.string({
|
|
13
|
+
description: 'Project ID',
|
|
14
|
+
required: true,
|
|
15
|
+
}),
|
|
16
|
+
};
|
|
17
|
+
static flags = {
|
|
18
|
+
format: Flags.string({
|
|
19
|
+
char: 'F',
|
|
20
|
+
description: 'Output format',
|
|
21
|
+
options: ['json', 'table', 'plain'],
|
|
22
|
+
default: 'json',
|
|
23
|
+
}),
|
|
24
|
+
unarchive: Flags.boolean({
|
|
25
|
+
char: 'u',
|
|
26
|
+
description: 'Unarchive instead of archive',
|
|
27
|
+
default: false,
|
|
28
|
+
}),
|
|
29
|
+
};
|
|
30
|
+
async run() {
|
|
31
|
+
try {
|
|
32
|
+
const { args, flags } = await this.parse(ProjectsArchive);
|
|
33
|
+
const format = flags.format;
|
|
34
|
+
const client = getClient();
|
|
35
|
+
let payload;
|
|
36
|
+
if (flags.unarchive) {
|
|
37
|
+
payload = await client.unarchiveProject(args.id);
|
|
38
|
+
}
|
|
39
|
+
else {
|
|
40
|
+
payload = await client.archiveProject(args.id);
|
|
41
|
+
}
|
|
42
|
+
if (!payload.success) {
|
|
43
|
+
const action = flags.unarchive ? 'unarchive' : 'archive';
|
|
44
|
+
throw new CliError(ErrorCodes.API_ERROR, `Failed to ${action} project`);
|
|
45
|
+
}
|
|
46
|
+
const project = await payload.project;
|
|
47
|
+
if (!project) {
|
|
48
|
+
throw new CliError(ErrorCodes.API_ERROR, 'Project not found in response');
|
|
49
|
+
}
|
|
50
|
+
const action = flags.unarchive ? 'unarchived' : 'archived';
|
|
51
|
+
const data = {
|
|
52
|
+
id: project.id,
|
|
53
|
+
name: project.name,
|
|
54
|
+
action,
|
|
55
|
+
archivedAt: project.archivedAt,
|
|
56
|
+
url: project.url,
|
|
57
|
+
};
|
|
58
|
+
if (format === 'json') {
|
|
59
|
+
print(success(data));
|
|
60
|
+
}
|
|
61
|
+
else if (format === 'table') {
|
|
62
|
+
printItem({
|
|
63
|
+
id: data.id,
|
|
64
|
+
name: data.name,
|
|
65
|
+
action: data.action,
|
|
66
|
+
archivedAt: data.archivedAt ?? 'N/A',
|
|
67
|
+
url: data.url,
|
|
68
|
+
}, format);
|
|
69
|
+
}
|
|
70
|
+
else {
|
|
71
|
+
console.log(data.id);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
catch (err) {
|
|
75
|
+
handleError(err);
|
|
76
|
+
this.exit(1);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { Command } from '@oclif/core';
|
|
2
|
+
export default class ProjectsCreate 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
|
+
description: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
9
|
+
state: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
10
|
+
'team-ids': import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
11
|
+
'lead-id': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
12
|
+
'start-date': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
13
|
+
'target-date': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
14
|
+
};
|
|
15
|
+
run(): Promise<void>;
|
|
16
|
+
}
|
|
@@ -0,0 +1,115 @@
|
|
|
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 ProjectsCreate extends Command {
|
|
6
|
+
static description = 'Create a project';
|
|
7
|
+
static examples = [
|
|
8
|
+
'<%= config.bin %> projects create --name "My Project" --team-ids TEAM_ID',
|
|
9
|
+
'<%= config.bin %> projects create --name "Q1 Goals" --description "First quarter objectives" --target-date 2024-03-31',
|
|
10
|
+
'<%= config.bin %> projects create --name "Feature X" --state started --lead-id USER_ID',
|
|
11
|
+
];
|
|
12
|
+
static flags = {
|
|
13
|
+
format: Flags.string({
|
|
14
|
+
char: 'F',
|
|
15
|
+
description: 'Output format',
|
|
16
|
+
options: ['json', 'table', 'plain'],
|
|
17
|
+
default: 'json',
|
|
18
|
+
}),
|
|
19
|
+
name: Flags.string({
|
|
20
|
+
char: 'n',
|
|
21
|
+
description: 'Project name',
|
|
22
|
+
required: true,
|
|
23
|
+
}),
|
|
24
|
+
description: Flags.string({
|
|
25
|
+
char: 'd',
|
|
26
|
+
description: 'Project description',
|
|
27
|
+
}),
|
|
28
|
+
state: Flags.string({
|
|
29
|
+
char: 's',
|
|
30
|
+
description: 'Project state',
|
|
31
|
+
options: ['planned', 'started', 'paused', 'completed', 'canceled'],
|
|
32
|
+
}),
|
|
33
|
+
'team-ids': Flags.string({
|
|
34
|
+
description: 'Team IDs (comma-separated)',
|
|
35
|
+
required: true,
|
|
36
|
+
}),
|
|
37
|
+
'lead-id': Flags.string({
|
|
38
|
+
description: 'Lead user ID',
|
|
39
|
+
}),
|
|
40
|
+
'start-date': Flags.string({
|
|
41
|
+
description: 'Start date (YYYY-MM-DD)',
|
|
42
|
+
}),
|
|
43
|
+
'target-date': Flags.string({
|
|
44
|
+
description: 'Target date (YYYY-MM-DD)',
|
|
45
|
+
}),
|
|
46
|
+
};
|
|
47
|
+
async run() {
|
|
48
|
+
try {
|
|
49
|
+
const { flags } = await this.parse(ProjectsCreate);
|
|
50
|
+
const format = flags.format;
|
|
51
|
+
const client = getClient();
|
|
52
|
+
const teamIds = flags['team-ids'].split(',').map((id) => id.trim());
|
|
53
|
+
const payload = await client.createProject({
|
|
54
|
+
name: flags.name,
|
|
55
|
+
description: flags.description,
|
|
56
|
+
state: flags.state,
|
|
57
|
+
teamIds,
|
|
58
|
+
leadId: flags['lead-id'],
|
|
59
|
+
startDate: flags['start-date'],
|
|
60
|
+
targetDate: flags['target-date'],
|
|
61
|
+
});
|
|
62
|
+
if (!payload.success || !payload.project) {
|
|
63
|
+
throw new CliError(ErrorCodes.API_ERROR, 'Failed to create project');
|
|
64
|
+
}
|
|
65
|
+
const project = await payload.project;
|
|
66
|
+
const [lead, teams] = await Promise.all([project.lead, project.teams()]);
|
|
67
|
+
const data = {
|
|
68
|
+
id: project.id,
|
|
69
|
+
name: project.name,
|
|
70
|
+
description: project.description,
|
|
71
|
+
state: project.state,
|
|
72
|
+
progress: project.progress,
|
|
73
|
+
startDate: project.startDate,
|
|
74
|
+
targetDate: project.targetDate,
|
|
75
|
+
url: project.url,
|
|
76
|
+
lead: lead
|
|
77
|
+
? {
|
|
78
|
+
id: lead.id,
|
|
79
|
+
name: lead.name,
|
|
80
|
+
}
|
|
81
|
+
: null,
|
|
82
|
+
teams: teams.nodes.map((team) => ({
|
|
83
|
+
id: team.id,
|
|
84
|
+
key: team.key,
|
|
85
|
+
name: team.name,
|
|
86
|
+
})),
|
|
87
|
+
createdAt: project.createdAt,
|
|
88
|
+
};
|
|
89
|
+
if (format === 'json') {
|
|
90
|
+
print(success(data));
|
|
91
|
+
}
|
|
92
|
+
else if (format === 'table') {
|
|
93
|
+
printItem({
|
|
94
|
+
id: data.id,
|
|
95
|
+
name: data.name,
|
|
96
|
+
description: data.description ?? 'N/A',
|
|
97
|
+
state: data.state,
|
|
98
|
+
startDate: data.startDate ?? 'N/A',
|
|
99
|
+
targetDate: data.targetDate ?? 'N/A',
|
|
100
|
+
lead: data.lead?.name ?? 'None',
|
|
101
|
+
teams: data.teams.map((t) => t.key).join(', '),
|
|
102
|
+
url: data.url,
|
|
103
|
+
createdAt: data.createdAt,
|
|
104
|
+
}, format);
|
|
105
|
+
}
|
|
106
|
+
else {
|
|
107
|
+
console.log(data.id);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
catch (err) {
|
|
111
|
+
handleError(err);
|
|
112
|
+
this.exit(1);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { Command } from '@oclif/core';
|
|
2
|
+
export default class ProjectsDelete 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 ProjectsDelete extends Command {
|
|
6
|
+
static description = 'Delete a project';
|
|
7
|
+
static examples = ['<%= config.bin %> projects delete PROJECT_ID'];
|
|
8
|
+
static args = {
|
|
9
|
+
id: Args.string({
|
|
10
|
+
description: 'Project 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(ProjectsDelete);
|
|
25
|
+
const format = flags.format;
|
|
26
|
+
const client = getClient();
|
|
27
|
+
const payload = await client.deleteProject(args.id);
|
|
28
|
+
if (!payload.success) {
|
|
29
|
+
throw new CliError(ErrorCodes.API_ERROR, 'Failed to delete project');
|
|
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(`Project ${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 ProjectsGet 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
|
+
}
|