@aaronshaf/plane 0.1.7 → 0.1.8

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/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "publishConfig": {
4
4
  "access": "public"
5
5
  },
6
- "version": "0.1.7",
6
+ "version": "0.1.8",
7
7
  "description": "CLI for the Plane project management API",
8
8
  "keywords": [
9
9
  "plane",
@@ -12,6 +12,7 @@ import {
12
12
  } from "../config.js";
13
13
  import {
14
14
  findIssueBySeq,
15
+ getEstimatePointId,
15
16
  getLabelId,
16
17
  getMemberId,
17
18
  getStateId,
@@ -65,8 +66,10 @@ const labelOption = Options.optional(Options.text("label")).pipe(
65
66
  Options.withDescription("Set issue label by name"),
66
67
  );
67
68
 
68
- const estimateOption = Options.optional(Options.integer("estimate")).pipe(
69
- Options.withDescription("Estimate point (0–7)"),
69
+ const estimateOption = Options.optional(Options.text("estimate")).pipe(
70
+ Options.withDescription(
71
+ "Estimate point value (e.g. '3', 'Medium', 'L') — resolved to UUID from the project's estimate scheme",
72
+ ),
70
73
  );
71
74
 
72
75
  const noAssigneeOption = Options.boolean("no-assignee").pipe(
@@ -128,7 +131,10 @@ export const issueUpdate = Command.make(
128
131
  body["label_ids"] = [labelId];
129
132
  }
130
133
  if (estimate._tag === "Some") {
131
- body["estimate_point"] = estimate.value;
134
+ body["estimate_point"] = yield* getEstimatePointId(
135
+ projectId,
136
+ estimate.value,
137
+ );
132
138
  }
133
139
 
134
140
  if (Object.keys(body).length === 0) {
@@ -251,7 +257,10 @@ export const issueCreate = Command.make(
251
257
  body["label_ids"] = [labelId];
252
258
  }
253
259
  if (estimate._tag === "Some") {
254
- body["estimate_point"] = estimate.value;
260
+ body["estimate_point"] = yield* getEstimatePointId(
261
+ projectId,
262
+ estimate.value,
263
+ );
255
264
  }
256
265
  const raw = yield* api.post(`projects/${projectId}/issues/`, body);
257
266
  const created = yield* decodeOrFail(IssueSchema, raw);
package/src/config.ts CHANGED
@@ -18,7 +18,7 @@ export const IssueSchema = Schema.Struct({
18
18
  state: Schema.Union(Schema.String, StateSchema),
19
19
  assignees: Schema.optional(Schema.NullOr(Schema.Array(Schema.String))),
20
20
  description_html: Schema.optional(Schema.NullOr(Schema.String)),
21
- estimate_point: Schema.optional(Schema.NullOr(Schema.Number)),
21
+ estimate_point: Schema.optional(Schema.NullOr(Schema.String)),
22
22
  });
23
23
  export type Issue = typeof IssueSchema.Type;
24
24
 
@@ -215,3 +215,19 @@ export type CycleIssue = typeof CycleIssueSchema.Type;
215
215
  export const CycleIssuesResponseSchema = Schema.Struct({
216
216
  results: Schema.Array(CycleIssueSchema),
217
217
  });
218
+
219
+ export const EstimatePointSchema = Schema.Struct({
220
+ id: Schema.String,
221
+ value: Schema.String,
222
+ key: Schema.Number,
223
+ });
224
+ export type EstimatePoint = typeof EstimatePointSchema.Type;
225
+
226
+ export const EstimateSchema = Schema.Struct({
227
+ id: Schema.String,
228
+ points: Schema.Array(EstimatePointSchema),
229
+ });
230
+
231
+ export const EstimatesResponseSchema = Schema.Struct({
232
+ results: Schema.Array(EstimateSchema),
233
+ });
package/src/resolve.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  import { Effect } from "effect";
2
2
  import { api, decodeOrFail } from "./api.js";
3
3
  import {
4
+ EstimatesResponseSchema,
4
5
  IssuesResponseSchema,
5
6
  LabelsResponseSchema,
6
7
  MembersResponseSchema,
@@ -111,6 +112,29 @@ export function getStateId(projectId: string, nameOrGroup: string) {
111
112
  });
112
113
  }
113
114
 
115
+ export function getEstimatePointId(projectId: string, value: string) {
116
+ return Effect.gen(function* () {
117
+ const raw = yield* api.get(`projects/${projectId}/estimates/`);
118
+ const { results } = yield* decodeOrFail(EstimatesResponseSchema, raw);
119
+ if (results.length === 0)
120
+ return yield* Effect.fail(
121
+ new Error("No estimate scheme configured for this project"),
122
+ );
123
+ const points = results[0].points;
124
+ const lower = value.toLowerCase();
125
+ const point = points.find(
126
+ (p) => p.value.toLowerCase() === lower || String(p.key) === value,
127
+ );
128
+ if (!point)
129
+ return yield* Effect.fail(
130
+ new Error(
131
+ `Estimate point not found: ${value}. Available: ${points.map((p) => p.value).join(", ")}`,
132
+ ),
133
+ );
134
+ return point.id;
135
+ });
136
+ }
137
+
114
138
  export function getLabelId(projectId: string, name: string) {
115
139
  return Effect.gen(function* () {
116
140
  const raw = yield* api.get(`projects/${projectId}/labels/`);
@@ -65,6 +65,23 @@ const server = setupServer(
65
65
  results: [{ id: "l-bug", name: "Bug", color: "#ff0000" }],
66
66
  }),
67
67
  ),
68
+ http.get(
69
+ `${BASE}/api/v1/workspaces/${WS}/projects/proj-acme/estimates/`,
70
+ () =>
71
+ HttpResponse.json({
72
+ results: [
73
+ {
74
+ id: "est-1",
75
+ points: [
76
+ { id: "ep-1", value: "1", key: 0 },
77
+ { id: "ep-2", value: "2", key: 1 },
78
+ { id: "ep-3", value: "3", key: 2 },
79
+ { id: "ep-5", value: "5", key: 3 },
80
+ ],
81
+ },
82
+ ],
83
+ }),
84
+ ),
68
85
  http.get(`${BASE}/api/v1/workspaces/${WS}/members/`, () =>
69
86
  HttpResponse.json(MEMBERS),
70
87
  ),
@@ -999,12 +1016,12 @@ describe("issueUpdate estimate", () => {
999
1016
  description: { _tag: "None" },
1000
1017
  assignee: { _tag: "None" },
1001
1018
  label: { _tag: "None" },
1002
- estimate: { _tag: "Some", value: 3 },
1019
+ estimate: { _tag: "Some", value: "3" },
1003
1020
  noAssignee: false,
1004
1021
  }),
1005
1022
  );
1006
1023
 
1007
- expect((patchedBody as any).estimate_point).toBe(3);
1024
+ expect((patchedBody as any).estimate_point).toBe("ep-3");
1008
1025
  });
1009
1026
  });
1010
1027
 
@@ -1037,11 +1054,11 @@ describe("issueCreate estimate", () => {
1037
1054
  description: { _tag: "None" },
1038
1055
  assignee: { _tag: "None" },
1039
1056
  label: { _tag: "None" },
1040
- estimate: { _tag: "Some", value: 5 },
1057
+ estimate: { _tag: "Some", value: "5" },
1041
1058
  }),
1042
1059
  );
1043
1060
 
1044
- expect((postedBody as any).estimate_point).toBe(5);
1061
+ expect((postedBody as any).estimate_point).toBe("ep-5");
1045
1062
  });
1046
1063
  });
1047
1064