@cipherly/plane-cli 1.0.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/LICENSE +201 -0
- package/README.md +65 -0
- package/dist/cycles/create.cycles.js +44 -0
- package/dist/cycles/delete.cycles.js +30 -0
- package/dist/cycles/index.js +21 -0
- package/dist/cycles/list.cycles.js +42 -0
- package/dist/cycles/update.cycles.js +46 -0
- package/dist/cycles/work-items/index.js +17 -0
- package/dist/cycles/work-items/list.cycles.work-items.js +43 -0
- package/dist/labels/create.labels.js +34 -0
- package/dist/labels/delete.labels.js +30 -0
- package/dist/labels/index.js +20 -0
- package/dist/labels/list.labels.js +36 -0
- package/dist/labels/update.labels.js +36 -0
- package/dist/plane.js +60 -0
- package/dist/projects/create.projects.js +38 -0
- package/dist/projects/delete.projects.js +28 -0
- package/dist/projects/index.js +20 -0
- package/dist/projects/list.projects.js +35 -0
- package/dist/projects/update.projects.js +39 -0
- package/dist/states/create.states.js +37 -0
- package/dist/states/delete.states.js +30 -0
- package/dist/states/index.js +20 -0
- package/dist/states/list.states.js +36 -0
- package/dist/states/update.states.js +36 -0
- package/dist/users/index.js +17 -0
- package/dist/users/me.users.js +36 -0
- package/dist/utils.js +63 -0
- package/dist/work-items/create.work-items.js +51 -0
- package/dist/work-items/delete.work-items.js +30 -0
- package/dist/work-items/index.js +21 -0
- package/dist/work-items/list.work-items.js +44 -0
- package/dist/work-items/types/index.js +17 -0
- package/dist/work-items/types/list.types.work-items.js +40 -0
- package/dist/work-items/update.work-items.js +41 -0
- package/package.json +29 -0
- package/src/cycles/create.cycles.ts +39 -0
- package/src/cycles/delete.cycles.ts +25 -0
- package/src/cycles/index.ts +5 -0
- package/src/cycles/list.cycles.ts +37 -0
- package/src/cycles/update.cycles.ts +41 -0
- package/src/cycles/work-items/index.ts +1 -0
- package/src/cycles/work-items/list.cycles.work-items.ts +40 -0
- package/src/labels/create.labels.ts +29 -0
- package/src/labels/delete.labels.ts +25 -0
- package/src/labels/index.ts +5 -0
- package/src/labels/list.labels.ts +31 -0
- package/src/labels/update.labels.ts +31 -0
- package/src/plane.ts +97 -0
- package/src/projects/create.projects.ts +33 -0
- package/src/projects/delete.projects.ts +23 -0
- package/src/projects/index.ts +5 -0
- package/src/projects/list.projects.ts +30 -0
- package/src/projects/update.projects.ts +32 -0
- package/src/states/create.states.ts +32 -0
- package/src/states/delete.states.ts +25 -0
- package/src/states/index.ts +5 -0
- package/src/states/list.states.ts +31 -0
- package/src/states/update.states.ts +31 -0
- package/src/users/index.ts +1 -0
- package/src/users/me.users.ts +30 -0
- package/src/utils.ts +81 -0
- package/src/work-items/create.work-items.ts +85 -0
- package/src/work-items/delete.work-items.ts +25 -0
- package/src/work-items/index.ts +5 -0
- package/src/work-items/list.work-items.ts +43 -0
- package/src/work-items/types/index.ts +1 -0
- package/src/work-items/types/list.types.work-items.ts +36 -0
- package/src/work-items/update.work-items.ts +79 -0
- package/tsconfig.json +14 -0
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { Command } from "commander";
|
|
2
|
+
import { checkRequiredOptionsAndReturn, requestPlaneAPI } from "../utils";
|
|
3
|
+
|
|
4
|
+
export const listProjects = new Command("list")
|
|
5
|
+
.description("List projects")
|
|
6
|
+
.action(async (__, cmd: Command) => {
|
|
7
|
+
if (cmd.parent == null) return;
|
|
8
|
+
const { apiKey, apiBase, workspaceSlug, json } =
|
|
9
|
+
checkRequiredOptionsAndReturn(cmd);
|
|
10
|
+
const { result, status } = await requestPlaneAPI({
|
|
11
|
+
apiBase,
|
|
12
|
+
apiKey,
|
|
13
|
+
endpoint: `workspaces/${workspaceSlug}/projects/`,
|
|
14
|
+
method: "GET",
|
|
15
|
+
});
|
|
16
|
+
if (json) console.log(JSON.stringify(result));
|
|
17
|
+
else {
|
|
18
|
+
if (status !== 200) console.table(result);
|
|
19
|
+
else console.table(result.results.map(renderProject));
|
|
20
|
+
}
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
export const renderProject = (project: any) => {
|
|
24
|
+
return {
|
|
25
|
+
id: project.id,
|
|
26
|
+
name: project.name,
|
|
27
|
+
description: project.description,
|
|
28
|
+
total_members: project.total_members,
|
|
29
|
+
};
|
|
30
|
+
};
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { Command } from "commander";
|
|
2
|
+
import { checkRequiredOptionsAndReturn, requestPlaneAPI } from "../utils";
|
|
3
|
+
import { renderProject } from "./list.projects";
|
|
4
|
+
|
|
5
|
+
export const updateProject = new Command("update")
|
|
6
|
+
.description("Update a project")
|
|
7
|
+
.requiredOption("-p, --project-id <projectId>", "Project's ID")
|
|
8
|
+
.option("-n, --name [name]", "Project's name")
|
|
9
|
+
.option("-d, --description [description]", "Project's description")
|
|
10
|
+
.action(async (__, cmd: Command) => {
|
|
11
|
+
if (cmd.parent == null) return;
|
|
12
|
+
const { apiKey, apiBase, workspaceSlug, json } =
|
|
13
|
+
checkRequiredOptionsAndReturn(cmd);
|
|
14
|
+
const projectId = cmd.getOptionValue("projectId");
|
|
15
|
+
const name = cmd.getOptionValue("name");
|
|
16
|
+
const description = cmd.getOptionValue("description");
|
|
17
|
+
const body: any = {};
|
|
18
|
+
if (name !== undefined) body.name = name;
|
|
19
|
+
if (description !== undefined) body.description = description;
|
|
20
|
+
const { result, status } = await requestPlaneAPI({
|
|
21
|
+
apiBase,
|
|
22
|
+
apiKey,
|
|
23
|
+
endpoint: `workspaces/${workspaceSlug}/projects/${projectId}/`,
|
|
24
|
+
method: "PATCH",
|
|
25
|
+
body,
|
|
26
|
+
});
|
|
27
|
+
if (json) console.log(JSON.stringify(result));
|
|
28
|
+
else {
|
|
29
|
+
if (status !== 200) console.table(result);
|
|
30
|
+
else console.table(renderProject(result));
|
|
31
|
+
}
|
|
32
|
+
});
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { Command } from "commander";
|
|
2
|
+
import { checkRequiredOptionsAndReturn, requestPlaneAPI } from "../utils";
|
|
3
|
+
import { renderState } from "./list.states";
|
|
4
|
+
|
|
5
|
+
export const createState = new Command("create")
|
|
6
|
+
.description("Create a new state")
|
|
7
|
+
.requiredOption("-p, --project-id <projectId>", "Project's ID")
|
|
8
|
+
.requiredOption("-n, --name <name>", "State's name")
|
|
9
|
+
.requiredOption("-c, --color <color>", "State's color")
|
|
10
|
+
.action(async (__, cmd: Command) => {
|
|
11
|
+
if (cmd.parent == null) return;
|
|
12
|
+
const { apiKey, apiBase, workspaceSlug, json } =
|
|
13
|
+
checkRequiredOptionsAndReturn(cmd);
|
|
14
|
+
const projectId = cmd.getOptionValue("projectId");
|
|
15
|
+
const name = cmd.getOptionValue("name");
|
|
16
|
+
const color = cmd.getOptionValue("color");
|
|
17
|
+
const { result, status } = await requestPlaneAPI({
|
|
18
|
+
apiBase,
|
|
19
|
+
apiKey,
|
|
20
|
+
endpoint: `workspaces/${workspaceSlug}/projects/${projectId}/states/`,
|
|
21
|
+
method: "POST",
|
|
22
|
+
body: {
|
|
23
|
+
name,
|
|
24
|
+
color,
|
|
25
|
+
},
|
|
26
|
+
});
|
|
27
|
+
if (json) console.log(JSON.stringify(result));
|
|
28
|
+
else {
|
|
29
|
+
if (status !== 201) console.table(result);
|
|
30
|
+
else console.table(renderState(result));
|
|
31
|
+
}
|
|
32
|
+
});
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { Command } from "commander";
|
|
2
|
+
import { checkRequiredOptionsAndReturn, requestPlaneAPI } from "../utils";
|
|
3
|
+
|
|
4
|
+
export const deleteState = new Command("delete")
|
|
5
|
+
.description("Delete a state")
|
|
6
|
+
.requiredOption("-p, --project-id <projectId>", "Project's ID")
|
|
7
|
+
.requiredOption("-s, --state-id <stateId>", "State's ID")
|
|
8
|
+
.action(async (__, cmd: Command) => {
|
|
9
|
+
if (cmd.parent == null) return;
|
|
10
|
+
const { apiKey, apiBase, workspaceSlug, json } =
|
|
11
|
+
checkRequiredOptionsAndReturn(cmd);
|
|
12
|
+
const projectId = cmd.getOptionValue("projectId");
|
|
13
|
+
const stateId = cmd.getOptionValue("stateId");
|
|
14
|
+
const { result, status } = await requestPlaneAPI({
|
|
15
|
+
apiBase,
|
|
16
|
+
apiKey,
|
|
17
|
+
endpoint: `workspaces/${workspaceSlug}/projects/${projectId}/states/${stateId}/`,
|
|
18
|
+
method: "DELETE",
|
|
19
|
+
});
|
|
20
|
+
if (json) console.log(JSON.stringify(result));
|
|
21
|
+
else {
|
|
22
|
+
if (status !== 204) console.table(result);
|
|
23
|
+
else console.table(result);
|
|
24
|
+
}
|
|
25
|
+
});
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { Command } from "commander";
|
|
2
|
+
import { checkRequiredOptionsAndReturn, requestPlaneAPI } from "../utils";
|
|
3
|
+
|
|
4
|
+
export const listStates = new Command("list")
|
|
5
|
+
.description("List states")
|
|
6
|
+
.requiredOption("-p, --project-id <projectId>", "Project's ID")
|
|
7
|
+
.action(async (__, cmd: Command) => {
|
|
8
|
+
if (cmd.parent == null) return;
|
|
9
|
+
const { apiKey, apiBase, workspaceSlug, json } =
|
|
10
|
+
checkRequiredOptionsAndReturn(cmd);
|
|
11
|
+
const projectId = cmd.getOptionValue("projectId");
|
|
12
|
+
const { result, status } = await requestPlaneAPI({
|
|
13
|
+
apiBase,
|
|
14
|
+
apiKey,
|
|
15
|
+
endpoint: `workspaces/${workspaceSlug}/projects/${projectId}/states/`,
|
|
16
|
+
method: "GET",
|
|
17
|
+
});
|
|
18
|
+
if (json) console.log(JSON.stringify(result));
|
|
19
|
+
else {
|
|
20
|
+
if (status !== 200) console.table(result);
|
|
21
|
+
else console.table(result.results.map(renderState));
|
|
22
|
+
}
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
export const renderState = (state: any) => {
|
|
26
|
+
return {
|
|
27
|
+
id: state.id,
|
|
28
|
+
name: state.name,
|
|
29
|
+
description: state.description,
|
|
30
|
+
};
|
|
31
|
+
};
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { Command } from "commander";
|
|
2
|
+
import { checkRequiredOptionsAndReturn, requestPlaneAPI } from "../utils";
|
|
3
|
+
import { renderState } from "./list.states";
|
|
4
|
+
|
|
5
|
+
export const updateState = new Command("update")
|
|
6
|
+
.description("Update a state")
|
|
7
|
+
.requiredOption("-p, --project-id <projectId>", "Project's ID")
|
|
8
|
+
.requiredOption("-s, --state-id <stateId>", "State's ID")
|
|
9
|
+
.requiredOption("-n, --name <name>", "State's name")
|
|
10
|
+
.action(async (__, cmd: Command) => {
|
|
11
|
+
if (cmd.parent == null) return;
|
|
12
|
+
const { apiKey, apiBase, workspaceSlug, json } =
|
|
13
|
+
checkRequiredOptionsAndReturn(cmd);
|
|
14
|
+
const projectId = cmd.getOptionValue("projectId");
|
|
15
|
+
const stateId = cmd.getOptionValue("stateId");
|
|
16
|
+
const name = cmd.getOptionValue("name");
|
|
17
|
+
const { result, status } = await requestPlaneAPI({
|
|
18
|
+
apiBase,
|
|
19
|
+
apiKey,
|
|
20
|
+
endpoint: `workspaces/${workspaceSlug}/projects/${projectId}/states/${stateId}/`,
|
|
21
|
+
method: "PATCH",
|
|
22
|
+
body: {
|
|
23
|
+
name,
|
|
24
|
+
},
|
|
25
|
+
});
|
|
26
|
+
if (json) console.log(JSON.stringify(result));
|
|
27
|
+
else {
|
|
28
|
+
if (status !== 200) console.table(result);
|
|
29
|
+
else console.table(renderState(result));
|
|
30
|
+
}
|
|
31
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./me.users";
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { Command } from "commander";
|
|
2
|
+
import { checkRequiredOptionsAndReturn, requestPlaneAPI } from "../utils";
|
|
3
|
+
|
|
4
|
+
export const getCurrentUser = new Command("me")
|
|
5
|
+
.description("Get current user")
|
|
6
|
+
.action(async (__, cmd: Command) => {
|
|
7
|
+
if (cmd.parent == null) return;
|
|
8
|
+
const { apiKey, apiBase, json } = checkRequiredOptionsAndReturn(cmd);
|
|
9
|
+
const { result, status } = await requestPlaneAPI({
|
|
10
|
+
apiBase,
|
|
11
|
+
apiKey,
|
|
12
|
+
endpoint: `users/me/`,
|
|
13
|
+
method: "GET",
|
|
14
|
+
});
|
|
15
|
+
if (json) console.log(JSON.stringify(result));
|
|
16
|
+
else {
|
|
17
|
+
if (status !== 200) console.table(result);
|
|
18
|
+
else console.table(renderUser(result));
|
|
19
|
+
}
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
export const renderUser = (user: any) => {
|
|
23
|
+
return {
|
|
24
|
+
id: user.id,
|
|
25
|
+
first_name: user.first_name,
|
|
26
|
+
last_name: user.last_name,
|
|
27
|
+
email: user.email,
|
|
28
|
+
display_name: user.display_name,
|
|
29
|
+
};
|
|
30
|
+
};
|
package/src/utils.ts
ADDED
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { Command } from "commander";
|
|
2
|
+
|
|
3
|
+
export const checkApiKey = (apiKey: any) => {
|
|
4
|
+
if (!apiKey) {
|
|
5
|
+
console.error(
|
|
6
|
+
"No API key provided. Use: plane <command> --api-key <API_KEY> or set PLANE_API_KEY environment variable",
|
|
7
|
+
);
|
|
8
|
+
process.exit(1);
|
|
9
|
+
}
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
export const checkApiBase = (apiBase: any) => {
|
|
13
|
+
if (!apiBase) {
|
|
14
|
+
console.error(
|
|
15
|
+
"No API base provided. Use: plane <command> --api-base <API_BASE> or set PLANE_API_BASE environment variable",
|
|
16
|
+
);
|
|
17
|
+
process.exit(1);
|
|
18
|
+
}
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
export const checkWorkspaceSlug = (workspaceSlug: any) => {
|
|
22
|
+
if (!workspaceSlug) {
|
|
23
|
+
console.error(
|
|
24
|
+
"No workspace slug provided. Use: plane <command> --workspace-slug <SLUG> or set PLANE_WORKSPACE_SLUG environment variable",
|
|
25
|
+
);
|
|
26
|
+
process.exit(1);
|
|
27
|
+
}
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
export const checkRequiredOptionsAndReturn = (cmd: Command) => {
|
|
31
|
+
const apiKey = cmd.parent.getOptionValue("apiKey");
|
|
32
|
+
const apiBase = cmd.parent.getOptionValue("apiBase");
|
|
33
|
+
const workspaceSlug = cmd.parent.getOptionValue("workspaceSlug");
|
|
34
|
+
checkApiKey(apiKey);
|
|
35
|
+
checkApiBase(apiBase);
|
|
36
|
+
checkWorkspaceSlug(workspaceSlug);
|
|
37
|
+
const json = cmd.parent.getOptionValue("json");
|
|
38
|
+
return {
|
|
39
|
+
apiKey,
|
|
40
|
+
apiBase,
|
|
41
|
+
workspaceSlug,
|
|
42
|
+
json,
|
|
43
|
+
};
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
export const requestPlaneAPI = async ({
|
|
47
|
+
apiKey,
|
|
48
|
+
apiBase,
|
|
49
|
+
endpoint,
|
|
50
|
+
method,
|
|
51
|
+
body,
|
|
52
|
+
params,
|
|
53
|
+
no_v1,
|
|
54
|
+
}: {
|
|
55
|
+
apiKey: string;
|
|
56
|
+
apiBase: string;
|
|
57
|
+
endpoint: string;
|
|
58
|
+
method: string;
|
|
59
|
+
body?: any;
|
|
60
|
+
params?: any;
|
|
61
|
+
no_v1?: boolean;
|
|
62
|
+
}) => {
|
|
63
|
+
let url = `${apiBase}/api${(!!!no_v1 && "/v1") || ""}/${endpoint}`;
|
|
64
|
+
if (params) {
|
|
65
|
+
const qs = new URLSearchParams(params).toString();
|
|
66
|
+
url += `?${qs}`;
|
|
67
|
+
}
|
|
68
|
+
const headers = {
|
|
69
|
+
"X-API-Key": apiKey,
|
|
70
|
+
"Content-Type": "application/json",
|
|
71
|
+
};
|
|
72
|
+
const opts = { method, headers, body };
|
|
73
|
+
if (body) opts.body = JSON.stringify(body);
|
|
74
|
+
try {
|
|
75
|
+
const res = await fetch(url, opts);
|
|
76
|
+
return { result: await res.json(), status: res.status };
|
|
77
|
+
} catch (err) {
|
|
78
|
+
console.error("Request failed:", err.message);
|
|
79
|
+
process.exit(1);
|
|
80
|
+
}
|
|
81
|
+
};
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { Command, Option } from "commander";
|
|
2
|
+
import { checkRequiredOptionsAndReturn, requestPlaneAPI } from "../utils";
|
|
3
|
+
|
|
4
|
+
export const createWorkItem = new Command("create")
|
|
5
|
+
.description("Create a new work-item")
|
|
6
|
+
.requiredOption("-p, --project-id <projectId>", "Project's ID")
|
|
7
|
+
.requiredOption("-n, --name <name>", "Work item's name")
|
|
8
|
+
.option(
|
|
9
|
+
"-d, --description [description_html]",
|
|
10
|
+
"Work item's description in HTML",
|
|
11
|
+
)
|
|
12
|
+
.option("-s, --state <state>", "Work item's state ID")
|
|
13
|
+
.option(
|
|
14
|
+
"-a, --assignees <assignees>",
|
|
15
|
+
"Work item's assignees IDs (comma seperated)",
|
|
16
|
+
)
|
|
17
|
+
.addOption(
|
|
18
|
+
new Option("-u, --priority <priority>", "Work item's priority").choices([
|
|
19
|
+
"none",
|
|
20
|
+
"urgent",
|
|
21
|
+
"high",
|
|
22
|
+
"medium",
|
|
23
|
+
"low",
|
|
24
|
+
]),
|
|
25
|
+
)
|
|
26
|
+
.option("-l, --labels <labels>", "Work item's labels IDs (comma seperated)")
|
|
27
|
+
.option("--parent <parentId>", "Work item's parent ID")
|
|
28
|
+
.option("-ep, --estimate-point <estimatePoint>", "Work item's estimate point")
|
|
29
|
+
.option("-sd, --start-date <startDate>", "Work item's start date")
|
|
30
|
+
.option("-td, --target-date <targetDate>", "Work item's target date")
|
|
31
|
+
.option("-m, --module <moduleId>", "Work item's module id")
|
|
32
|
+
.action(async (__, cmd: Command) => {
|
|
33
|
+
if (cmd.parent == null) return;
|
|
34
|
+
const { apiKey, apiBase, workspaceSlug, json } =
|
|
35
|
+
checkRequiredOptionsAndReturn(cmd);
|
|
36
|
+
const projectId = cmd.getOptionValue("projectId");
|
|
37
|
+
const name = cmd.getOptionValue("name");
|
|
38
|
+
const description_html = cmd.getOptionValue("description");
|
|
39
|
+
const state = cmd.getOptionValue("state");
|
|
40
|
+
const assignees = cmd.getOptionValue("assignees");
|
|
41
|
+
const priority = cmd.getOptionValue("priority");
|
|
42
|
+
const labels = cmd.getOptionValue("labels");
|
|
43
|
+
const parent_id = cmd.getOptionValue("parent");
|
|
44
|
+
const estimate_point = cmd.getOptionValue("estimatePoint");
|
|
45
|
+
const start_date = cmd.getOptionValue("startDate");
|
|
46
|
+
const target_date = cmd.getOptionValue("targetDate");
|
|
47
|
+
const module_id = cmd.getOptionValue("module");
|
|
48
|
+
const { result, status } = await requestPlaneAPI({
|
|
49
|
+
apiBase,
|
|
50
|
+
apiKey,
|
|
51
|
+
endpoint: `workspaces/${workspaceSlug}/projects/${projectId}/issues/`,
|
|
52
|
+
method: "POST",
|
|
53
|
+
body: {
|
|
54
|
+
name,
|
|
55
|
+
description_html,
|
|
56
|
+
project_id: projectId,
|
|
57
|
+
state,
|
|
58
|
+
assignees,
|
|
59
|
+
priority,
|
|
60
|
+
labels,
|
|
61
|
+
parent: parent_id,
|
|
62
|
+
estimate_point,
|
|
63
|
+
start_date,
|
|
64
|
+
target_date,
|
|
65
|
+
module: module_id,
|
|
66
|
+
},
|
|
67
|
+
params: {
|
|
68
|
+
expand: "state,labels,assignees",
|
|
69
|
+
},
|
|
70
|
+
});
|
|
71
|
+
if (json) {
|
|
72
|
+
console.log(JSON.stringify(result));
|
|
73
|
+
} else {
|
|
74
|
+
if (status !== 201) console.table(result);
|
|
75
|
+
else console.table(renderNewWorkItem(result));
|
|
76
|
+
}
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
export const renderNewWorkItem = (workItem: any) => {
|
|
80
|
+
return {
|
|
81
|
+
id: workItem.id,
|
|
82
|
+
name: workItem.name,
|
|
83
|
+
created: true,
|
|
84
|
+
};
|
|
85
|
+
};
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { Command } from "commander";
|
|
2
|
+
import { checkRequiredOptionsAndReturn, requestPlaneAPI } from "../utils";
|
|
3
|
+
|
|
4
|
+
export const deleteWorkItem = new Command("delete")
|
|
5
|
+
.description("Delete a work-item")
|
|
6
|
+
.requiredOption("-p, --project-id <projectId>", "Project's ID")
|
|
7
|
+
.requiredOption("-w, --work-item-id <workItemId>", "Work item's ID")
|
|
8
|
+
.action(async (__, cmd: Command) => {
|
|
9
|
+
if (cmd.parent == null) return;
|
|
10
|
+
const { apiKey, apiBase, workspaceSlug, json } =
|
|
11
|
+
checkRequiredOptionsAndReturn(cmd);
|
|
12
|
+
const projectId = cmd.getOptionValue("projectId");
|
|
13
|
+
const workItemId = cmd.getOptionValue("workItemId");
|
|
14
|
+
const { result, status } = await requestPlaneAPI({
|
|
15
|
+
apiBase,
|
|
16
|
+
apiKey,
|
|
17
|
+
endpoint: `workspaces/${workspaceSlug}/projects/${projectId}/work-items/${workItemId}/`,
|
|
18
|
+
method: "DELETE",
|
|
19
|
+
});
|
|
20
|
+
if (json) console.log(JSON.stringify(result));
|
|
21
|
+
else {
|
|
22
|
+
if (status !== 204) console.table(result);
|
|
23
|
+
else console.table(result);
|
|
24
|
+
}
|
|
25
|
+
});
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { Command } from "commander";
|
|
2
|
+
import { checkRequiredOptionsAndReturn, requestPlaneAPI } from "../utils";
|
|
3
|
+
|
|
4
|
+
export const listWorkItems = new Command("list")
|
|
5
|
+
.description("List work items")
|
|
6
|
+
.requiredOption("-p, --project-id <projectId>", "Project's ID")
|
|
7
|
+
.action(async (__, cmd: Command) => {
|
|
8
|
+
if (cmd.parent == null) return;
|
|
9
|
+
const { apiKey, apiBase, workspaceSlug, json } =
|
|
10
|
+
checkRequiredOptionsAndReturn(cmd);
|
|
11
|
+
const projectId = cmd.getOptionValue("projectId");
|
|
12
|
+
const { result, status } = await requestPlaneAPI({
|
|
13
|
+
apiBase,
|
|
14
|
+
apiKey,
|
|
15
|
+
endpoint: `workspaces/${workspaceSlug}/projects/${projectId}/work-items/`,
|
|
16
|
+
method: "GET",
|
|
17
|
+
params: {
|
|
18
|
+
expand: "state,labels,assignees",
|
|
19
|
+
},
|
|
20
|
+
});
|
|
21
|
+
if (json) console.log(JSON.stringify(result));
|
|
22
|
+
else {
|
|
23
|
+
if (status !== 200) console.table(result);
|
|
24
|
+
else console.table(result.results.map(renderWorkItem));
|
|
25
|
+
}
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
export const renderWorkItem = (workItem: any) => {
|
|
29
|
+
return {
|
|
30
|
+
id: workItem.id,
|
|
31
|
+
name: workItem.name,
|
|
32
|
+
state: (workItem.state && workItem.state.name) || null,
|
|
33
|
+
labels:
|
|
34
|
+
(workItem.labels && workItem.labels.map((label: any) => label.name)) ||
|
|
35
|
+
[],
|
|
36
|
+
assignees:
|
|
37
|
+
(workItem.assignees &&
|
|
38
|
+
workItem.assignees.map((user: any) =>
|
|
39
|
+
`${user.first_name} ${user.last_name}`.trim(),
|
|
40
|
+
)) ||
|
|
41
|
+
[],
|
|
42
|
+
};
|
|
43
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./list.types.work-items";
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { Command } from "commander";
|
|
2
|
+
import { checkRequiredOptionsAndReturn, requestPlaneAPI } from "../../utils";
|
|
3
|
+
|
|
4
|
+
// WARN: THIS ENDPOINT IS WIP
|
|
5
|
+
export const listWorkItemTypes = new Command("list")
|
|
6
|
+
.description("List work item types")
|
|
7
|
+
.requiredOption("-p, --project-id <projectId>", "Project's ID")
|
|
8
|
+
.action(async (__, cmd: Command) => {
|
|
9
|
+
if (cmd.parent == null) return;
|
|
10
|
+
const { apiKey, apiBase, workspaceSlug, json } =
|
|
11
|
+
checkRequiredOptionsAndReturn(cmd);
|
|
12
|
+
const projectId = cmd.getOptionValue("projectId");
|
|
13
|
+
const { result, status } = await requestPlaneAPI({
|
|
14
|
+
apiBase,
|
|
15
|
+
apiKey,
|
|
16
|
+
endpoint: `workspaces/${workspaceSlug}/projects/${projectId}/work-item-types/`,
|
|
17
|
+
method: "GET",
|
|
18
|
+
});
|
|
19
|
+
if (json) console.log(JSON.stringify(result));
|
|
20
|
+
else {
|
|
21
|
+
if (status !== 200) console.table(result);
|
|
22
|
+
else console.table(result.results.map(renderWorkItemType));
|
|
23
|
+
}
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
export const renderWorkItemType = (workItemType: any) => {
|
|
27
|
+
return {
|
|
28
|
+
id: workItemType.id,
|
|
29
|
+
name: workItemType.name,
|
|
30
|
+
description: workItemType.description,
|
|
31
|
+
is_epic: workItemType.is_epic,
|
|
32
|
+
is_default: workItemType.is_default,
|
|
33
|
+
is_active: workItemType.is_active,
|
|
34
|
+
level: workItemType.level,
|
|
35
|
+
};
|
|
36
|
+
};
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { Command, Option } from "commander";
|
|
2
|
+
import { checkRequiredOptionsAndReturn, requestPlaneAPI } from "../utils";
|
|
3
|
+
|
|
4
|
+
export const updateWorkItem = new Command("update")
|
|
5
|
+
.description("Update a work-item")
|
|
6
|
+
.requiredOption("-p, --project-id <projectId>", "Project's ID")
|
|
7
|
+
.requiredOption("-w, --work-item-id <workItemId>", "Work item's ID")
|
|
8
|
+
.option("-n, --name [name]", "Work item's name")
|
|
9
|
+
.option("-d, --description [description]", "Work item's description in HTML")
|
|
10
|
+
.option("-s, --state <state>", "Work item's state ID")
|
|
11
|
+
.option(
|
|
12
|
+
"-a, --assignees <assignees>",
|
|
13
|
+
"Work item's assignees IDs (comma seperated)",
|
|
14
|
+
)
|
|
15
|
+
.addOption(
|
|
16
|
+
new Option("-u, --priority <priority>", "Work item's priority").choices([
|
|
17
|
+
"none",
|
|
18
|
+
"urgent",
|
|
19
|
+
"high",
|
|
20
|
+
"medium",
|
|
21
|
+
"low",
|
|
22
|
+
]),
|
|
23
|
+
)
|
|
24
|
+
.option("-l, --labels <labels>", "Work item's labels IDs (comma seperated)")
|
|
25
|
+
.option("--parent <parentId>", "Work item's parent ID")
|
|
26
|
+
.option("-ep, --estimate-point <estimatePoint>", "Work item's estimate point")
|
|
27
|
+
.option("-sd, --start-date <startDate>", "Work item's start date")
|
|
28
|
+
.option("-td, --target-date <targetDate>", "Work item's target date")
|
|
29
|
+
.option("-m, --module <moduleId>", "Work item's module id")
|
|
30
|
+
.action(async (__, cmd: Command) => {
|
|
31
|
+
if (cmd.parent == null) return;
|
|
32
|
+
const { apiKey, apiBase, workspaceSlug, json } =
|
|
33
|
+
checkRequiredOptionsAndReturn(cmd);
|
|
34
|
+
const projectId = cmd.getOptionValue("projectId");
|
|
35
|
+
const workItemId = cmd.getOptionValue("workItemId");
|
|
36
|
+
const name = cmd.getOptionValue("name");
|
|
37
|
+
const description = cmd.getOptionValue("description");
|
|
38
|
+
const state = cmd.getOptionValue("state");
|
|
39
|
+
const assignees = cmd.getOptionValue("assignees");
|
|
40
|
+
const priority = cmd.getOptionValue("priority");
|
|
41
|
+
const labels = cmd.getOptionValue("labels");
|
|
42
|
+
const parent_id = cmd.getOptionValue("parent");
|
|
43
|
+
const estimate_point = cmd.getOptionValue("estimatePoint");
|
|
44
|
+
const start_date = cmd.getOptionValue("startDate");
|
|
45
|
+
const target_date = cmd.getOptionValue("targetDate");
|
|
46
|
+
const module_id = cmd.getOptionValue("module");
|
|
47
|
+
const body: any = {};
|
|
48
|
+
if (name !== undefined) body.name = name;
|
|
49
|
+
if (description !== undefined) body.description = description;
|
|
50
|
+
if (state !== undefined) body.state = state;
|
|
51
|
+
if (assignees !== undefined) body.assignees = assignees;
|
|
52
|
+
if (priority !== undefined) body.priority = priority;
|
|
53
|
+
if (labels !== undefined) body.labels = labels;
|
|
54
|
+
if (parent_id !== undefined) body.parent = parent_id;
|
|
55
|
+
if (estimate_point !== undefined) body.estimate_point = estimate_point;
|
|
56
|
+
if (start_date !== undefined) body.start_date = start_date;
|
|
57
|
+
if (target_date !== undefined) body.target_date = target_date;
|
|
58
|
+
if (module_id !== undefined) body.module = module_id;
|
|
59
|
+
const { result, status } = await requestPlaneAPI({
|
|
60
|
+
apiBase,
|
|
61
|
+
apiKey,
|
|
62
|
+
endpoint: `workspaces/${workspaceSlug}/projects/${projectId}/work-items/${workItemId}/`,
|
|
63
|
+
method: "PATCH",
|
|
64
|
+
body,
|
|
65
|
+
});
|
|
66
|
+
if (json) console.log(JSON.stringify(result));
|
|
67
|
+
else {
|
|
68
|
+
if (status !== 200) console.table(result);
|
|
69
|
+
else console.table(renderUpdatedWorkItem(result));
|
|
70
|
+
}
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
export const renderUpdatedWorkItem = (workItem: any) => {
|
|
74
|
+
return {
|
|
75
|
+
id: workItem.id,
|
|
76
|
+
name: workItem.name,
|
|
77
|
+
updated: true,
|
|
78
|
+
};
|
|
79
|
+
};
|
package/tsconfig.json
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ES2020",
|
|
4
|
+
"module": "CommonJS",
|
|
5
|
+
"outDir": "dist",
|
|
6
|
+
"rootDir": "src",
|
|
7
|
+
"moduleResolution": "Node",
|
|
8
|
+
"esModuleInterop": true,
|
|
9
|
+
"forceConsistentCasingInFileNames": true,
|
|
10
|
+
"strict": false,
|
|
11
|
+
"skipLibCheck": true,
|
|
12
|
+
"lib": ["ES2020", "DOM"]
|
|
13
|
+
}
|
|
14
|
+
}
|