@aaronshaf/plane 0.1.7 → 0.1.10

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.
@@ -9,7 +9,7 @@ import {
9
9
  } from "bun:test";
10
10
  import { Command } from "@effect/cli";
11
11
  import { NodeContext } from "@effect/platform-node";
12
- import { Effect, Layer } from "effect";
12
+ import { Effect, Layer, Option } from "effect";
13
13
  import { http, HttpResponse } from "msw";
14
14
  import { setupServer } from "msw/node";
15
15
  import { _clearProjectCache } from "@/resolve";
@@ -65,6 +65,7 @@ const server = setupServer(
65
65
  results: [{ id: "l-bug", name: "Bug", color: "#ff0000" }],
66
66
  }),
67
67
  ),
68
+
68
69
  http.get(`${BASE}/api/v1/workspaces/${WS}/members/`, () =>
69
70
  HttpResponse.json(MEMBERS),
70
71
  ),
@@ -89,13 +90,13 @@ afterEach(() => {
89
90
 
90
91
  describe("issueGet", () => {
91
92
  it("prints full JSON for an issue", async () => {
92
- const { issueGet } = await import("@/commands/issue");
93
+ const { issueGetHandler } = await import("@/commands/issue");
93
94
  const logs: string[] = [];
94
95
  const orig = console.log;
95
96
  console.log = (...args: unknown[]) => logs.push(args.join(" "));
96
97
 
97
98
  try {
98
- await Effect.runPromise((issueGet as any).handler({ ref: "ACME-29" }));
99
+ await Effect.runPromise(issueGetHandler({ ref: "ACME-29" }));
99
100
  } finally {
100
101
  console.log = orig;
101
102
  }
@@ -136,18 +137,18 @@ describe("issuesList", () => {
136
137
  ),
137
138
  );
138
139
 
139
- const { issuesList } = await import("@/commands/issues");
140
+ const { issuesListHandler } = await import("@/commands/issues");
140
141
  const logs: string[] = [];
141
142
  const orig = console.log;
142
143
  console.log = (...args: unknown[]) => logs.push(args.join(" "));
143
144
 
144
145
  try {
145
146
  await Effect.runPromise(
146
- (issuesList as any).handler({
147
+ issuesListHandler({
147
148
  project: "ACME",
148
- state: { _tag: "Some", value: "completed" },
149
- assignee: { _tag: "None" },
150
- priority: { _tag: "None" },
149
+ state: Option.some("completed"),
150
+ assignee: Option.none(),
151
+ priority: Option.none(),
151
152
  }),
152
153
  );
153
154
  } finally {
@@ -187,18 +188,18 @@ describe("issuesList", () => {
187
188
  ),
188
189
  );
189
190
 
190
- const { issuesList } = await import("@/commands/issues");
191
+ const { issuesListHandler } = await import("@/commands/issues");
191
192
  const logs: string[] = [];
192
193
  const orig = console.log;
193
194
  console.log = (...args: unknown[]) => logs.push(args.join(" "));
194
195
 
195
196
  try {
196
197
  await Effect.runPromise(
197
- (issuesList as any).handler({
198
+ issuesListHandler({
198
199
  project: "ACME",
199
- state: { _tag: "None" },
200
- assignee: { _tag: "Some", value: "alice@example.com" },
201
- priority: { _tag: "None" },
200
+ state: Option.none(),
201
+ assignee: Option.some("alice@example.com"),
202
+ priority: Option.none(),
202
203
  }),
203
204
  );
204
205
  } finally {
@@ -238,18 +239,18 @@ describe("issuesList", () => {
238
239
  ),
239
240
  );
240
241
 
241
- const { issuesList } = await import("@/commands/issues");
242
+ const { issuesListHandler } = await import("@/commands/issues");
242
243
  const logs: string[] = [];
243
244
  const orig = console.log;
244
245
  console.log = (...args: unknown[]) => logs.push(args.join(" "));
245
246
 
246
247
  try {
247
248
  await Effect.runPromise(
248
- (issuesList as any).handler({
249
+ issuesListHandler({
249
250
  project: "ACME",
250
- state: { _tag: "None" },
251
- assignee: { _tag: "None" },
252
- priority: { _tag: "Some", value: "urgent" },
251
+ state: Option.none(),
252
+ assignee: Option.none(),
253
+ priority: Option.some("urgent"),
253
254
  }),
254
255
  );
255
256
  } finally {
@@ -268,7 +269,7 @@ describe("issueUpdate", () => {
268
269
  http.patch(
269
270
  `${BASE}/api/v1/workspaces/${WS}/projects/proj-acme/issues/i1/`,
270
271
  async ({ request }) => {
271
- const body = (await request.json()) as any;
272
+ const body = (await request.json()) as { state?: string };
272
273
  return HttpResponse.json({
273
274
  id: "i1",
274
275
  sequence_id: 29,
@@ -280,23 +281,21 @@ describe("issueUpdate", () => {
280
281
  ),
281
282
  );
282
283
 
283
- const { issueUpdate } = await import("@/commands/issue");
284
+ const { issueUpdateHandler } = await import("@/commands/issue");
284
285
  const logs: string[] = [];
285
286
  const orig = console.log;
286
287
  console.log = (...args: unknown[]) => logs.push(args.join(" "));
287
288
 
288
289
  try {
289
290
  await Effect.runPromise(
290
- (issueUpdate as any).handler({
291
+ issueUpdateHandler({
291
292
  ref: "ACME-29",
292
- state: { _tag: "Some", value: "completed" },
293
- priority: { _tag: "None" },
294
- title: { _tag: "None" },
295
- description: { _tag: "None" },
296
- assignee: { _tag: "None" },
297
- label: { _tag: "None" },
298
- estimate: { _tag: "None" },
299
-
293
+ state: Option.some("completed"),
294
+ priority: Option.none(),
295
+ title: Option.none(),
296
+ description: Option.none(),
297
+ assignee: Option.none(),
298
+ label: Option.none(),
300
299
  noAssignee: false,
301
300
  }),
302
301
  );
@@ -312,7 +311,7 @@ describe("issueUpdate", () => {
312
311
  http.patch(
313
312
  `${BASE}/api/v1/workspaces/${WS}/projects/proj-acme/issues/i1/`,
314
313
  async ({ request }) => {
315
- const body = (await request.json()) as any;
314
+ const body = (await request.json()) as { priority?: string };
316
315
  return HttpResponse.json({
317
316
  id: "i1",
318
317
  sequence_id: 29,
@@ -324,23 +323,21 @@ describe("issueUpdate", () => {
324
323
  ),
325
324
  );
326
325
 
327
- const { issueUpdate } = await import("@/commands/issue");
326
+ const { issueUpdateHandler } = await import("@/commands/issue");
328
327
  const logs: string[] = [];
329
328
  const orig = console.log;
330
329
  console.log = (...args: unknown[]) => logs.push(args.join(" "));
331
330
 
332
331
  try {
333
332
  await Effect.runPromise(
334
- (issueUpdate as any).handler({
333
+ issueUpdateHandler({
335
334
  ref: "ACME-29",
336
- state: { _tag: "None" },
337
- priority: { _tag: "Some", value: "urgent" },
338
- title: { _tag: "None" },
339
- description: { _tag: "None" },
340
- assignee: { _tag: "None" },
341
- label: { _tag: "None" },
342
- estimate: { _tag: "None" },
343
-
335
+ state: Option.none(),
336
+ priority: Option.some("urgent"),
337
+ title: Option.none(),
338
+ description: Option.none(),
339
+ assignee: Option.none(),
340
+ label: Option.none(),
344
341
  noAssignee: false,
345
342
  }),
346
343
  );
@@ -352,19 +349,17 @@ describe("issueUpdate", () => {
352
349
  });
353
350
 
354
351
  it("fails when nothing to update", async () => {
355
- const { issueUpdate } = await import("@/commands/issue");
352
+ const { issueUpdateHandler } = await import("@/commands/issue");
356
353
  const result = await Effect.runPromise(
357
354
  Effect.either(
358
- (issueUpdate as any).handler({
355
+ issueUpdateHandler({
359
356
  ref: "ACME-29",
360
- state: { _tag: "None" },
361
- priority: { _tag: "None" },
362
- title: { _tag: "None" },
363
- description: { _tag: "None" },
364
- assignee: { _tag: "None" },
365
- label: { _tag: "None" },
366
- estimate: { _tag: "None" },
367
-
357
+ state: Option.none(),
358
+ priority: Option.none(),
359
+ title: Option.none(),
360
+ description: Option.none(),
361
+ assignee: Option.none(),
362
+ label: Option.none(),
368
363
  noAssignee: false,
369
364
  }),
370
365
  ),
@@ -393,23 +388,21 @@ describe("issueUpdate", () => {
393
388
  ),
394
389
  );
395
390
 
396
- const { issueUpdate } = await import("@/commands/issue");
391
+ const { issueUpdateHandler } = await import("@/commands/issue");
397
392
  await Effect.runPromise(
398
- (issueUpdate as any).handler({
393
+ issueUpdateHandler({
399
394
  ref: "ACME-29",
400
- state: { _tag: "None" },
401
- priority: { _tag: "None" },
402
- title: { _tag: "Some", value: "New title" },
403
- description: { _tag: "None" },
404
- assignee: { _tag: "None" },
405
- label: { _tag: "None" },
406
- estimate: { _tag: "None" },
407
-
395
+ state: Option.none(),
396
+ priority: Option.none(),
397
+ title: Option.some("New title"),
398
+ description: Option.none(),
399
+ assignee: Option.none(),
400
+ label: Option.none(),
408
401
  noAssignee: false,
409
402
  }),
410
403
  );
411
404
 
412
- expect((patchedBody as any).name).toBe("New title");
405
+ expect((patchedBody as { name?: string }).name).toBe("New title");
413
406
  });
414
407
  });
415
408
 
@@ -426,14 +419,14 @@ describe("issueComment", () => {
426
419
  ),
427
420
  );
428
421
 
429
- const { issueComment } = await import("@/commands/issue");
422
+ const { issueCommentHandler } = await import("@/commands/issue");
430
423
  const logs: string[] = [];
431
424
  const orig = console.log;
432
425
  console.log = (...args: unknown[]) => logs.push(args.join(" "));
433
426
 
434
427
  try {
435
428
  await Effect.runPromise(
436
- (issueComment as any).handler({
429
+ issueCommentHandler({
437
430
  ref: "ACME-29",
438
431
  text: "Fixed in latest build",
439
432
  }),
@@ -442,7 +435,9 @@ describe("issueComment", () => {
442
435
  console.log = orig;
443
436
  }
444
437
 
445
- expect((postedBody as any).comment_html).toContain("Fixed in latest build");
438
+ expect((postedBody as { comment_html?: string }).comment_html).toContain(
439
+ "Fixed in latest build",
440
+ );
446
441
  expect(logs.join("\n")).toContain("Comment added to ACME-29");
447
442
  });
448
443
 
@@ -458,10 +453,10 @@ describe("issueComment", () => {
458
453
  ),
459
454
  );
460
455
 
461
- const { issueComment } = await import("@/commands/issue");
456
+ const { issueCommentHandler } = await import("@/commands/issue");
462
457
  try {
463
458
  await Effect.runPromise(
464
- (issueComment as any).handler({
459
+ issueCommentHandler({
465
460
  ref: "ACME-29",
466
461
  text: "<script>alert(1)</script>",
467
462
  }),
@@ -469,8 +464,12 @@ describe("issueComment", () => {
469
464
  } finally {
470
465
  }
471
466
 
472
- expect((postedBody as any).comment_html).toContain("&lt;script&gt;");
473
- expect((postedBody as any).comment_html).not.toContain("<script>");
467
+ expect((postedBody as { comment_html?: string }).comment_html).toContain(
468
+ "&lt;script&gt;",
469
+ );
470
+ expect(
471
+ (postedBody as { comment_html?: string }).comment_html,
472
+ ).not.toContain("<script>");
474
473
  });
475
474
  });
476
475
 
@@ -480,7 +479,7 @@ describe("issueCreate", () => {
480
479
  http.post(
481
480
  `${BASE}/api/v1/workspaces/${WS}/projects/proj-acme/issues/`,
482
481
  async ({ request }) => {
483
- const body = (await request.json()) as any;
482
+ const body = (await request.json()) as { name?: string };
484
483
  return HttpResponse.json({
485
484
  id: "new-i",
486
485
  sequence_id: 99,
@@ -492,22 +491,21 @@ describe("issueCreate", () => {
492
491
  ),
493
492
  );
494
493
 
495
- const { issueCreate } = await import("@/commands/issue");
494
+ const { issueCreateHandler } = await import("@/commands/issue");
496
495
  const logs: string[] = [];
497
496
  const orig = console.log;
498
497
  console.log = (...args: unknown[]) => logs.push(args.join(" "));
499
498
 
500
499
  try {
501
500
  await Effect.runPromise(
502
- (issueCreate as any).handler({
501
+ issueCreateHandler({
503
502
  project: "ACME",
504
503
  title: "New issue",
505
- priority: { _tag: "None" },
506
- state: { _tag: "None" },
507
- description: { _tag: "None" },
508
- assignee: { _tag: "None" },
509
- estimate: { _tag: "None" },
510
- label: { _tag: "None" },
504
+ priority: Option.none(),
505
+ state: Option.none(),
506
+ description: Option.none(),
507
+ assignee: Option.none(),
508
+ label: Option.none(),
511
509
  }),
512
510
  );
513
511
  } finally {
@@ -523,7 +521,11 @@ describe("issueCreate", () => {
523
521
  http.post(
524
522
  `${BASE}/api/v1/workspaces/${WS}/projects/proj-acme/issues/`,
525
523
  async ({ request }) => {
526
- const body = (await request.json()) as any;
524
+ const body = (await request.json()) as {
525
+ name?: string;
526
+ priority?: string;
527
+ state?: string;
528
+ };
527
529
  return HttpResponse.json({
528
530
  id: "new-i2",
529
531
  sequence_id: 100,
@@ -535,22 +537,21 @@ describe("issueCreate", () => {
535
537
  ),
536
538
  );
537
539
 
538
- const { issueCreate } = await import("@/commands/issue");
540
+ const { issueCreateHandler } = await import("@/commands/issue");
539
541
  const logs: string[] = [];
540
542
  const orig = console.log;
541
543
  console.log = (...args: unknown[]) => logs.push(args.join(" "));
542
544
 
543
545
  try {
544
546
  await Effect.runPromise(
545
- (issueCreate as any).handler({
547
+ issueCreateHandler({
546
548
  project: "ACME",
547
549
  title: "High priority issue",
548
- priority: { _tag: "Some", value: "high" },
549
- state: { _tag: "Some", value: "completed" },
550
- description: { _tag: "None" },
551
- assignee: { _tag: "None" },
552
- estimate: { _tag: "None" },
553
- label: { _tag: "None" },
550
+ priority: Option.some("high"),
551
+ state: Option.some("completed"),
552
+ description: Option.none(),
553
+ assignee: Option.none(),
554
+ label: Option.none(),
554
555
  }),
555
556
  );
556
557
  } finally {
@@ -572,7 +573,7 @@ describe("issueCreate description", () => {
572
573
  return HttpResponse.json({
573
574
  id: "new-i3",
574
575
  sequence_id: 101,
575
- name: (postedBody as any).name,
576
+ name: (postedBody as { name?: string }).name,
576
577
  priority: "none",
577
578
  state: "s1",
578
579
  });
@@ -580,21 +581,20 @@ describe("issueCreate description", () => {
580
581
  ),
581
582
  );
582
583
 
583
- const { issueCreate } = await import("@/commands/issue");
584
+ const { issueCreateHandler } = await import("@/commands/issue");
584
585
  await Effect.runPromise(
585
- (issueCreate as any).handler({
586
+ issueCreateHandler({
586
587
  project: "ACME",
587
588
  title: "Issue with description",
588
- priority: { _tag: "None" },
589
- state: { _tag: "None" },
590
- description: { _tag: "Some", value: "Some context here" },
591
- assignee: { _tag: "None" },
592
- estimate: { _tag: "None" },
593
- label: { _tag: "None" },
589
+ priority: Option.none(),
590
+ state: Option.none(),
591
+ description: Option.some("Some context here"),
592
+ assignee: Option.none(),
593
+ label: Option.none(),
594
594
  }),
595
595
  );
596
596
 
597
- expect((postedBody as any).description_html).toBe(
597
+ expect((postedBody as { description_html?: string }).description_html).toBe(
598
598
  "<p>Some context here</p>",
599
599
  );
600
600
  });
@@ -609,7 +609,7 @@ describe("issueCreate description", () => {
609
609
  return HttpResponse.json({
610
610
  id: "new-i4",
611
611
  sequence_id: 102,
612
- name: (postedBody as any).name,
612
+ name: (postedBody as { name?: string }).name,
613
613
  priority: "none",
614
614
  state: "s1",
615
615
  });
@@ -617,22 +617,25 @@ describe("issueCreate description", () => {
617
617
  ),
618
618
  );
619
619
 
620
- const { issueCreate } = await import("@/commands/issue");
620
+ const { issueCreateHandler } = await import("@/commands/issue");
621
621
  await Effect.runPromise(
622
- (issueCreate as any).handler({
622
+ issueCreateHandler({
623
623
  project: "ACME",
624
624
  title: "XSS test",
625
- priority: { _tag: "None" },
626
- state: { _tag: "None" },
627
- description: { _tag: "Some", value: "<script>alert(1)</script>" },
628
- assignee: { _tag: "None" },
629
- estimate: { _tag: "None" },
630
- label: { _tag: "None" },
625
+ priority: Option.none(),
626
+ state: Option.none(),
627
+ description: Option.some("<script>alert(1)</script>"),
628
+ assignee: Option.none(),
629
+ label: Option.none(),
631
630
  }),
632
631
  );
633
632
 
634
- expect((postedBody as any).description_html).toContain("&lt;script&gt;");
635
- expect((postedBody as any).description_html).not.toContain("<script>");
633
+ expect(
634
+ (postedBody as { description_html?: string }).description_html,
635
+ ).toContain("&lt;script&gt;");
636
+ expect(
637
+ (postedBody as { description_html?: string }).description_html,
638
+ ).not.toContain("<script>");
636
639
  });
637
640
  });
638
641
 
@@ -655,25 +658,23 @@ describe("issueUpdate description", () => {
655
658
  ),
656
659
  );
657
660
 
658
- const { issueUpdate } = await import("@/commands/issue");
661
+ const { issueUpdateHandler } = await import("@/commands/issue");
659
662
  await Effect.runPromise(
660
- (issueUpdate as any).handler({
663
+ issueUpdateHandler({
661
664
  ref: "ACME-29",
662
- state: { _tag: "None" },
663
- priority: { _tag: "None" },
664
- title: { _tag: "None" },
665
- description: { _tag: "Some", value: "Updated description" },
666
- assignee: { _tag: "None" },
667
- label: { _tag: "None" },
668
- estimate: { _tag: "None" },
669
-
665
+ state: Option.none(),
666
+ priority: Option.none(),
667
+ title: Option.none(),
668
+ description: Option.some("Updated description"),
669
+ assignee: Option.none(),
670
+ label: Option.none(),
670
671
  noAssignee: false,
671
672
  }),
672
673
  );
673
674
 
674
- expect((patchedBody as any).description_html).toBe(
675
- "<p>Updated description</p>",
676
- );
675
+ expect(
676
+ (patchedBody as { description_html?: string }).description_html,
677
+ ).toBe("<p>Updated description</p>");
677
678
  });
678
679
 
679
680
  it("HTML-escapes angle brackets in update description", async () => {
@@ -694,24 +695,26 @@ describe("issueUpdate description", () => {
694
695
  ),
695
696
  );
696
697
 
697
- const { issueUpdate } = await import("@/commands/issue");
698
+ const { issueUpdateHandler } = await import("@/commands/issue");
698
699
  await Effect.runPromise(
699
- (issueUpdate as any).handler({
700
+ issueUpdateHandler({
700
701
  ref: "ACME-29",
701
- state: { _tag: "None" },
702
- priority: { _tag: "None" },
703
- title: { _tag: "None" },
704
- description: { _tag: "Some", value: "<b>bold</b>" },
705
- assignee: { _tag: "None" },
706
- label: { _tag: "None" },
707
- estimate: { _tag: "None" },
708
-
702
+ state: Option.none(),
703
+ priority: Option.none(),
704
+ title: Option.none(),
705
+ description: Option.some("<b>bold</b>"),
706
+ assignee: Option.none(),
707
+ label: Option.none(),
709
708
  noAssignee: false,
710
709
  }),
711
710
  );
712
711
 
713
- expect((patchedBody as any).description_html).toContain("&lt;b&gt;");
714
- expect((patchedBody as any).description_html).not.toContain("<b>");
712
+ expect(
713
+ (patchedBody as { description_html?: string }).description_html,
714
+ ).toContain("&lt;b&gt;");
715
+ expect(
716
+ (patchedBody as { description_html?: string }).description_html,
717
+ ).not.toContain("<b>");
715
718
  });
716
719
  });
717
720
 
@@ -734,23 +737,23 @@ describe("issueUpdate assignee", () => {
734
737
  ),
735
738
  );
736
739
 
737
- const { issueUpdate } = await import("@/commands/issue");
740
+ const { issueUpdateHandler } = await import("@/commands/issue");
738
741
  await Effect.runPromise(
739
- (issueUpdate as any).handler({
742
+ issueUpdateHandler({
740
743
  ref: "ACME-29",
741
- state: { _tag: "None" },
742
- priority: { _tag: "None" },
743
- title: { _tag: "None" },
744
- description: { _tag: "None" },
745
- assignee: { _tag: "Some", value: "Alice" },
746
- label: { _tag: "None" },
747
- estimate: { _tag: "None" },
748
-
744
+ state: Option.none(),
745
+ priority: Option.none(),
746
+ title: Option.none(),
747
+ description: Option.none(),
748
+ assignee: Option.some("Alice"),
749
+ label: Option.none(),
749
750
  noAssignee: false,
750
751
  }),
751
752
  );
752
753
 
753
- expect((patchedBody as any).assignees).toEqual(["m-alice"]);
754
+ expect((patchedBody as { assignees?: string[] }).assignees).toEqual([
755
+ "m-alice",
756
+ ]);
754
757
  });
755
758
 
756
759
  it("clears assignees with --no-assignee", async () => {
@@ -771,23 +774,21 @@ describe("issueUpdate assignee", () => {
771
774
  ),
772
775
  );
773
776
 
774
- const { issueUpdate } = await import("@/commands/issue");
777
+ const { issueUpdateHandler } = await import("@/commands/issue");
775
778
  await Effect.runPromise(
776
- (issueUpdate as any).handler({
779
+ issueUpdateHandler({
777
780
  ref: "ACME-29",
778
- state: { _tag: "None" },
779
- priority: { _tag: "None" },
780
- title: { _tag: "None" },
781
- description: { _tag: "None" },
782
- assignee: { _tag: "None" },
783
- label: { _tag: "None" },
784
- estimate: { _tag: "None" },
785
-
781
+ state: Option.none(),
782
+ priority: Option.none(),
783
+ title: Option.none(),
784
+ description: Option.none(),
785
+ assignee: Option.none(),
786
+ label: Option.none(),
786
787
  noAssignee: true,
787
788
  }),
788
789
  );
789
790
 
790
- expect((patchedBody as any).assignees).toEqual([]);
791
+ expect((patchedBody as { assignees?: string[] }).assignees).toEqual([]);
791
792
  });
792
793
 
793
794
  it("resolves assignee by email", async () => {
@@ -808,23 +809,23 @@ describe("issueUpdate assignee", () => {
808
809
  ),
809
810
  );
810
811
 
811
- const { issueUpdate } = await import("@/commands/issue");
812
+ const { issueUpdateHandler } = await import("@/commands/issue");
812
813
  await Effect.runPromise(
813
- (issueUpdate as any).handler({
814
+ issueUpdateHandler({
814
815
  ref: "ACME-29",
815
- state: { _tag: "None" },
816
- priority: { _tag: "None" },
817
- title: { _tag: "None" },
818
- description: { _tag: "None" },
819
- assignee: { _tag: "Some", value: "bob@example.com" },
820
- label: { _tag: "None" },
821
- estimate: { _tag: "None" },
822
-
816
+ state: Option.none(),
817
+ priority: Option.none(),
818
+ title: Option.none(),
819
+ description: Option.none(),
820
+ assignee: Option.some("bob@example.com"),
821
+ label: Option.none(),
823
822
  noAssignee: false,
824
823
  }),
825
824
  );
826
825
 
827
- expect((patchedBody as any).assignees).toEqual(["m-bob"]);
826
+ expect((patchedBody as { assignees?: string[] }).assignees).toEqual([
827
+ "m-bob",
828
+ ]);
828
829
  });
829
830
  });
830
831
 
@@ -839,7 +840,7 @@ describe("issueCreate assignee", () => {
839
840
  return HttpResponse.json({
840
841
  id: "new-assignee",
841
842
  sequence_id: 300,
842
- name: (postedBody as any).name,
843
+ name: (postedBody as { name?: string }).name,
843
844
  priority: "none",
844
845
  state: "s1",
845
846
  });
@@ -847,21 +848,22 @@ describe("issueCreate assignee", () => {
847
848
  ),
848
849
  );
849
850
 
850
- const { issueCreate } = await import("@/commands/issue");
851
+ const { issueCreateHandler } = await import("@/commands/issue");
851
852
  await Effect.runPromise(
852
- (issueCreate as any).handler({
853
+ issueCreateHandler({
853
854
  project: "ACME",
854
855
  title: "Assigned issue",
855
- priority: { _tag: "None" },
856
- state: { _tag: "None" },
857
- description: { _tag: "None" },
858
- assignee: { _tag: "Some", value: "Alice" },
859
- estimate: { _tag: "None" },
860
- label: { _tag: "None" },
856
+ priority: Option.none(),
857
+ state: Option.none(),
858
+ description: Option.none(),
859
+ assignee: Option.some("Alice"),
860
+ label: Option.none(),
861
861
  }),
862
862
  );
863
863
 
864
- expect((postedBody as any).assignees).toEqual(["m-alice"]);
864
+ expect((postedBody as { assignees?: string[] }).assignees).toEqual([
865
+ "m-alice",
866
+ ]);
865
867
  });
866
868
  });
867
869
 
@@ -884,23 +886,23 @@ describe("issueUpdate label", () => {
884
886
  ),
885
887
  );
886
888
 
887
- const { issueUpdate } = await import("@/commands/issue");
889
+ const { issueUpdateHandler } = await import("@/commands/issue");
888
890
  await Effect.runPromise(
889
- (issueUpdate as any).handler({
891
+ issueUpdateHandler({
890
892
  ref: "ACME-29",
891
- state: { _tag: "None" },
892
- priority: { _tag: "None" },
893
- title: { _tag: "None" },
894
- description: { _tag: "None" },
895
- assignee: { _tag: "None" },
896
- label: { _tag: "Some", value: "bug" },
897
- estimate: { _tag: "None" },
898
-
893
+ state: Option.none(),
894
+ priority: Option.none(),
895
+ title: Option.none(),
896
+ description: Option.none(),
897
+ assignee: Option.none(),
898
+ label: Option.some("bug"),
899
899
  noAssignee: false,
900
900
  }),
901
901
  );
902
902
 
903
- expect((patchedBody as any).label_ids).toEqual(["l-bug"]);
903
+ expect((patchedBody as { label_ids?: string[] }).label_ids).toEqual([
904
+ "l-bug",
905
+ ]);
904
906
  });
905
907
  });
906
908
 
@@ -915,7 +917,7 @@ describe("issueCreate label", () => {
915
917
  return HttpResponse.json({
916
918
  id: "new-label",
917
919
  sequence_id: 301,
918
- name: (postedBody as any).name,
920
+ name: (postedBody as { name?: string }).name,
919
921
  priority: "none",
920
922
  state: "s1",
921
923
  });
@@ -923,21 +925,22 @@ describe("issueCreate label", () => {
923
925
  ),
924
926
  );
925
927
 
926
- const { issueCreate } = await import("@/commands/issue");
928
+ const { issueCreateHandler } = await import("@/commands/issue");
927
929
  await Effect.runPromise(
928
- (issueCreate as any).handler({
930
+ issueCreateHandler({
929
931
  project: "ACME",
930
932
  title: "Labeled issue",
931
- priority: { _tag: "None" },
932
- state: { _tag: "None" },
933
- description: { _tag: "None" },
934
- assignee: { _tag: "None" },
935
- label: { _tag: "Some", value: "Bug" },
936
- estimate: { _tag: "None" },
933
+ priority: Option.none(),
934
+ state: Option.none(),
935
+ description: Option.none(),
936
+ assignee: Option.none(),
937
+ label: Option.some("Bug"),
937
938
  }),
938
939
  );
939
940
 
940
- expect((postedBody as any).label_ids).toEqual(["l-bug"]);
941
+ expect((postedBody as { label_ids?: string[] }).label_ids).toEqual([
942
+ "l-bug",
943
+ ]);
941
944
  });
942
945
  });
943
946
 
@@ -954,13 +957,13 @@ describe("issueDelete", () => {
954
957
  ),
955
958
  );
956
959
 
957
- const { issueDelete } = await import("@/commands/issue");
960
+ const { issueDeleteHandler } = await import("@/commands/issue");
958
961
  const logs: string[] = [];
959
962
  const orig = console.log;
960
963
  console.log = (...args: unknown[]) => logs.push(args.join(" "));
961
964
 
962
965
  try {
963
- await Effect.runPromise((issueDelete as any).handler({ ref: "ACME-29" }));
966
+ await Effect.runPromise(issueDeleteHandler({ ref: "ACME-29" }));
964
967
  } finally {
965
968
  console.log = orig;
966
969
  }
@@ -970,81 +973,6 @@ describe("issueDelete", () => {
970
973
  });
971
974
  });
972
975
 
973
- describe("issueUpdate estimate", () => {
974
- it("sets estimate on update", async () => {
975
- let patchedBody: unknown;
976
- server.use(
977
- http.patch(
978
- `${BASE}/api/v1/workspaces/${WS}/projects/proj-acme/issues/i1/`,
979
- async ({ request }) => {
980
- patchedBody = await request.json();
981
- return HttpResponse.json({
982
- id: "i1",
983
- sequence_id: 29,
984
- name: "Migrate Button",
985
- priority: "high",
986
- state: "s1",
987
- });
988
- },
989
- ),
990
- );
991
-
992
- const { issueUpdate } = await import("@/commands/issue");
993
- await Effect.runPromise(
994
- (issueUpdate as any).handler({
995
- ref: "ACME-29",
996
- state: { _tag: "None" },
997
- priority: { _tag: "None" },
998
- title: { _tag: "None" },
999
- description: { _tag: "None" },
1000
- assignee: { _tag: "None" },
1001
- label: { _tag: "None" },
1002
- estimate: { _tag: "Some", value: 3 },
1003
- noAssignee: false,
1004
- }),
1005
- );
1006
-
1007
- expect((patchedBody as any).estimate_point).toBe(3);
1008
- });
1009
- });
1010
-
1011
- describe("issueCreate estimate", () => {
1012
- it("sets estimate on create", async () => {
1013
- let postedBody: unknown;
1014
- server.use(
1015
- http.post(
1016
- `${BASE}/api/v1/workspaces/${WS}/projects/proj-acme/issues/`,
1017
- async ({ request }) => {
1018
- postedBody = await request.json();
1019
- return HttpResponse.json({
1020
- id: "new-est",
1021
- sequence_id: 400,
1022
- name: (postedBody as any).name,
1023
- priority: "none",
1024
- state: "s1",
1025
- });
1026
- },
1027
- ),
1028
- );
1029
-
1030
- const { issueCreate } = await import("@/commands/issue");
1031
- await Effect.runPromise(
1032
- (issueCreate as any).handler({
1033
- project: "ACME",
1034
- title: "Estimated issue",
1035
- priority: { _tag: "None" },
1036
- state: { _tag: "None" },
1037
- description: { _tag: "None" },
1038
- assignee: { _tag: "None" },
1039
- label: { _tag: "None" },
1040
- estimate: { _tag: "Some", value: 5 },
1041
- }),
1042
- );
1043
-
1044
- expect((postedBody as any).estimate_point).toBe(5);
1045
- });
1046
- });
1047
-
1048
976
  describe("--description argv parsing", () => {
1049
977
  async function runCli(argv: string[]): Promise<{ logs: string[] }> {
1050
978
  const { issue } = await import("@/commands/issue");
@@ -1084,7 +1012,7 @@ describe("--description argv parsing", () => {
1084
1012
  return HttpResponse.json({
1085
1013
  id: "argv-i1",
1086
1014
  sequence_id: 200,
1087
- name: (postedBody as any).name,
1015
+ name: (postedBody as { name?: string }).name,
1088
1016
  priority: "none",
1089
1017
  state: "s1",
1090
1018
  });
@@ -1101,7 +1029,9 @@ describe("--description argv parsing", () => {
1101
1029
  "Argv test issue",
1102
1030
  ]);
1103
1031
  expect(logs.join("\n")).toContain("Created");
1104
- expect((postedBody as any).description_html).toBe("<p>Hello world</p>");
1032
+ expect((postedBody as { description_html?: string }).description_html).toBe(
1033
+ "<p>Hello world</p>",
1034
+ );
1105
1035
  });
1106
1036
 
1107
1037
  it("issue create HTML-escapes & in description via argv", async () => {
@@ -1114,7 +1044,7 @@ describe("--description argv parsing", () => {
1114
1044
  return HttpResponse.json({
1115
1045
  id: "argv-i2",
1116
1046
  sequence_id: 201,
1117
- name: (postedBody as any).name,
1047
+ name: (postedBody as { name?: string }).name,
1118
1048
  priority: "none",
1119
1049
  state: "s1",
1120
1050
  });
@@ -1130,7 +1060,9 @@ describe("--description argv parsing", () => {
1130
1060
  "ACME",
1131
1061
  "Ampersand test",
1132
1062
  ]);
1133
- expect((postedBody as any).description_html).toBe("<p>a &amp; b</p>");
1063
+ expect((postedBody as { description_html?: string }).description_html).toBe(
1064
+ "<p>a &amp; b</p>",
1065
+ );
1134
1066
  });
1135
1067
 
1136
1068
  it("issue update passes --description to API via argv", async () => {
@@ -1152,6 +1084,8 @@ describe("--description argv parsing", () => {
1152
1084
  );
1153
1085
 
1154
1086
  await runCli(["issue", "update", "--description", "New desc", "ACME-29"]);
1155
- expect((patchedBody as any).description_html).toBe("<p>New desc</p>");
1087
+ expect(
1088
+ (patchedBody as { description_html?: string }).description_html,
1089
+ ).toBe("<p>New desc</p>");
1156
1090
  });
1157
1091
  });