@bifos/dooray-cli 0.5.4 → 0.7.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 +172 -43
- package/dist/index.js +1153 -166
- package/package.json +2 -2
- package/skills/dooray-cli/SKILL.md +91 -17
package/dist/index.js
CHANGED
|
@@ -24,7 +24,7 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
24
24
|
));
|
|
25
25
|
|
|
26
26
|
// src/index.ts
|
|
27
|
-
var
|
|
27
|
+
var import_commander47 = require("commander");
|
|
28
28
|
var import_chalk7 = __toESM(require("chalk"));
|
|
29
29
|
|
|
30
30
|
// src/commands/config.ts
|
|
@@ -127,10 +127,13 @@ async function setConfigValue(key, value) {
|
|
|
127
127
|
case "smtp-port":
|
|
128
128
|
config.smtpPort = parseInt(value, 10);
|
|
129
129
|
break;
|
|
130
|
+
case "track-last-run":
|
|
131
|
+
config.trackLastRun = value === "true";
|
|
132
|
+
break;
|
|
130
133
|
default:
|
|
131
134
|
throw new DoorayCliError(
|
|
132
135
|
`\uC54C \uC218 \uC5C6\uB294 \uC124\uC815 \uD0A4: ${key}
|
|
133
|
-
\uC0AC\uC6A9 \uAC00\uB2A5\uD55C \uD0A4: api-key, base-url, tenant-name, imap-host, imap-port, imap-username, imap-password, smtp-host, smtp-port`,
|
|
136
|
+
\uC0AC\uC6A9 \uAC00\uB2A5\uD55C \uD0A4: api-key, base-url, tenant-name, imap-host, imap-port, imap-username, imap-password, smtp-host, smtp-port, track-last-run`,
|
|
134
137
|
EXIT_CONFIG_ERROR
|
|
135
138
|
);
|
|
136
139
|
}
|
|
@@ -411,7 +414,7 @@ var DoorayApiClient = class {
|
|
|
411
414
|
try {
|
|
412
415
|
return await this.api.get("common/v1/members/me").json();
|
|
413
416
|
} catch (e) {
|
|
414
|
-
return toDoorayCliError(e);
|
|
417
|
+
return await toDoorayCliError(e);
|
|
415
418
|
}
|
|
416
419
|
}
|
|
417
420
|
// ─── Projects ───────────────────────────────────────
|
|
@@ -428,7 +431,7 @@ var DoorayApiClient = class {
|
|
|
428
431
|
}
|
|
429
432
|
}).json();
|
|
430
433
|
} catch (e) {
|
|
431
|
-
return toDoorayCliError(e);
|
|
434
|
+
return await toDoorayCliError(e);
|
|
432
435
|
}
|
|
433
436
|
}
|
|
434
437
|
// ─── Posts ──────────────────────────────────────────
|
|
@@ -455,42 +458,42 @@ var DoorayApiClient = class {
|
|
|
455
458
|
}
|
|
456
459
|
}).json();
|
|
457
460
|
} catch (e) {
|
|
458
|
-
return toDoorayCliError(e);
|
|
461
|
+
return await toDoorayCliError(e);
|
|
459
462
|
}
|
|
460
463
|
}
|
|
461
464
|
async getPost(projectId, postId) {
|
|
462
465
|
try {
|
|
463
466
|
return await this.api.get(`project/v1/projects/${projectId}/posts/${postId}`).json();
|
|
464
467
|
} catch (e) {
|
|
465
|
-
return toDoorayCliError(e);
|
|
468
|
+
return await toDoorayCliError(e);
|
|
466
469
|
}
|
|
467
470
|
}
|
|
468
471
|
async getPostStandalone(postId) {
|
|
469
472
|
try {
|
|
470
473
|
return await this.api.get(`project/v1/posts/${postId}`).json();
|
|
471
474
|
} catch (e) {
|
|
472
|
-
return toDoorayCliError(e);
|
|
475
|
+
return await toDoorayCliError(e);
|
|
473
476
|
}
|
|
474
477
|
}
|
|
475
478
|
async createPost(projectId, body) {
|
|
476
479
|
try {
|
|
477
480
|
return await this.api.post(`project/v1/projects/${projectId}/posts`, { json: body }).json();
|
|
478
481
|
} catch (e) {
|
|
479
|
-
return toDoorayCliError(e);
|
|
482
|
+
return await toDoorayCliError(e);
|
|
480
483
|
}
|
|
481
484
|
}
|
|
482
485
|
async updatePost(projectId, postId, body) {
|
|
483
486
|
try {
|
|
484
487
|
return await this.api.put(`project/v1/projects/${projectId}/posts/${postId}`, { json: body }).json();
|
|
485
488
|
} catch (e) {
|
|
486
|
-
return toDoorayCliError(e);
|
|
489
|
+
return await toDoorayCliError(e);
|
|
487
490
|
}
|
|
488
491
|
}
|
|
489
492
|
async setPostDone(projectId, postId) {
|
|
490
493
|
try {
|
|
491
494
|
return await this.api.post(`project/v1/projects/${projectId}/posts/${postId}/set-done`).json();
|
|
492
495
|
} catch (e) {
|
|
493
|
-
return toDoorayCliError(e);
|
|
496
|
+
return await toDoorayCliError(e);
|
|
494
497
|
}
|
|
495
498
|
}
|
|
496
499
|
async setPostWorkflow(projectId, postId, workflowId) {
|
|
@@ -499,7 +502,7 @@ var DoorayApiClient = class {
|
|
|
499
502
|
json: { workflowId }
|
|
500
503
|
}).json();
|
|
501
504
|
} catch (e) {
|
|
502
|
-
return toDoorayCliError(e);
|
|
505
|
+
return await toDoorayCliError(e);
|
|
503
506
|
}
|
|
504
507
|
}
|
|
505
508
|
async setPostParent(projectId, postId, parentPostId) {
|
|
@@ -508,7 +511,7 @@ var DoorayApiClient = class {
|
|
|
508
511
|
json: { parentPostId }
|
|
509
512
|
}).json();
|
|
510
513
|
} catch (e) {
|
|
511
|
-
return toDoorayCliError(e);
|
|
514
|
+
return await toDoorayCliError(e);
|
|
512
515
|
}
|
|
513
516
|
}
|
|
514
517
|
// ─── Post Comments ──────────────────────────────────
|
|
@@ -522,28 +525,35 @@ var DoorayApiClient = class {
|
|
|
522
525
|
}
|
|
523
526
|
}).json();
|
|
524
527
|
} catch (e) {
|
|
525
|
-
return toDoorayCliError(e);
|
|
528
|
+
return await toDoorayCliError(e);
|
|
529
|
+
}
|
|
530
|
+
}
|
|
531
|
+
async getPostComment(projectId, postId, logId) {
|
|
532
|
+
try {
|
|
533
|
+
return await this.api.get(`project/v1/projects/${projectId}/posts/${postId}/logs/${logId}`).json();
|
|
534
|
+
} catch (e) {
|
|
535
|
+
return await toDoorayCliError(e);
|
|
526
536
|
}
|
|
527
537
|
}
|
|
528
538
|
async createPostComment(projectId, postId, body) {
|
|
529
539
|
try {
|
|
530
540
|
return await this.api.post(`project/v1/projects/${projectId}/posts/${postId}/logs`, { json: body }).json();
|
|
531
541
|
} catch (e) {
|
|
532
|
-
return toDoorayCliError(e);
|
|
542
|
+
return await toDoorayCliError(e);
|
|
533
543
|
}
|
|
534
544
|
}
|
|
535
545
|
async updatePostComment(projectId, postId, logId, body) {
|
|
536
546
|
try {
|
|
537
547
|
return await this.api.put(`project/v1/projects/${projectId}/posts/${postId}/logs/${logId}`, { json: body }).json();
|
|
538
548
|
} catch (e) {
|
|
539
|
-
return toDoorayCliError(e);
|
|
549
|
+
return await toDoorayCliError(e);
|
|
540
550
|
}
|
|
541
551
|
}
|
|
542
552
|
async deletePostComment(projectId, postId, logId) {
|
|
543
553
|
try {
|
|
544
554
|
return await this.api.delete(`project/v1/projects/${projectId}/posts/${postId}/logs/${logId}`).json();
|
|
545
555
|
} catch (e) {
|
|
546
|
-
return toDoorayCliError(e);
|
|
556
|
+
return await toDoorayCliError(e);
|
|
547
557
|
}
|
|
548
558
|
}
|
|
549
559
|
// ─── Members ────────────────────────────────────────
|
|
@@ -557,14 +567,31 @@ var DoorayApiClient = class {
|
|
|
557
567
|
}
|
|
558
568
|
}).json();
|
|
559
569
|
} catch (e) {
|
|
560
|
-
return toDoorayCliError(e);
|
|
570
|
+
return await toDoorayCliError(e);
|
|
561
571
|
}
|
|
562
572
|
}
|
|
563
573
|
async getMemberDetail(memberId) {
|
|
564
574
|
try {
|
|
565
575
|
return await this.api.get(`common/v1/members/${memberId}`).json();
|
|
566
576
|
} catch (e) {
|
|
567
|
-
return toDoorayCliError(e);
|
|
577
|
+
return await toDoorayCliError(e);
|
|
578
|
+
}
|
|
579
|
+
}
|
|
580
|
+
async searchMembers(params) {
|
|
581
|
+
try {
|
|
582
|
+
return await this.api.get("common/v1/members", {
|
|
583
|
+
searchParams: {
|
|
584
|
+
...params.name && { name: params.name },
|
|
585
|
+
...params.externalEmailAddresses && { externalEmailAddresses: params.externalEmailAddresses },
|
|
586
|
+
...params.userCode && { userCode: params.userCode },
|
|
587
|
+
...params.userCodeExact && { userCodeExact: params.userCodeExact },
|
|
588
|
+
...params.idProviderUserId && { idProviderUserId: params.idProviderUserId },
|
|
589
|
+
...params.page != null && { page: params.page },
|
|
590
|
+
...params.size != null && { size: params.size }
|
|
591
|
+
}
|
|
592
|
+
}).json();
|
|
593
|
+
} catch (e) {
|
|
594
|
+
return await toDoorayCliError(e);
|
|
568
595
|
}
|
|
569
596
|
}
|
|
570
597
|
// ─── Workflows ──────────────────────────────────────
|
|
@@ -572,7 +599,7 @@ var DoorayApiClient = class {
|
|
|
572
599
|
try {
|
|
573
600
|
return await this.api.get(`project/v1/projects/${projectId}/workflows`).json();
|
|
574
601
|
} catch (e) {
|
|
575
|
-
return toDoorayCliError(e);
|
|
602
|
+
return await toDoorayCliError(e);
|
|
576
603
|
}
|
|
577
604
|
}
|
|
578
605
|
// ─── Tags ───────────────────────────────────────────
|
|
@@ -585,7 +612,7 @@ var DoorayApiClient = class {
|
|
|
585
612
|
}
|
|
586
613
|
}).json();
|
|
587
614
|
} catch (e) {
|
|
588
|
-
return toDoorayCliError(e);
|
|
615
|
+
return await toDoorayCliError(e);
|
|
589
616
|
}
|
|
590
617
|
}
|
|
591
618
|
// ─── Member Groups ──────────────────────────────────
|
|
@@ -598,7 +625,7 @@ var DoorayApiClient = class {
|
|
|
598
625
|
}
|
|
599
626
|
}).json();
|
|
600
627
|
} catch (e) {
|
|
601
|
-
return toDoorayCliError(e);
|
|
628
|
+
return await toDoorayCliError(e);
|
|
602
629
|
}
|
|
603
630
|
}
|
|
604
631
|
// ─── Milestones ─────────────────────────────────────
|
|
@@ -611,7 +638,7 @@ var DoorayApiClient = class {
|
|
|
611
638
|
}
|
|
612
639
|
}).json();
|
|
613
640
|
} catch (e) {
|
|
614
|
-
return toDoorayCliError(e);
|
|
641
|
+
return await toDoorayCliError(e);
|
|
615
642
|
}
|
|
616
643
|
}
|
|
617
644
|
// ─── Wiki ───────────────────────────────────────────
|
|
@@ -624,7 +651,7 @@ var DoorayApiClient = class {
|
|
|
624
651
|
}
|
|
625
652
|
}).json();
|
|
626
653
|
} catch (e) {
|
|
627
|
-
return toDoorayCliError(e);
|
|
654
|
+
return await toDoorayCliError(e);
|
|
628
655
|
}
|
|
629
656
|
}
|
|
630
657
|
async getWikiPages(wikiId, parentPageId) {
|
|
@@ -635,42 +662,42 @@ var DoorayApiClient = class {
|
|
|
635
662
|
}
|
|
636
663
|
}).json();
|
|
637
664
|
} catch (e) {
|
|
638
|
-
return toDoorayCliError(e);
|
|
665
|
+
return await toDoorayCliError(e);
|
|
639
666
|
}
|
|
640
667
|
}
|
|
641
668
|
async getWikiPage(wikiId, pageId) {
|
|
642
669
|
try {
|
|
643
670
|
return await this.api.get(`wiki/v1/wikis/${wikiId}/pages/${pageId}`).json();
|
|
644
671
|
} catch (e) {
|
|
645
|
-
return toDoorayCliError(e);
|
|
672
|
+
return await toDoorayCliError(e);
|
|
646
673
|
}
|
|
647
674
|
}
|
|
648
675
|
async createWikiPage(wikiId, body) {
|
|
649
676
|
try {
|
|
650
677
|
return await this.api.post(`wiki/v1/wikis/${wikiId}/pages`, { json: body }).json();
|
|
651
678
|
} catch (e) {
|
|
652
|
-
return toDoorayCliError(e);
|
|
679
|
+
return await toDoorayCliError(e);
|
|
653
680
|
}
|
|
654
681
|
}
|
|
655
682
|
async updateWikiPage(wikiId, pageId, body) {
|
|
656
683
|
try {
|
|
657
684
|
return await this.api.put(`wiki/v1/wikis/${wikiId}/pages/${pageId}`, { json: body }).json();
|
|
658
685
|
} catch (e) {
|
|
659
|
-
return toDoorayCliError(e);
|
|
686
|
+
return await toDoorayCliError(e);
|
|
660
687
|
}
|
|
661
688
|
}
|
|
662
689
|
async updateWikiPageTitle(wikiId, pageId, body) {
|
|
663
690
|
try {
|
|
664
691
|
return await this.api.put(`wiki/v1/wikis/${wikiId}/pages/${pageId}/title`, { json: body }).json();
|
|
665
692
|
} catch (e) {
|
|
666
|
-
return toDoorayCliError(e);
|
|
693
|
+
return await toDoorayCliError(e);
|
|
667
694
|
}
|
|
668
695
|
}
|
|
669
696
|
async updateWikiPageContent(wikiId, pageId, body) {
|
|
670
697
|
try {
|
|
671
698
|
return await this.api.put(`wiki/v1/wikis/${wikiId}/pages/${pageId}/content`, { json: body }).json();
|
|
672
699
|
} catch (e) {
|
|
673
|
-
return toDoorayCliError(e);
|
|
700
|
+
return await toDoorayCliError(e);
|
|
674
701
|
}
|
|
675
702
|
}
|
|
676
703
|
// ─── Post Files ─────────────────────────────────────
|
|
@@ -678,7 +705,7 @@ var DoorayApiClient = class {
|
|
|
678
705
|
try {
|
|
679
706
|
return await this.api.get(`project/v1/projects/${projectId}/posts/${postId}/files`).json();
|
|
680
707
|
} catch (e) {
|
|
681
|
-
return toDoorayCliError(e);
|
|
708
|
+
return await toDoorayCliError(e);
|
|
682
709
|
}
|
|
683
710
|
}
|
|
684
711
|
async getPostFileMeta(projectId, postId, fileId) {
|
|
@@ -687,7 +714,7 @@ var DoorayApiClient = class {
|
|
|
687
714
|
searchParams: { media: "meta" }
|
|
688
715
|
}).json();
|
|
689
716
|
} catch (e) {
|
|
690
|
-
return toDoorayCliError(e);
|
|
717
|
+
return await toDoorayCliError(e);
|
|
691
718
|
}
|
|
692
719
|
}
|
|
693
720
|
async downloadPostFile(projectId, postId, fileId) {
|
|
@@ -717,7 +744,7 @@ var DoorayApiClient = class {
|
|
|
717
744
|
return { buffer, fileName };
|
|
718
745
|
} catch (e) {
|
|
719
746
|
if (e instanceof DoorayCliError) throw e;
|
|
720
|
-
return toDoorayCliError(e);
|
|
747
|
+
return await toDoorayCliError(e);
|
|
721
748
|
}
|
|
722
749
|
}
|
|
723
750
|
async uploadPostFile(projectId, postId, filePath) {
|
|
@@ -754,14 +781,14 @@ var DoorayApiClient = class {
|
|
|
754
781
|
return await res.json();
|
|
755
782
|
} catch (e) {
|
|
756
783
|
if (e instanceof DoorayCliError) throw e;
|
|
757
|
-
return toDoorayCliError(e);
|
|
784
|
+
return await toDoorayCliError(e);
|
|
758
785
|
}
|
|
759
786
|
}
|
|
760
787
|
async deletePostFile(projectId, postId, fileId) {
|
|
761
788
|
try {
|
|
762
789
|
return await this.api.delete(`project/v1/projects/${projectId}/posts/${postId}/files/${fileId}`).json();
|
|
763
790
|
} catch (e) {
|
|
764
|
-
return toDoorayCliError(e);
|
|
791
|
+
return await toDoorayCliError(e);
|
|
765
792
|
}
|
|
766
793
|
}
|
|
767
794
|
};
|
|
@@ -780,13 +807,24 @@ var WIKIS_TTL_MS = 864e5;
|
|
|
780
807
|
// src/resolvers/me.ts
|
|
781
808
|
async function ensureMe(client) {
|
|
782
809
|
const entry = await getMe();
|
|
783
|
-
if (entry && !isExpired(entry.updatedAt, ME_TTL_MS)) {
|
|
810
|
+
if (entry && !isExpired(entry.updatedAt, ME_TTL_MS) && entry.data.orgId) {
|
|
784
811
|
return entry.data;
|
|
785
812
|
}
|
|
786
813
|
const res = await client.getMe();
|
|
787
|
-
const
|
|
788
|
-
|
|
789
|
-
|
|
814
|
+
const orgId = res.result.defaultOrganization?.id ?? "";
|
|
815
|
+
if (!orgId) {
|
|
816
|
+
throw new DoorayCliError(
|
|
817
|
+
"orgId\uB97C \uD655\uC778\uD560 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4 (getMe \uC751\uB2F5\uC5D0 defaultOrganization.id \uB204\uB77D). dooray cache clear \uD6C4 \uC7AC\uC2DC\uB3C4\uD558\uC138\uC694.",
|
|
818
|
+
EXIT_PARAM_ERROR
|
|
819
|
+
);
|
|
820
|
+
}
|
|
821
|
+
const cached = {
|
|
822
|
+
id: res.result.id,
|
|
823
|
+
name: res.result.name,
|
|
824
|
+
orgId
|
|
825
|
+
};
|
|
826
|
+
await setMe(cached);
|
|
827
|
+
return cached;
|
|
790
828
|
}
|
|
791
829
|
|
|
792
830
|
// src/commands/doctor.ts
|
|
@@ -973,6 +1011,11 @@ var setupCommand = new import_commander4.Command("setup").description("\uB300\uD
|
|
|
973
1011
|
}
|
|
974
1012
|
}
|
|
975
1013
|
}
|
|
1014
|
+
const trackLastRun = await confirm2({
|
|
1015
|
+
message: "feedback --last \uBAA8\uB4DC \uD65C\uC131\uD654 (\uC9C1\uC804 \uBA85\uB839 \uC5D0\uB7EC\uB97C GitHub issue\uC5D0 \uC790\uB3D9 \uCCA8\uBD80)?",
|
|
1016
|
+
default: false,
|
|
1017
|
+
theme: { prefix: "\u{1F4CB}" }
|
|
1018
|
+
});
|
|
976
1019
|
const config = {
|
|
977
1020
|
version: 1,
|
|
978
1021
|
apiKey,
|
|
@@ -985,6 +1028,7 @@ var setupCommand = new import_commander4.Command("setup").description("\uB300\uD
|
|
|
985
1028
|
smtpHost: useMail ? DEFAULTS.smtpHost : existing?.smtpHost,
|
|
986
1029
|
smtpPort: useMail ? DEFAULTS.smtpPort : existing?.smtpPort
|
|
987
1030
|
};
|
|
1031
|
+
config.trackLastRun = trackLastRun;
|
|
988
1032
|
await saveConfig(config);
|
|
989
1033
|
console.log(
|
|
990
1034
|
import_chalk4.default.green(
|
|
@@ -1084,17 +1128,29 @@ function output(opts, data) {
|
|
|
1084
1128
|
// src/utils/spinner.ts
|
|
1085
1129
|
var import_ora = __toESM(require("ora"));
|
|
1086
1130
|
var current = null;
|
|
1131
|
+
var quiet = false;
|
|
1132
|
+
var noopSpinner = new Proxy({}, {
|
|
1133
|
+
get(_target, prop) {
|
|
1134
|
+
if (prop === "text" || prop === "prefixText" || prop === "suffixText") return "";
|
|
1135
|
+
if (prop === "isSpinning") return false;
|
|
1136
|
+
return () => noopSpinner;
|
|
1137
|
+
},
|
|
1138
|
+
set() {
|
|
1139
|
+
return true;
|
|
1140
|
+
}
|
|
1141
|
+
});
|
|
1142
|
+
function setQuiet(value) {
|
|
1143
|
+
quiet = value;
|
|
1144
|
+
}
|
|
1087
1145
|
function startSpinner(text) {
|
|
1146
|
+
if (quiet) return noopSpinner;
|
|
1088
1147
|
current = (0, import_ora.default)({ text, stream: process.stderr }).start();
|
|
1089
1148
|
return current;
|
|
1090
1149
|
}
|
|
1091
1150
|
function stopSpinner(success, text) {
|
|
1092
1151
|
if (!current) return;
|
|
1093
|
-
if (success === false)
|
|
1094
|
-
|
|
1095
|
-
} else {
|
|
1096
|
-
current.succeed(text);
|
|
1097
|
-
}
|
|
1152
|
+
if (success === false) current.fail(text);
|
|
1153
|
+
else current.succeed(text);
|
|
1098
1154
|
current = null;
|
|
1099
1155
|
}
|
|
1100
1156
|
|
|
@@ -1312,6 +1368,12 @@ async function ensureMemberGroups(client, projectId) {
|
|
|
1312
1368
|
await setMemberGroups(projectId, items);
|
|
1313
1369
|
return items;
|
|
1314
1370
|
}
|
|
1371
|
+
async function resolveMemberGroup(client, projectId, input2) {
|
|
1372
|
+
const groups = await ensureMemberGroups(client, projectId);
|
|
1373
|
+
const adapter = groups.map((g) => ({ name: g.code, id: g.id, code: g.code }));
|
|
1374
|
+
const match = matchByName(adapter, input2, "\uADF8\uB8F9", (g) => `${g.code} (${g.id})`);
|
|
1375
|
+
return { id: match.id, code: match.code };
|
|
1376
|
+
}
|
|
1315
1377
|
|
|
1316
1378
|
// src/commands/project/groups.ts
|
|
1317
1379
|
var projectGroupsCommand = new import_commander8.Command("groups").description("\uD504\uB85C\uC81D\uD2B8 \uBA64\uBC84 \uADF8\uB8F9 \uBAA9\uB85D \uC870\uD68C").argument("<project>", "\uD504\uB85C\uC81D\uD2B8 \uCF54\uB4DC \uB610\uB294 ID").action(async (project) => {
|
|
@@ -1364,6 +1426,35 @@ async function ensureTags(client, projectId) {
|
|
|
1364
1426
|
await setTags(projectId, items);
|
|
1365
1427
|
return items;
|
|
1366
1428
|
}
|
|
1429
|
+
function buildMandatoryHint(allTags, missingGroupIds) {
|
|
1430
|
+
const lines = [];
|
|
1431
|
+
for (const groupId of missingGroupIds) {
|
|
1432
|
+
const groupTags = allTags.filter((t) => t.groupId === groupId);
|
|
1433
|
+
const groupName = groupTags[0]?.groupName ?? groupId;
|
|
1434
|
+
const candidates = groupTags.map((t) => t.name).join(", ");
|
|
1435
|
+
lines.push(` - "${groupName}": ${candidates || "(\uD0DC\uADF8 \uC5C6\uC74C)"}`);
|
|
1436
|
+
}
|
|
1437
|
+
return lines.join("\n");
|
|
1438
|
+
}
|
|
1439
|
+
async function validateMandatoryTags(client, projectId) {
|
|
1440
|
+
const allTags = await ensureTags(client, projectId);
|
|
1441
|
+
const missingGroupIds = [];
|
|
1442
|
+
const seen = /* @__PURE__ */ new Set();
|
|
1443
|
+
for (const t of allTags) {
|
|
1444
|
+
if (t.groupMandatory && t.groupId && !seen.has(t.groupId)) {
|
|
1445
|
+
seen.add(t.groupId);
|
|
1446
|
+
missingGroupIds.push(t.groupId);
|
|
1447
|
+
}
|
|
1448
|
+
}
|
|
1449
|
+
if (missingGroupIds.length === 0) return;
|
|
1450
|
+
throw new DoorayCliError(
|
|
1451
|
+
`\uD544\uC218 \uD0DC\uADF8 \uADF8\uB8F9\uC774 \uB204\uB77D\uB418\uC5C8\uC2B5\uB2C8\uB2E4 (\uADF8\uB8F9\uB2F9 1\uAC1C \uC774\uC0C1 \uD544\uC694):
|
|
1452
|
+
` + buildMandatoryHint(allTags, missingGroupIds) + `
|
|
1453
|
+
|
|
1454
|
+
\uB2E4\uC2DC \uC2DC\uB3C4: --tag "<\uADF8\uB8F9>: <\uD6C4\uBCF4>" \uD615\uC2DD\uC73C\uB85C \uCD94\uAC00`,
|
|
1455
|
+
EXIT_PARAM_ERROR
|
|
1456
|
+
);
|
|
1457
|
+
}
|
|
1367
1458
|
async function resolveTags(client, projectId, inputs) {
|
|
1368
1459
|
const allTags = await ensureTags(client, projectId);
|
|
1369
1460
|
const selected = inputs.map(
|
|
@@ -1379,14 +1470,14 @@ async function resolveTags(client, projectId, inputs) {
|
|
|
1379
1470
|
if (t.groupMandatory && t.groupId) mandatoryGroups.set(t.groupId, t.groupName ?? t.groupId);
|
|
1380
1471
|
}
|
|
1381
1472
|
const coveredGroups = new Set(selected.map((t) => t.groupId).filter((g) => !!g));
|
|
1382
|
-
const
|
|
1383
|
-
for (const [gid
|
|
1384
|
-
if (!coveredGroups.has(gid))
|
|
1473
|
+
const missingIds = [];
|
|
1474
|
+
for (const [gid] of mandatoryGroups) {
|
|
1475
|
+
if (!coveredGroups.has(gid)) missingIds.push(gid);
|
|
1385
1476
|
}
|
|
1386
|
-
if (
|
|
1477
|
+
if (missingIds.length > 0) {
|
|
1387
1478
|
throw new DoorayCliError(
|
|
1388
1479
|
`\uD544\uC218 \uD0DC\uADF8 \uADF8\uB8F9\uC774 \uB204\uB77D\uB418\uC5C8\uC2B5\uB2C8\uB2E4 (\uADF8\uB8F9\uB2F9 1\uAC1C \uC774\uC0C1 \uD544\uC694):
|
|
1389
|
-
` +
|
|
1480
|
+
` + buildMandatoryHint(allTags, missingIds),
|
|
1390
1481
|
EXIT_PARAM_ERROR
|
|
1391
1482
|
);
|
|
1392
1483
|
}
|
|
@@ -1553,9 +1644,13 @@ async function resolvePost(client, projectId, postNumber) {
|
|
|
1553
1644
|
|
|
1554
1645
|
// src/utils/dooray-url.ts
|
|
1555
1646
|
var TASK_URL_RE = /^https?:\/\/[\w.-]+\.dooray\.com\/task\/to\/(\d+)(?:[/?#].*)?$/;
|
|
1647
|
+
var TASK_URL_ALT_RE = /^https?:\/\/[\w.-]+\.dooray\.com\/task\/(?:\d+)\/(\d+)(?:[/?#].*)?$/;
|
|
1556
1648
|
function parseDoorayTaskUrl(input2) {
|
|
1557
|
-
const
|
|
1558
|
-
|
|
1649
|
+
const m1 = TASK_URL_RE.exec(input2);
|
|
1650
|
+
if (m1) return m1[1];
|
|
1651
|
+
const m2 = TASK_URL_ALT_RE.exec(input2);
|
|
1652
|
+
if (m2) return m2[1];
|
|
1653
|
+
return null;
|
|
1559
1654
|
}
|
|
1560
1655
|
function isLikelyDoorayUrl(input2) {
|
|
1561
1656
|
return /^https?:\/\//.test(input2);
|
|
@@ -1648,6 +1743,80 @@ var postGetCommand = new import_commander12.Command("get").description("\uC5C5\u
|
|
|
1648
1743
|
// src/commands/post/edit.ts
|
|
1649
1744
|
var import_commander13 = require("commander");
|
|
1650
1745
|
|
|
1746
|
+
// src/utils/mention.ts
|
|
1747
|
+
function buildMemberMention(m, me) {
|
|
1748
|
+
const title = m.memberId === me.id ? "me" : "member";
|
|
1749
|
+
return `[@${m.name}](dooray://${me.orgId}/members/${m.memberId} "${title}")`;
|
|
1750
|
+
}
|
|
1751
|
+
function buildGroupMention(g, me) {
|
|
1752
|
+
return `[@${g.projectCode}/${g.code}](dooray://${me.orgId}/member-groups/${g.groupId})`;
|
|
1753
|
+
}
|
|
1754
|
+
function prependMentions(body, members, groups, me) {
|
|
1755
|
+
const parts = [];
|
|
1756
|
+
for (const m of members) parts.push(buildMemberMention(m, me));
|
|
1757
|
+
for (const g of groups) parts.push(buildGroupMention(g, me));
|
|
1758
|
+
if (parts.length === 0) return body;
|
|
1759
|
+
return parts.join(" ") + " " + body;
|
|
1760
|
+
}
|
|
1761
|
+
|
|
1762
|
+
// src/utils/task-link.ts
|
|
1763
|
+
function escapeLinkText(text) {
|
|
1764
|
+
return text.replace(/&/g, "&").replace(/\[/g, "[").replace(/\]/g, "]").replace(/—/g, "—");
|
|
1765
|
+
}
|
|
1766
|
+
function buildTaskLink(t, me) {
|
|
1767
|
+
const text = `${t.projectCode}/${t.number} ${escapeLinkText(t.subject)}`;
|
|
1768
|
+
const url = `dooray://${me.orgId}/tasks/${t.postId}`;
|
|
1769
|
+
if (t.workflowClass) {
|
|
1770
|
+
const safeClass = t.workflowClass.replace(/"/g, """);
|
|
1771
|
+
return `[${text}](${url} "${safeClass}")`;
|
|
1772
|
+
}
|
|
1773
|
+
return `[${text}](${url})`;
|
|
1774
|
+
}
|
|
1775
|
+
function parseLinkRef(ref) {
|
|
1776
|
+
if (/^[0-9]{15,}$/.test(ref)) return { idOpt: ref };
|
|
1777
|
+
if (ref.includes("/")) {
|
|
1778
|
+
const [p, n] = ref.split("/");
|
|
1779
|
+
if (!p || !n) {
|
|
1780
|
+
throw new DoorayCliError(
|
|
1781
|
+
`--link-task \uD615\uC2DD\uC774 \uC62C\uBC14\uB974\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4: "${ref}". <project>/<number> \uB610\uB294 postId\uB97C \uC785\uB825\uD558\uC138\uC694.`,
|
|
1782
|
+
EXIT_PARAM_ERROR
|
|
1783
|
+
);
|
|
1784
|
+
}
|
|
1785
|
+
return { projectArg: p, postNumberArg: n };
|
|
1786
|
+
}
|
|
1787
|
+
throw new DoorayCliError(
|
|
1788
|
+
`--link-task \uD615\uC2DD\uC774 \uC62C\uBC14\uB974\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4: "${ref}". <project>/<number> \uB610\uB294 postId\uB97C \uC785\uB825\uD558\uC138\uC694.`,
|
|
1789
|
+
EXIT_PARAM_ERROR
|
|
1790
|
+
);
|
|
1791
|
+
}
|
|
1792
|
+
function appendTaskLinks(body, links, me) {
|
|
1793
|
+
if (links.length === 0) return body;
|
|
1794
|
+
const rendered = links.map((l) => buildTaskLink(l, me)).join("\n");
|
|
1795
|
+
if (!body) return rendered;
|
|
1796
|
+
return body.replace(/\n*$/, "") + "\n\n" + rendered;
|
|
1797
|
+
}
|
|
1798
|
+
|
|
1799
|
+
// src/resolvers/task-link.ts
|
|
1800
|
+
async function resolveTaskLinks(client, linkInputs) {
|
|
1801
|
+
return Promise.all(
|
|
1802
|
+
linkInputs.map(async (ref) => {
|
|
1803
|
+
const { projectArg, postNumberArg, idOpt } = parseLinkRef(ref);
|
|
1804
|
+
const { projectId, postId, projectCode, postNumber } = await resolvePostInput(
|
|
1805
|
+
client,
|
|
1806
|
+
{ projectArg, postNumberArg, idOpt }
|
|
1807
|
+
);
|
|
1808
|
+
const detail = await client.getPost(projectId, postId);
|
|
1809
|
+
return {
|
|
1810
|
+
projectCode,
|
|
1811
|
+
number: postNumber,
|
|
1812
|
+
postId,
|
|
1813
|
+
subject: detail.result.subject,
|
|
1814
|
+
workflowClass: detail.result.workflowClass
|
|
1815
|
+
};
|
|
1816
|
+
})
|
|
1817
|
+
);
|
|
1818
|
+
}
|
|
1819
|
+
|
|
1651
1820
|
// src/editor/index.ts
|
|
1652
1821
|
var import_node_child_process = require("child_process");
|
|
1653
1822
|
var import_promises6 = __toESM(require("fs/promises"));
|
|
@@ -1694,11 +1863,11 @@ function openInEditor(content) {
|
|
|
1694
1863
|
}
|
|
1695
1864
|
});
|
|
1696
1865
|
}
|
|
1697
|
-
function
|
|
1866
|
+
function memberIdToName(memberId, members) {
|
|
1698
1867
|
const member = members.find(
|
|
1699
1868
|
(m) => m.organizationMemberId === memberId
|
|
1700
1869
|
);
|
|
1701
|
-
return member?.
|
|
1870
|
+
return member?.name ?? memberId;
|
|
1702
1871
|
}
|
|
1703
1872
|
function serializePostFrontmatter(post, members) {
|
|
1704
1873
|
const frontmatter = {
|
|
@@ -1706,12 +1875,12 @@ function serializePostFrontmatter(post, members) {
|
|
|
1706
1875
|
priority: post.priority,
|
|
1707
1876
|
due_date: post.dueDate ?? null,
|
|
1708
1877
|
to: post.users.to.map((u) => {
|
|
1709
|
-
if (u.member) return
|
|
1878
|
+
if (u.member) return memberIdToName(u.member.organizationMemberId, members);
|
|
1710
1879
|
if (u.emailUser) return u.emailUser.emailAddress;
|
|
1711
1880
|
return "";
|
|
1712
1881
|
}).filter(Boolean),
|
|
1713
1882
|
cc: post.users.cc.map((u) => {
|
|
1714
|
-
if (u.member) return
|
|
1883
|
+
if (u.member) return memberIdToName(u.member.organizationMemberId, members);
|
|
1715
1884
|
if (u.emailUser) return u.emailUser.emailAddress;
|
|
1716
1885
|
return "";
|
|
1717
1886
|
}).filter(Boolean)
|
|
@@ -1807,20 +1976,88 @@ async function readStdin() {
|
|
|
1807
1976
|
return Buffer.concat(chunks).toString("utf-8");
|
|
1808
1977
|
}
|
|
1809
1978
|
|
|
1979
|
+
// src/utils/attachment-check.ts
|
|
1980
|
+
var import_node_readline = __toESM(require("readline"));
|
|
1981
|
+
function extractAttachmentFileIds(body) {
|
|
1982
|
+
const ids = /* @__PURE__ */ new Set();
|
|
1983
|
+
const re = /!?\[[^\]]*\]\(\/files\/([^\s)?#]+)/g;
|
|
1984
|
+
let m;
|
|
1985
|
+
while ((m = re.exec(body)) !== null) {
|
|
1986
|
+
ids.add(m[1]);
|
|
1987
|
+
}
|
|
1988
|
+
return ids;
|
|
1989
|
+
}
|
|
1990
|
+
function findDroppedAttachments(oldBody, newBody, attachments) {
|
|
1991
|
+
const oldIds = extractAttachmentFileIds(oldBody);
|
|
1992
|
+
const newIds = extractAttachmentFileIds(newBody);
|
|
1993
|
+
const dropped = [];
|
|
1994
|
+
for (const att of attachments) {
|
|
1995
|
+
if (oldIds.has(att.id) && !newIds.has(att.id)) {
|
|
1996
|
+
dropped.push({ id: att.id, name: att.name });
|
|
1997
|
+
}
|
|
1998
|
+
}
|
|
1999
|
+
return dropped;
|
|
2000
|
+
}
|
|
2001
|
+
function sanitizeFileName(name) {
|
|
2002
|
+
return name.replace(/[\x00-\x1F\x7F]/g, "?");
|
|
2003
|
+
}
|
|
2004
|
+
function printDroppedWarning(dropped) {
|
|
2005
|
+
process.stderr.write(`\u26A0 \uC0C8 \uBCF8\uBB38\uC5D0\uC11C ${dropped.length}\uAC1C attachment reference \uAC00 \uBE60\uC9D1\uB2C8\uB2E4:
|
|
2006
|
+
`);
|
|
2007
|
+
for (const a of dropped) {
|
|
2008
|
+
const safe = a.name ? sanitizeFileName(a.name) : void 0;
|
|
2009
|
+
process.stderr.write(` - /files/${a.id} ${safe ? "\u2190 " + safe : ""}
|
|
2010
|
+
`);
|
|
2011
|
+
}
|
|
2012
|
+
process.stderr.write(` (attachment \uC790\uCCB4\uB294 \uC11C\uBC84\uC5D0 \uB0A8\uC9C0\uB9CC \uBCF8\uBB38\uC5D0\uC11C \uC0AC\uB77C\uC838 \uBCF4\uC785\uB2C8\uB2E4.)
|
|
2013
|
+
`);
|
|
2014
|
+
}
|
|
2015
|
+
async function confirmDropped() {
|
|
2016
|
+
const rl = import_node_readline.default.createInterface({ input: process.stdin, output: process.stderr });
|
|
2017
|
+
const answer = await new Promise((resolve) => {
|
|
2018
|
+
rl.question("\uACC4\uC18D \uC9C4\uD589\uD558\uC2DC\uACA0\uC2B5\uB2C8\uAE4C? (y/N) ", resolve);
|
|
2019
|
+
});
|
|
2020
|
+
rl.close();
|
|
2021
|
+
return /^y(es)?$/i.test(answer.trim());
|
|
2022
|
+
}
|
|
2023
|
+
async function checkAndGuardDropped(oldBody, newBody, attachments, noConfirm) {
|
|
2024
|
+
const dropped = findDroppedAttachments(oldBody, newBody, attachments);
|
|
2025
|
+
if (dropped.length === 0) return;
|
|
2026
|
+
printDroppedWarning(dropped);
|
|
2027
|
+
if (noConfirm) {
|
|
2028
|
+
process.stderr.write(` --no-confirm \uD50C\uB798\uADF8\uB85C \uADF8\uB300\uB85C \uC9C4\uD589\uD569\uB2C8\uB2E4.
|
|
2029
|
+
`);
|
|
2030
|
+
return;
|
|
2031
|
+
}
|
|
2032
|
+
if (!process.stdin.isTTY) {
|
|
2033
|
+
throw new DoorayCliError(
|
|
2034
|
+
"non-TTY \uD658\uACBD\uC5D0\uC11C \uB204\uB77D attachment \uAC00 \uAC10\uC9C0\uB418\uC5C8\uC2B5\uB2C8\uB2E4. \uC758\uB3C4\uD55C \uBCC0\uACBD\uC774\uBA74 --no-confirm \uD50C\uB798\uADF8\uB85C \uB2E4\uC2DC \uC2E4\uD589\uD558\uC138\uC694.",
|
|
2035
|
+
EXIT_PARAM_ERROR
|
|
2036
|
+
);
|
|
2037
|
+
}
|
|
2038
|
+
const confirmed = await confirmDropped();
|
|
2039
|
+
if (!confirmed) {
|
|
2040
|
+
throw new DoorayCliError("\uCDE8\uC18C\uB418\uC5C8\uC2B5\uB2C8\uB2E4.", EXIT_PARAM_ERROR);
|
|
2041
|
+
}
|
|
2042
|
+
}
|
|
2043
|
+
|
|
1810
2044
|
// src/commands/post/edit.ts
|
|
1811
|
-
async function resolveUsers(client, projectId,
|
|
2045
|
+
async function resolveUsers(client, projectId, names) {
|
|
1812
2046
|
const users = [];
|
|
1813
|
-
for (const
|
|
1814
|
-
const memberId = await resolveMember(client, projectId,
|
|
2047
|
+
for (const name of names) {
|
|
2048
|
+
const memberId = await resolveMember(client, projectId, name);
|
|
1815
2049
|
users.push({ type: "member", member: { organizationMemberId: memberId } });
|
|
1816
2050
|
}
|
|
1817
2051
|
return users;
|
|
1818
2052
|
}
|
|
1819
|
-
var postEditCommand = new import_commander13.Command("edit").description("\uC5C5\uBB34 \uC218\uC815 ($EDITOR \uB610\uB294 --title/--body \uC635\uC158)").argument("[project]", "\uD504\uB85C\uC81D\uD2B8 \uCF54\uB4DC (\uB610\uB294 \uCCAB \uC778\uC790\uC5D0 Dooray URL)").argument("[post-number]", "\uC5C5\uBB34 \uBC88\uD638 (project\uC640 \uD568\uAED8 \uC0AC\uC6A9)").option("--id <postId>", "Dooray post ID (project/post-number \uB300\uC2E0)").option("--url <url>", "Dooray \uC5C5\uBB34 URL (project/post-number \uB300\uC2E0)").option("--title <title>", "\uC81C\uBAA9 \uBCC0\uACBD (non-interactive)").option("--subject <subject>", "--title\uC758 deprecated alias").option("--body <text>", "\uBCF8\uBB38 \uBCC0\uACBD (- \uC785\uB825 \uC2DC stdin, non-interactive)").option("--body-file <path>", "\uBCF8\uBB38 \uD30C\uC77C \uACBD\uB85C (- \uC785\uB825 \uC2DC stdin, non-interactive)").action(async (project, postNumberStr, opts) => {
|
|
2053
|
+
var postEditCommand = new import_commander13.Command("edit").description("\uC5C5\uBB34 \uC218\uC815 ($EDITOR \uB610\uB294 --title/--body \uC635\uC158)").argument("[project]", "\uD504\uB85C\uC81D\uD2B8 \uCF54\uB4DC (\uB610\uB294 \uCCAB \uC778\uC790\uC5D0 Dooray URL)").argument("[post-number]", "\uC5C5\uBB34 \uBC88\uD638 (project\uC640 \uD568\uAED8 \uC0AC\uC6A9)").option("--id <postId>", "Dooray post ID (project/post-number \uB300\uC2E0)").option("--url <url>", "Dooray \uC5C5\uBB34 URL (project/post-number \uB300\uC2E0)").option("--title <title>", "\uC81C\uBAA9 \uBCC0\uACBD (non-interactive)").option("--subject <subject>", "--title\uC758 deprecated alias").option("--body <text>", "\uBCF8\uBB38 \uBCC0\uACBD (- \uC785\uB825 \uC2DC stdin, non-interactive)").option("--body-file <path>", "\uBCF8\uBB38 \uD30C\uC77C \uACBD\uB85C (- \uC785\uB825 \uC2DC stdin, non-interactive)").option("--mention <name>", "\uBA64\uBC84 \uBA58\uC158 (\uBC18\uBCF5 \uAC00\uB2A5, \uC774\uB984 \uBD80\uBD84\uC77C\uCE58)", (v, prev) => [...prev, v], []).option("--mention-group <code>", "\uADF8\uB8F9 \uBA58\uC158 (\uBC18\uBCF5 \uAC00\uB2A5, code \uBD80\uBD84\uC77C\uCE58)", (v, prev) => [...prev, v], []).option("--link-task <ref>", "\uB2E4\uB978 \uC5C5\uBB34 \uB9C1\uD06C \uCD94\uAC00 (<project>/<number> \uB610\uB294 postId, \uBC18\uBCF5 \uAC00\uB2A5)", (v, prev) => [...prev, v], []).option("--dry-run", "API \uD638\uCD9C \uC5C6\uC774 \uD569\uC131\uB41C \uBCF8\uBB38\uB9CC stdout \uCD9C\uB825 (mention/link-task \uC801\uC6A9 \uACB0\uACFC \uBBF8\uB9AC\uBCF4\uAE30)").option("--no-confirm", "\uB204\uB77D attachment \uACBD\uACE0 \uC2DC confirm \uC5C6\uC774 \uC9C4\uD589 (\uC790\uB3D9\uD654\uC6A9)").action(async (project, postNumberStr, opts) => {
|
|
1820
2054
|
const config = await getConfigOrThrow();
|
|
1821
2055
|
const client = new DoorayApiClient(config.apiKey, config.baseUrl);
|
|
2056
|
+
const mentionInputs = (opts.mention ?? []).filter((s) => s.length > 0);
|
|
2057
|
+
const groupInputs = (opts.mentionGroup ?? []).filter((s) => s.length > 0);
|
|
2058
|
+
const linkInputs = (opts.linkTask ?? []).filter((s) => s.length > 0);
|
|
1822
2059
|
startSpinner("\uC5C5\uBB34 \uC870\uD68C \uC911...");
|
|
1823
|
-
const { projectId, postId, postNumber } = await resolvePostInput(client, {
|
|
2060
|
+
const { projectId, postId, postNumber, projectCode } = await resolvePostInput(client, {
|
|
1824
2061
|
projectArg: project,
|
|
1825
2062
|
postNumberArg: postNumberStr,
|
|
1826
2063
|
idOpt: opts.id,
|
|
@@ -1838,7 +2075,47 @@ var postEditCommand = new import_commander13.Command("edit").description("\uC5C5
|
|
|
1838
2075
|
}
|
|
1839
2076
|
const nonInteractive = title || opts.body || opts.bodyFile;
|
|
1840
2077
|
if (nonInteractive) {
|
|
1841
|
-
|
|
2078
|
+
let newBody = await readBodyInputOrNull(opts);
|
|
2079
|
+
if (newBody != null && !opts.dryRun) {
|
|
2080
|
+
const attachments = (post.files ?? []).map((f) => ({ id: f.id, name: f.name }));
|
|
2081
|
+
await checkAndGuardDropped(post.body.content, newBody, attachments, !opts.confirm);
|
|
2082
|
+
}
|
|
2083
|
+
if (mentionInputs.length > 0 || groupInputs.length > 0) {
|
|
2084
|
+
const effectiveBody = newBody ?? post.body.content;
|
|
2085
|
+
const me = await ensureMe(client);
|
|
2086
|
+
const memberIds = await Promise.all(
|
|
2087
|
+
mentionInputs.map((name) => resolveMember(client, projectId, name))
|
|
2088
|
+
);
|
|
2089
|
+
const nameMap = await buildMemberNameMap(client, projectId);
|
|
2090
|
+
const members2 = memberIds.map((memberId) => ({
|
|
2091
|
+
memberId,
|
|
2092
|
+
name: nameMap.get(memberId) ?? memberId
|
|
2093
|
+
}));
|
|
2094
|
+
const groups = await Promise.all(
|
|
2095
|
+
groupInputs.map(async (code) => {
|
|
2096
|
+
const g = await resolveMemberGroup(client, projectId, code);
|
|
2097
|
+
return { groupId: g.id, code: g.code, projectCode };
|
|
2098
|
+
})
|
|
2099
|
+
);
|
|
2100
|
+
newBody = prependMentions(effectiveBody, members2, groups, me);
|
|
2101
|
+
}
|
|
2102
|
+
if (linkInputs.length > 0) {
|
|
2103
|
+
const effectiveBody = newBody ?? post.body.content;
|
|
2104
|
+
const me = await ensureMe(client);
|
|
2105
|
+
const links = await resolveTaskLinks(client, linkInputs);
|
|
2106
|
+
newBody = appendTaskLinks(effectiveBody, links, me);
|
|
2107
|
+
}
|
|
2108
|
+
if (opts.dryRun) {
|
|
2109
|
+
stopSpinner(false);
|
|
2110
|
+
const globalOpts = postEditCommand.optsWithGlobals();
|
|
2111
|
+
const previewBody = newBody ?? post.body.content;
|
|
2112
|
+
if (globalOpts.json) {
|
|
2113
|
+
process.stdout.write(JSON.stringify({ body: previewBody }) + "\n");
|
|
2114
|
+
} else {
|
|
2115
|
+
process.stdout.write(previewBody + "\n");
|
|
2116
|
+
}
|
|
2117
|
+
return;
|
|
2118
|
+
}
|
|
1842
2119
|
startSpinner("\uC5C5\uBB34 \uC218\uC815 \uC911...");
|
|
1843
2120
|
const toUsers = post.users.to.map((u) => ({
|
|
1844
2121
|
type: u.type,
|
|
@@ -1865,6 +2142,16 @@ var postEditCommand = new import_commander13.Command("edit").description("\uC5C5
|
|
|
1865
2142
|
});
|
|
1866
2143
|
stopSpinner(true, "\uC5C5\uBB34 \uC218\uC815 \uC644\uB8CC");
|
|
1867
2144
|
} else {
|
|
2145
|
+
if (mentionInputs.length > 0 || groupInputs.length > 0) {
|
|
2146
|
+
process.stderr.write(
|
|
2147
|
+
"\u26A0 --mention/--mention-group \uC740 --title/--body \uC640 \uD568\uAED8 \uC0AC\uC6A9 \uC2DC\uC5D0\uB9CC \uC801\uC6A9\uB429\uB2C8\uB2E4.\n"
|
|
2148
|
+
);
|
|
2149
|
+
}
|
|
2150
|
+
if (linkInputs.length > 0) {
|
|
2151
|
+
process.stderr.write(
|
|
2152
|
+
"\u26A0 --link-task \uB294 --title/--body \uC640 \uD568\uAED8 \uC0AC\uC6A9 \uC2DC\uC5D0\uB9CC \uC801\uC6A9\uB429\uB2C8\uB2E4.\n"
|
|
2153
|
+
);
|
|
2154
|
+
}
|
|
1868
2155
|
const original = serializePostFrontmatter(post, members);
|
|
1869
2156
|
const edited = await openInEditor(original);
|
|
1870
2157
|
if (original === edited) {
|
|
@@ -1872,6 +2159,8 @@ var postEditCommand = new import_commander13.Command("edit").description("\uC5C5
|
|
|
1872
2159
|
return;
|
|
1873
2160
|
}
|
|
1874
2161
|
const parsed = parsePostFrontmatter(edited);
|
|
2162
|
+
const attachmentsInteractive = (post.files ?? []).map((f) => ({ id: f.id, name: f.name }));
|
|
2163
|
+
await checkAndGuardDropped(post.body.content, parsed.body, attachmentsInteractive, !opts.confirm);
|
|
1875
2164
|
startSpinner("\uC5C5\uBB34 \uC218\uC815 \uC911...");
|
|
1876
2165
|
const toUsers = await resolveUsers(client, projectId, parsed.to);
|
|
1877
2166
|
const ccUsers = await resolveUsers(client, projectId, parsed.cc);
|
|
@@ -1945,7 +2234,7 @@ async function resolveUsers2(client, projectId, inputs) {
|
|
|
1945
2234
|
}
|
|
1946
2235
|
return users;
|
|
1947
2236
|
}
|
|
1948
|
-
var postCreateCommand = new import_commander14.Command("create").description("\uC5C5\uBB34 \uC0DD\uC131").argument("<project>", "\uD504\uB85C\uC81D\uD2B8 \uCF54\uB4DC \uB610\uB294 ID").option("--title <title>", "\uC5C5\uBB34 \uC81C\uBAA9").option("--subject <subject>", "--title\uC758 deprecated alias").option("--to <members...>", "\uB2F4\uB2F9\uC790 (\uC774\uB984 \uB610\uB294 \uC774\uBA54\uC77C, \uC5EC\uB7EC \uBA85 \uAC00\uB2A5)").option("--cc <members...>", "\uCC38\uC870\uC790 (\uC774\uB984 \uB610\uB294 \uC774\uBA54\uC77C, \uC5EC\uB7EC \uBA85 \uAC00\uB2A5)").option("--body <text>", "\uBCF8\uBB38 \uD14D\uC2A4\uD2B8 (- \uC785\uB825 \uC2DC stdin\uC5D0\uC11C \uC77D\uAE30)").option("--body-file <path>", "\uBCF8\uBB38 \uD30C\uC77C \uACBD\uB85C (- \uC785\uB825 \uC2DC stdin\uC5D0\uC11C \uC77D\uAE30)").option("--priority <level>", "\uC6B0\uC120\uC21C\uC704 (highest, high, normal, low, lowest)", "normal").option("--due-date <date>", "\uB9C8\uAC10\uC77C (ISO 8601 \uD615\uC2DD)").option("--tag <name>", "\uD0DC\uADF8 \uC774\uB984 (\uBC18\uBCF5 \uAC00\uB2A5)", (value, prev) => [...prev, value], []).option("--parent <ref>", "\uBD80\uBAA8 \uC5C5\uBB34 (project/number \uB610\uB294 postId)").option("--workflow <name>", "\uCD08\uAE30 \uC6CC\uD06C\uD50C\uB85C\uC6B0 \uC774\uB984 \uB610\uB294 class").option("--milestone <name>", "\uB9C8\uC77C\uC2A4\uD1A4 \uC774\uB984").action(async (project, opts) => {
|
|
2237
|
+
var postCreateCommand = new import_commander14.Command("create").description("\uC5C5\uBB34 \uC0DD\uC131").argument("<project>", "\uD504\uB85C\uC81D\uD2B8 \uCF54\uB4DC \uB610\uB294 ID").option("--title <title>", "\uC5C5\uBB34 \uC81C\uBAA9").option("--subject <subject>", "--title\uC758 deprecated alias").option("--to <members...>", "\uB2F4\uB2F9\uC790 (\uC774\uB984 \uB610\uB294 \uC774\uBA54\uC77C, \uC5EC\uB7EC \uBA85 \uAC00\uB2A5)").option("--cc <members...>", "\uCC38\uC870\uC790 (\uC774\uB984 \uB610\uB294 \uC774\uBA54\uC77C, \uC5EC\uB7EC \uBA85 \uAC00\uB2A5)").option("--body <text>", "\uBCF8\uBB38 \uD14D\uC2A4\uD2B8 (- \uC785\uB825 \uC2DC stdin\uC5D0\uC11C \uC77D\uAE30)").option("--body-file <path>", "\uBCF8\uBB38 \uD30C\uC77C \uACBD\uB85C (- \uC785\uB825 \uC2DC stdin\uC5D0\uC11C \uC77D\uAE30)").option("--priority <level>", "\uC6B0\uC120\uC21C\uC704 (highest, high, normal, low, lowest)", "normal").option("--due-date <date>", "\uB9C8\uAC10\uC77C (ISO 8601 \uD615\uC2DD)").option("--tag <name>", "\uD0DC\uADF8 \uC774\uB984 (\uBC18\uBCF5 \uAC00\uB2A5)", (value, prev) => [...prev, value], []).option("--mention <name>", "\uBA64\uBC84 \uBA58\uC158 (\uBC18\uBCF5 \uAC00\uB2A5, \uC774\uB984 \uBD80\uBD84\uC77C\uCE58)", (v, prev) => [...prev, v], []).option("--mention-group <code>", "\uADF8\uB8F9 \uBA58\uC158 (\uBC18\uBCF5 \uAC00\uB2A5, code \uBD80\uBD84\uC77C\uCE58)", (v, prev) => [...prev, v], []).option("--link-task <ref>", "\uB2E4\uB978 \uC5C5\uBB34 \uB9C1\uD06C \uCD94\uAC00 (<project>/<number> \uB610\uB294 postId, \uBC18\uBCF5 \uAC00\uB2A5)", (v, prev) => [...prev, v], []).option("--parent <ref>", "\uBD80\uBAA8 \uC5C5\uBB34 (project/number \uB610\uB294 postId)").option("--workflow <name>", "\uCD08\uAE30 \uC6CC\uD06C\uD50C\uB85C\uC6B0 \uC774\uB984 \uB610\uB294 class").option("--milestone <name>", "\uB9C8\uC77C\uC2A4\uD1A4 \uC774\uB984").option("--dry-run", "API \uD638\uCD9C \uC5C6\uC774 \uD569\uC131\uB41C \uBCF8\uBB38\uB9CC stdout \uCD9C\uB825 (mention/link-task \uC801\uC6A9 \uACB0\uACFC \uBBF8\uB9AC\uBCF4\uAE30)").action(async (project, opts) => {
|
|
1949
2238
|
const globalOpts = postCreateCommand.optsWithGlobals();
|
|
1950
2239
|
const config = await getConfigOrThrow();
|
|
1951
2240
|
const client = new DoorayApiClient(config.apiKey, config.baseUrl);
|
|
@@ -1961,14 +2250,60 @@ var postCreateCommand = new import_commander14.Command("create").description("\u
|
|
|
1961
2250
|
"\u26A0 --subject\uB294 deprecated\uC785\uB2C8\uB2E4. \uB300\uC2E0 --title\uC744 \uC0AC\uC6A9\uD574\uC8FC\uC138\uC694.\n"
|
|
1962
2251
|
);
|
|
1963
2252
|
}
|
|
1964
|
-
const
|
|
2253
|
+
const mentionInputs = (opts.mention ?? []).filter((s) => s.length > 0);
|
|
2254
|
+
const groupInputs = (opts.mentionGroup ?? []).filter((s) => s.length > 0);
|
|
2255
|
+
const linkInputs = (opts.linkTask ?? []).filter((s) => s.length > 0);
|
|
2256
|
+
let bodyContent = await readBodyInput(opts);
|
|
1965
2257
|
startSpinner("\uC5C5\uBB34 \uC0DD\uC131 \uC911...");
|
|
1966
2258
|
const projectId = await resolveProject(client, project);
|
|
2259
|
+
let projectCode;
|
|
2260
|
+
if (groupInputs.length > 0) {
|
|
2261
|
+
const projects = await ensureProjects(client);
|
|
2262
|
+
projectCode = projects.find((p) => p.id === projectId)?.code;
|
|
2263
|
+
if (!projectCode) {
|
|
2264
|
+
throw new DoorayCliError(
|
|
2265
|
+
`--mention-group \uC740 \uACF5\uAC1C \uD504\uB85C\uC81D\uD2B8\uC5D0\uC11C\uB9CC \uC9C0\uC6D0\uB429\uB2C8\uB2E4. dooray project list \uB85C \uCE90\uC2DC \uAC31\uC2E0 \uD6C4 \uC7AC\uC2DC\uB3C4\uD558\uC138\uC694.`,
|
|
2266
|
+
EXIT_PARAM_ERROR
|
|
2267
|
+
);
|
|
2268
|
+
}
|
|
2269
|
+
}
|
|
2270
|
+
if (mentionInputs.length > 0 || groupInputs.length > 0) {
|
|
2271
|
+
const me = await ensureMe(client);
|
|
2272
|
+
const memberIds = await Promise.all(
|
|
2273
|
+
mentionInputs.map((name) => resolveMember(client, projectId, name))
|
|
2274
|
+
);
|
|
2275
|
+
const nameMap = await buildMemberNameMap(client, projectId);
|
|
2276
|
+
const members = memberIds.map((memberId) => ({
|
|
2277
|
+
memberId,
|
|
2278
|
+
name: nameMap.get(memberId) ?? memberId
|
|
2279
|
+
}));
|
|
2280
|
+
const groups = await Promise.all(
|
|
2281
|
+
groupInputs.map(async (code) => {
|
|
2282
|
+
const g = await resolveMemberGroup(client, projectId, code);
|
|
2283
|
+
return { groupId: g.id, code: g.code, projectCode: projectCode ?? "" };
|
|
2284
|
+
})
|
|
2285
|
+
);
|
|
2286
|
+
bodyContent = prependMentions(bodyContent, members, groups, me);
|
|
2287
|
+
}
|
|
2288
|
+
if (linkInputs.length > 0) {
|
|
2289
|
+
const me = await ensureMe(client);
|
|
2290
|
+
const links = await resolveTaskLinks(client, linkInputs);
|
|
2291
|
+
bodyContent = appendTaskLinks(bodyContent, links, me);
|
|
2292
|
+
}
|
|
2293
|
+
if (opts.dryRun) {
|
|
2294
|
+
stopSpinner(false);
|
|
2295
|
+
if (globalOpts.json) {
|
|
2296
|
+
process.stdout.write(JSON.stringify({ body: bodyContent }) + "\n");
|
|
2297
|
+
} else {
|
|
2298
|
+
process.stdout.write(bodyContent + "\n");
|
|
2299
|
+
}
|
|
2300
|
+
return;
|
|
2301
|
+
}
|
|
1967
2302
|
const toUsers = opts.to ? await resolveUsers2(client, projectId, opts.to) : [];
|
|
1968
2303
|
const ccUsers = opts.cc ? await resolveUsers2(client, projectId, opts.cc) : [];
|
|
1969
2304
|
const tagInputs = (opts.tag ?? []).filter((s) => s.length > 0);
|
|
1970
2305
|
const [tagIds, parentPostId, milestoneId] = await Promise.all([
|
|
1971
|
-
tagInputs.length > 0 ? resolveTags(client, projectId, tagInputs) :
|
|
2306
|
+
tagInputs.length > 0 ? resolveTags(client, projectId, tagInputs) : validateMandatoryTags(client, projectId).then(() => void 0),
|
|
1972
2307
|
opts.parent ? resolvePostRef(client, opts.parent) : Promise.resolve(void 0),
|
|
1973
2308
|
opts.milestone ? resolveMilestone(client, projectId, opts.milestone) : Promise.resolve(void 0)
|
|
1974
2309
|
]);
|
|
@@ -2241,7 +2576,17 @@ var commentLatestCommand = new import_commander18.Command("latest").description(
|
|
|
2241
2576
|
|
|
2242
2577
|
// src/commands/post/comment/add.ts
|
|
2243
2578
|
var import_commander19 = require("commander");
|
|
2244
|
-
var commentAddCommand = new import_commander19.Command("add").description("\uB313\uAE00 \uCD94\uAC00").argument("[project]", "\uD504\uB85C\uC81D\uD2B8 \uCF54\uB4DC (\uB610\uB294 \uCCAB \uC778\uC790\uC5D0 Dooray URL)").argument("[post-number]", "\uC5C5\uBB34 \uBC88\uD638 (project\uC640 \uD568\uAED8 \uC0AC\uC6A9)").option("--id <postId>", "Dooray post ID (project/post-number \uB300\uC2E0)").option("--url <url>", "Dooray \uC5C5\uBB34 URL (project/post-number \uB300\uC2E0)").option("--body <text>", "\uB313\uAE00 \uBCF8\uBB38 (- \uC785\uB825 \uC2DC stdin\uC5D0\uC11C \uC77D\uAE30)").option("--body-file <path>", "\uBCF8\uBB38 \uD30C\uC77C \uACBD\uB85C (- \uC785\uB825 \uC2DC stdin\uC5D0\uC11C \uC77D\uAE30)").
|
|
2579
|
+
var commentAddCommand = new import_commander19.Command("add").description("\uB313\uAE00 \uCD94\uAC00").argument("[project]", "\uD504\uB85C\uC81D\uD2B8 \uCF54\uB4DC (\uB610\uB294 \uCCAB \uC778\uC790\uC5D0 Dooray URL)").argument("[post-number]", "\uC5C5\uBB34 \uBC88\uD638 (project\uC640 \uD568\uAED8 \uC0AC\uC6A9)").option("--id <postId>", "Dooray post ID (project/post-number \uB300\uC2E0)").option("--url <url>", "Dooray \uC5C5\uBB34 URL (project/post-number \uB300\uC2E0)").option("--body <text>", "\uB313\uAE00 \uBCF8\uBB38 (- \uC785\uB825 \uC2DC stdin\uC5D0\uC11C \uC77D\uAE30)").option("--body-file <path>", "\uBCF8\uBB38 \uD30C\uC77C \uACBD\uB85C (- \uC785\uB825 \uC2DC stdin\uC5D0\uC11C \uC77D\uAE30)").option(
|
|
2580
|
+
"--mention <name>",
|
|
2581
|
+
"\uBA64\uBC84 \uBA58\uC158 (\uBC18\uBCF5 \uAC00\uB2A5, \uC774\uB984 \uBD80\uBD84\uC77C\uCE58)",
|
|
2582
|
+
(value, prev) => [...prev, value],
|
|
2583
|
+
[]
|
|
2584
|
+
).option(
|
|
2585
|
+
"--mention-group <code>",
|
|
2586
|
+
"\uADF8\uB8F9 \uBA58\uC158 (\uBC18\uBCF5 \uAC00\uB2A5, code \uBD80\uBD84\uC77C\uCE58)",
|
|
2587
|
+
(value, prev) => [...prev, value],
|
|
2588
|
+
[]
|
|
2589
|
+
).option("--link-task <ref>", "\uB2E4\uB978 \uC5C5\uBB34 \uB9C1\uD06C \uCD94\uAC00 (<project>/<number> \uB610\uB294 postId, \uBC18\uBCF5 \uAC00\uB2A5)", (v, prev) => [...prev, v], []).option("--dry-run", "API \uD638\uCD9C \uC5C6\uC774 \uD569\uC131\uB41C \uBCF8\uBB38\uB9CC stdout \uCD9C\uB825 (mention/link-task \uC801\uC6A9 \uACB0\uACFC \uBBF8\uB9AC\uBCF4\uAE30)").action(async (project, postNumberStr, opts) => {
|
|
2245
2590
|
const globalOpts = commentAddCommand.optsWithGlobals();
|
|
2246
2591
|
const config = await getConfigOrThrow();
|
|
2247
2592
|
const client = new DoorayApiClient(config.apiKey, config.baseUrl);
|
|
@@ -2254,12 +2599,47 @@ var commentAddCommand = new import_commander19.Command("add").description("\uB31
|
|
|
2254
2599
|
}
|
|
2255
2600
|
}
|
|
2256
2601
|
startSpinner("\uB313\uAE00 \uCD94\uAC00 \uC911...");
|
|
2257
|
-
const { projectId, postId } = await resolvePostInput(client, {
|
|
2602
|
+
const { projectId, postId, projectCode } = await resolvePostInput(client, {
|
|
2258
2603
|
projectArg: project,
|
|
2259
2604
|
postNumberArg: postNumberStr,
|
|
2260
2605
|
idOpt: opts.id,
|
|
2261
2606
|
urlOpt: opts.url
|
|
2262
2607
|
});
|
|
2608
|
+
const mentionInputs = (opts.mention ?? []).filter((s) => s.length > 0);
|
|
2609
|
+
const groupInputs = (opts.mentionGroup ?? []).filter((s) => s.length > 0);
|
|
2610
|
+
const linkInputs = (opts.linkTask ?? []).filter((s) => s.length > 0);
|
|
2611
|
+
if (mentionInputs.length > 0 || groupInputs.length > 0) {
|
|
2612
|
+
const me = await ensureMe(client);
|
|
2613
|
+
const memberIds = await Promise.all(
|
|
2614
|
+
mentionInputs.map((name) => resolveMember(client, projectId, name))
|
|
2615
|
+
);
|
|
2616
|
+
const nameMap = await buildMemberNameMap(client, projectId);
|
|
2617
|
+
const members = memberIds.map((memberId) => ({
|
|
2618
|
+
memberId,
|
|
2619
|
+
name: nameMap.get(memberId) ?? memberId
|
|
2620
|
+
}));
|
|
2621
|
+
const groups = await Promise.all(
|
|
2622
|
+
groupInputs.map(async (code) => {
|
|
2623
|
+
const g = await resolveMemberGroup(client, projectId, code);
|
|
2624
|
+
return { groupId: g.id, code: g.code, projectCode };
|
|
2625
|
+
})
|
|
2626
|
+
);
|
|
2627
|
+
bodyContent = prependMentions(bodyContent, members, groups, me);
|
|
2628
|
+
}
|
|
2629
|
+
if (linkInputs.length > 0) {
|
|
2630
|
+
const me = await ensureMe(client);
|
|
2631
|
+
const links = await resolveTaskLinks(client, linkInputs);
|
|
2632
|
+
bodyContent = appendTaskLinks(bodyContent, links, me);
|
|
2633
|
+
}
|
|
2634
|
+
if (opts.dryRun) {
|
|
2635
|
+
stopSpinner(false);
|
|
2636
|
+
if (globalOpts.json) {
|
|
2637
|
+
process.stdout.write(JSON.stringify({ body: bodyContent }) + "\n");
|
|
2638
|
+
} else {
|
|
2639
|
+
process.stdout.write(bodyContent + "\n");
|
|
2640
|
+
}
|
|
2641
|
+
return;
|
|
2642
|
+
}
|
|
2263
2643
|
const res = await client.createPostComment(projectId, postId, {
|
|
2264
2644
|
body: { mimeType: "text/x-markdown", content: bodyContent }
|
|
2265
2645
|
});
|
|
@@ -2276,7 +2656,17 @@ var commentAddCommand = new import_commander19.Command("add").description("\uB31
|
|
|
2276
2656
|
|
|
2277
2657
|
// src/commands/post/comment/edit.ts
|
|
2278
2658
|
var import_commander20 = require("commander");
|
|
2279
|
-
var commentEditCommand = new import_commander20.Command("edit").description("\uB313\uAE00 \uC218\uC815 ($EDITOR \uB610\uB294 --body \uC635\uC158)").argument("[arg1]", "\uD504\uB85C\uC81D\uD2B8 \uCF54\uB4DC / Dooray URL / \uB313\uAE00 ID (\uBAA8\uB4DC\uBCC4)").argument("[arg2]", "\uC5C5\uBB34 \uBC88\uD638 \uB610\uB294 \uB313\uAE00 ID (\uBAA8\uB4DC\uBCC4)").argument("[arg3]", "\uB313\uAE00 ID (positional 3\uAC1C \uBAA8\uB4DC)").option("--id <postId>", "Dooray post ID (project/post-number \uB300\uC2E0)").option("--url <url>", "Dooray \uC5C5\uBB34 URL (project/post-number \uB300\uC2E0)").option("--comment-id <commentId>", "\uB313\uAE00 ID (positional \uB300\uCCB4)").option("--body <text>", "\uB313\uAE00 \uBCF8\uBB38 \uBCC0\uACBD (- \uC785\uB825 \uC2DC stdin, non-interactive)").option("--body-file <path>", "\uBCF8\uBB38 \uD30C\uC77C \uACBD\uB85C (- \uC785\uB825 \uC2DC stdin, non-interactive)").
|
|
2659
|
+
var commentEditCommand = new import_commander20.Command("edit").description("\uB313\uAE00 \uC218\uC815 ($EDITOR \uB610\uB294 --body \uC635\uC158)").argument("[arg1]", "\uD504\uB85C\uC81D\uD2B8 \uCF54\uB4DC / Dooray URL / \uB313\uAE00 ID (\uBAA8\uB4DC\uBCC4)").argument("[arg2]", "\uC5C5\uBB34 \uBC88\uD638 \uB610\uB294 \uB313\uAE00 ID (\uBAA8\uB4DC\uBCC4)").argument("[arg3]", "\uB313\uAE00 ID (positional 3\uAC1C \uBAA8\uB4DC)").option("--id <postId>", "Dooray post ID (project/post-number \uB300\uC2E0)").option("--url <url>", "Dooray \uC5C5\uBB34 URL (project/post-number \uB300\uC2E0)").option("--comment-id <commentId>", "\uB313\uAE00 ID (positional \uB300\uCCB4)").option("--body <text>", "\uB313\uAE00 \uBCF8\uBB38 \uBCC0\uACBD (- \uC785\uB825 \uC2DC stdin, non-interactive)").option("--body-file <path>", "\uBCF8\uBB38 \uD30C\uC77C \uACBD\uB85C (- \uC785\uB825 \uC2DC stdin, non-interactive)").option("--no-confirm", "\uB204\uB77D attachment \uACBD\uACE0 \uC2DC confirm \uC5C6\uC774 \uC9C4\uD589 (\uC790\uB3D9\uD654\uC6A9)").option(
|
|
2660
|
+
"--mention <name>",
|
|
2661
|
+
"\uBA64\uBC84 \uBA58\uC158 (\uBC18\uBCF5 \uAC00\uB2A5, \uC774\uB984 \uBD80\uBD84\uC77C\uCE58)",
|
|
2662
|
+
(value, prev) => [...prev, value],
|
|
2663
|
+
[]
|
|
2664
|
+
).option(
|
|
2665
|
+
"--mention-group <code>",
|
|
2666
|
+
"\uADF8\uB8F9 \uBA58\uC158 (\uBC18\uBCF5 \uAC00\uB2A5, code \uBD80\uBD84\uC77C\uCE58)",
|
|
2667
|
+
(value, prev) => [...prev, value],
|
|
2668
|
+
[]
|
|
2669
|
+
).option("--link-task <ref>", "\uB2E4\uB978 \uC5C5\uBB34 \uB9C1\uD06C \uCD94\uAC00 (<project>/<number> \uB610\uB294 postId, \uBC18\uBCF5 \uAC00\uB2A5)", (v, prev) => [...prev, v], []).option("--dry-run", "API \uD638\uCD9C \uC5C6\uC774 \uD569\uC131\uB41C \uBCF8\uBB38\uB9CC stdout \uCD9C\uB825 (mention/link-task \uC801\uC6A9 \uACB0\uACFC \uBBF8\uB9AC\uBCF4\uAE30)").action(async (arg1, arg2, arg3, opts) => {
|
|
2280
2670
|
const config = await getConfigOrThrow();
|
|
2281
2671
|
const client = new DoorayApiClient(config.apiKey, config.baseUrl);
|
|
2282
2672
|
let projectArg;
|
|
@@ -2319,7 +2709,7 @@ var commentEditCommand = new import_commander20.Command("edit").description("\uB
|
|
|
2319
2709
|
);
|
|
2320
2710
|
}
|
|
2321
2711
|
startSpinner("\uB313\uAE00 \uC870\uD68C \uC911...");
|
|
2322
|
-
const { projectId, postId } = await resolvePostInput(client, {
|
|
2712
|
+
const { projectId, postId, projectCode } = await resolvePostInput(client, {
|
|
2323
2713
|
projectArg,
|
|
2324
2714
|
postNumberArg,
|
|
2325
2715
|
idOpt: opts.id,
|
|
@@ -2333,15 +2723,57 @@ var commentEditCommand = new import_commander20.Command("edit").description("\uB
|
|
|
2333
2723
|
`);
|
|
2334
2724
|
process.exit(1);
|
|
2335
2725
|
}
|
|
2726
|
+
const mentionInputs = (opts.mention ?? []).filter((s) => s.length > 0);
|
|
2727
|
+
const groupInputs = (opts.mentionGroup ?? []).filter((s) => s.length > 0);
|
|
2728
|
+
const linkInputs = (opts.linkTask ?? []).filter((s) => s.length > 0);
|
|
2729
|
+
let mentionPrefix = "";
|
|
2730
|
+
if (mentionInputs.length > 0 || groupInputs.length > 0) {
|
|
2731
|
+
const me = await ensureMe(client);
|
|
2732
|
+
const memberIds = await Promise.all(
|
|
2733
|
+
mentionInputs.map((name) => resolveMember(client, projectId, name))
|
|
2734
|
+
);
|
|
2735
|
+
const nameMap = await buildMemberNameMap(client, projectId);
|
|
2736
|
+
const members = memberIds.map((memberId) => ({
|
|
2737
|
+
memberId,
|
|
2738
|
+
name: nameMap.get(memberId) ?? memberId
|
|
2739
|
+
}));
|
|
2740
|
+
const groups = await Promise.all(
|
|
2741
|
+
groupInputs.map(async (code) => {
|
|
2742
|
+
const g = await resolveMemberGroup(client, projectId, code);
|
|
2743
|
+
return { groupId: g.id, code: g.code, projectCode };
|
|
2744
|
+
})
|
|
2745
|
+
);
|
|
2746
|
+
mentionPrefix = prependMentions("", members, groups, me).trimEnd();
|
|
2747
|
+
}
|
|
2336
2748
|
let edited = await readBodyInputOrNull(opts);
|
|
2337
2749
|
if (edited == null) {
|
|
2338
|
-
const
|
|
2339
|
-
|
|
2340
|
-
|
|
2750
|
+
const rawContent = comment.body.content;
|
|
2751
|
+
const editorSeed = mentionPrefix ? mentionPrefix + " " + rawContent : rawContent;
|
|
2752
|
+
edited = await openInEditor(editorSeed);
|
|
2753
|
+
if (rawContent === edited) {
|
|
2341
2754
|
process.stdout.write("\uBCC0\uACBD\uC0AC\uD56D \uC5C6\uC74C\n");
|
|
2342
2755
|
return;
|
|
2343
2756
|
}
|
|
2757
|
+
} else if (mentionPrefix) {
|
|
2758
|
+
edited = mentionPrefix + " " + edited;
|
|
2344
2759
|
}
|
|
2760
|
+
if (linkInputs.length > 0) {
|
|
2761
|
+
const me = await ensureMe(client);
|
|
2762
|
+
const links = await resolveTaskLinks(client, linkInputs);
|
|
2763
|
+
edited = appendTaskLinks(edited, links, me);
|
|
2764
|
+
}
|
|
2765
|
+
if (opts.dryRun) {
|
|
2766
|
+
stopSpinner(false);
|
|
2767
|
+
const globalOpts = commentEditCommand.optsWithGlobals();
|
|
2768
|
+
if (globalOpts.json) {
|
|
2769
|
+
process.stdout.write(JSON.stringify({ body: edited }) + "\n");
|
|
2770
|
+
} else {
|
|
2771
|
+
process.stdout.write(edited + "\n");
|
|
2772
|
+
}
|
|
2773
|
+
return;
|
|
2774
|
+
}
|
|
2775
|
+
const attachments = (comment.files ?? []).map((f) => ({ id: f.id, name: f.name }));
|
|
2776
|
+
await checkAndGuardDropped(comment.body.content, edited, attachments, !opts.confirm);
|
|
2345
2777
|
startSpinner("\uB313\uAE00 \uC218\uC815 \uC911...");
|
|
2346
2778
|
await client.updatePostComment(projectId, postId, commentId, {
|
|
2347
2779
|
body: { mimeType: "text/x-markdown", content: edited }
|
|
@@ -2408,14 +2840,397 @@ var commentDeleteCommand = new import_commander21.Command("delete").description(
|
|
|
2408
2840
|
`);
|
|
2409
2841
|
});
|
|
2410
2842
|
|
|
2411
|
-
// src/commands/post/
|
|
2843
|
+
// src/commands/post/comment/get.ts
|
|
2412
2844
|
var import_commander22 = require("commander");
|
|
2845
|
+
|
|
2846
|
+
// src/formatters/comment.ts
|
|
2847
|
+
function formatCommentDetail(comment, opts) {
|
|
2848
|
+
if (opts.json) {
|
|
2849
|
+
printJson(comment);
|
|
2850
|
+
return;
|
|
2851
|
+
}
|
|
2852
|
+
if (opts.quiet) {
|
|
2853
|
+
process.stdout.write(comment.id + "\n");
|
|
2854
|
+
return;
|
|
2855
|
+
}
|
|
2856
|
+
const metaRows = [
|
|
2857
|
+
["ID", comment.id],
|
|
2858
|
+
["\uC791\uC131\uC790", comment.creator.member?.name ?? ""],
|
|
2859
|
+
["\uC0DD\uC131", comment.createdAt],
|
|
2860
|
+
...comment.modifiedAt ? [["\uC218\uC815", comment.modifiedAt]] : [],
|
|
2861
|
+
["mimeType", comment.body.mimeType]
|
|
2862
|
+
];
|
|
2863
|
+
printTable(["Field", "Value"], metaRows);
|
|
2864
|
+
process.stdout.write("\n" + comment.body.content + "\n");
|
|
2865
|
+
if (comment.files && comment.files.length > 0) {
|
|
2866
|
+
process.stdout.write("\n[Attachments]\n");
|
|
2867
|
+
printTable(
|
|
2868
|
+
["Name", "Size", "ID"],
|
|
2869
|
+
comment.files.map((f) => [f.name, String(f.size), f.id])
|
|
2870
|
+
);
|
|
2871
|
+
}
|
|
2872
|
+
}
|
|
2873
|
+
|
|
2874
|
+
// src/commands/post/comment/get.ts
|
|
2875
|
+
function parseGetArgs(arg1, arg2, arg3, opts) {
|
|
2876
|
+
const hasPositional = arg1 !== void 0 || arg2 !== void 0 || arg3 !== void 0;
|
|
2877
|
+
const hasIdUrl = !!(opts.id || opts.url);
|
|
2878
|
+
if (hasPositional && hasIdUrl) {
|
|
2879
|
+
throw new DoorayCliError(
|
|
2880
|
+
"positional \uC778\uC790\uC640 --id/--url \uC635\uC158\uC740 \uB3D9\uC2DC\uC5D0 \uC0AC\uC6A9\uD560 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4.",
|
|
2881
|
+
EXIT_PARAM_ERROR
|
|
2882
|
+
);
|
|
2883
|
+
}
|
|
2884
|
+
if (hasIdUrl) {
|
|
2885
|
+
if (!opts.commentId) {
|
|
2886
|
+
throw new DoorayCliError(
|
|
2887
|
+
"--id/--url \uBAA8\uB4DC\uC5D0\uC11C\uB294 --comment-id \uC635\uC158\uC774 \uD544\uC694\uD569\uB2C8\uB2E4.",
|
|
2888
|
+
EXIT_PARAM_ERROR
|
|
2889
|
+
);
|
|
2890
|
+
}
|
|
2891
|
+
return { commentId: opts.commentId, idOpt: opts.id, urlOpt: opts.url };
|
|
2892
|
+
}
|
|
2893
|
+
if (arg3) {
|
|
2894
|
+
if (opts.commentId) {
|
|
2895
|
+
throw new DoorayCliError(
|
|
2896
|
+
"positional \uB313\uAE00 ID \uC640 --comment-id \uC635\uC158\uC740 \uB3D9\uC2DC\uC5D0 \uC0AC\uC6A9\uD560 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4.",
|
|
2897
|
+
EXIT_PARAM_ERROR
|
|
2898
|
+
);
|
|
2899
|
+
}
|
|
2900
|
+
return {
|
|
2901
|
+
projectArg: arg1,
|
|
2902
|
+
postNumberArg: arg2,
|
|
2903
|
+
commentId: arg3
|
|
2904
|
+
};
|
|
2905
|
+
}
|
|
2906
|
+
if (arg1 && arg2 && opts.commentId) {
|
|
2907
|
+
return {
|
|
2908
|
+
projectArg: arg1,
|
|
2909
|
+
postNumberArg: arg2,
|
|
2910
|
+
commentId: opts.commentId
|
|
2911
|
+
};
|
|
2912
|
+
}
|
|
2913
|
+
throw new DoorayCliError(
|
|
2914
|
+
"<comment-id>\uAC00 \uD544\uC694\uD569\uB2C8\uB2E4. positional 3\uBC88\uC9F8 \uB610\uB294 --comment-id \uC635\uC158\uC744 \uC0AC\uC6A9\uD558\uC138\uC694.",
|
|
2915
|
+
EXIT_PARAM_ERROR
|
|
2916
|
+
);
|
|
2917
|
+
}
|
|
2918
|
+
var commentGetCommand = new import_commander22.Command("get").description("\uB2E8\uC77C \uB313\uAE00 \uBCF8\uBB38 + \uBA54\uD0C0 + attachments \uC870\uD68C").argument("[arg1]", "\uD504\uB85C\uC81D\uD2B8 \uCF54\uB4DC / Dooray URL (\uBAA8\uB4DC\uBCC4)").argument("[arg2]", "\uC5C5\uBB34 \uBC88\uD638 (\uBAA8\uB4DC\uBCC4)").argument("[arg3]", "\uB313\uAE00 ID (positional 3\uAC1C \uBAA8\uB4DC)").option("--id <postId>", "Dooray post ID (positional \uB300\uC2E0)").option("--url <url>", "Dooray \uC5C5\uBB34 URL (positional \uB300\uC2E0)").option("--comment-id <id>", "\uB313\uAE00 ID (arg3 \uB300\uC2E0)").action(async (arg1, arg2, arg3, opts) => {
|
|
2919
|
+
const parsed = parseGetArgs(arg1, arg2, arg3, opts);
|
|
2920
|
+
const config = await getConfigOrThrow();
|
|
2921
|
+
const client = new DoorayApiClient(config.apiKey, config.baseUrl);
|
|
2922
|
+
const globalOpts = commentGetCommand.optsWithGlobals();
|
|
2923
|
+
startSpinner("\uB313\uAE00 \uC870\uD68C \uC911...");
|
|
2924
|
+
let projectId;
|
|
2925
|
+
let comment;
|
|
2926
|
+
try {
|
|
2927
|
+
const resolved = await resolvePostInput(client, {
|
|
2928
|
+
projectArg: parsed.projectArg,
|
|
2929
|
+
postNumberArg: parsed.postNumberArg,
|
|
2930
|
+
idOpt: parsed.idOpt,
|
|
2931
|
+
urlOpt: parsed.urlOpt
|
|
2932
|
+
});
|
|
2933
|
+
projectId = resolved.projectId;
|
|
2934
|
+
const detail = await client.getPostComment(resolved.projectId, resolved.postId, parsed.commentId);
|
|
2935
|
+
comment = detail.result;
|
|
2936
|
+
stopSpinner(true, "\uB313\uAE00 \uC870\uD68C \uC644\uB8CC");
|
|
2937
|
+
} catch (e) {
|
|
2938
|
+
stopSpinner(false);
|
|
2939
|
+
throw e;
|
|
2940
|
+
}
|
|
2941
|
+
if (!globalOpts.json) {
|
|
2942
|
+
let nameMap = /* @__PURE__ */ new Map();
|
|
2943
|
+
try {
|
|
2944
|
+
nameMap = await buildMemberNameMap(client, projectId);
|
|
2945
|
+
} catch {
|
|
2946
|
+
}
|
|
2947
|
+
comment = enrichCommentCreators([comment], nameMap)[0];
|
|
2948
|
+
}
|
|
2949
|
+
formatCommentDetail(comment, globalOpts);
|
|
2950
|
+
});
|
|
2951
|
+
|
|
2952
|
+
// src/commands/post/comment/file/index.ts
|
|
2953
|
+
var import_commander27 = require("commander");
|
|
2954
|
+
|
|
2955
|
+
// src/commands/post/comment/file/list.ts
|
|
2956
|
+
var import_commander23 = require("commander");
|
|
2957
|
+
|
|
2958
|
+
// src/resolvers/comment-file-input.ts
|
|
2959
|
+
var FILE_ID_SECONDARY_LABEL = {
|
|
2960
|
+
positional: "4\uBC88\uC9F8",
|
|
2961
|
+
option: "--file-id",
|
|
2962
|
+
identifier: "<fileId>"
|
|
2963
|
+
};
|
|
2964
|
+
function assertNonEmpty(value, fieldName) {
|
|
2965
|
+
if (value.trim() === "") {
|
|
2966
|
+
throw new DoorayCliError(
|
|
2967
|
+
`${fieldName} \uAC00 \uBE44\uC5B4 \uC788\uC2B5\uB2C8\uB2E4.`,
|
|
2968
|
+
EXIT_PARAM_ERROR
|
|
2969
|
+
);
|
|
2970
|
+
}
|
|
2971
|
+
}
|
|
2972
|
+
function parseImpl(args) {
|
|
2973
|
+
const isOptionMode = !!(args.idOpt || args.urlOpt);
|
|
2974
|
+
let projectArg;
|
|
2975
|
+
let postNumberArg;
|
|
2976
|
+
let commentId = args.commentIdOpt;
|
|
2977
|
+
let secondary = args.secondaryOpt;
|
|
2978
|
+
if (isOptionMode) {
|
|
2979
|
+
if (!commentId) commentId = args.arg1;
|
|
2980
|
+
if (!secondary) secondary = args.arg2;
|
|
2981
|
+
if (args.arg3 || args.arg4) {
|
|
2982
|
+
throw new DoorayCliError(
|
|
2983
|
+
"--id/--url \uBAA8\uB4DC\uC5D0\uC11C\uB294 \uCD94\uAC00 positional \uC778\uC790\uAC00 \uD5C8\uC6A9\uB418\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4.",
|
|
2984
|
+
EXIT_PARAM_ERROR
|
|
2985
|
+
);
|
|
2986
|
+
}
|
|
2987
|
+
} else {
|
|
2988
|
+
projectArg = args.arg1;
|
|
2989
|
+
postNumberArg = args.arg2;
|
|
2990
|
+
if (!commentId) commentId = args.arg3;
|
|
2991
|
+
if (!secondary) secondary = args.arg4;
|
|
2992
|
+
}
|
|
2993
|
+
if (!commentId) {
|
|
2994
|
+
throw new DoorayCliError(
|
|
2995
|
+
"<comment-id> \uAC00 \uD544\uC694\uD569\uB2C8\uB2E4. positional 3\uBC88\uC9F8 \uB610\uB294 --comment-id \uC635\uC158\uC744 \uC0AC\uC6A9\uD558\uC138\uC694.",
|
|
2996
|
+
EXIT_PARAM_ERROR
|
|
2997
|
+
);
|
|
2998
|
+
}
|
|
2999
|
+
assertNonEmpty(commentId, "<comment-id>");
|
|
3000
|
+
if (args.requireSecondary) {
|
|
3001
|
+
if (!secondary) {
|
|
3002
|
+
const { identifier, positional, option } = args.secondaryLabel;
|
|
3003
|
+
throw new DoorayCliError(
|
|
3004
|
+
`${identifier} \uAC00 \uD544\uC694\uD569\uB2C8\uB2E4. positional ${positional} \uB610\uB294 ${option} \uC635\uC158\uC744 \uC0AC\uC6A9\uD558\uC138\uC694.`,
|
|
3005
|
+
EXIT_PARAM_ERROR
|
|
3006
|
+
);
|
|
3007
|
+
}
|
|
3008
|
+
assertNonEmpty(secondary, args.secondaryLabel.identifier);
|
|
3009
|
+
} else if (secondary !== void 0) {
|
|
3010
|
+
assertNonEmpty(secondary, "<secondary>");
|
|
3011
|
+
}
|
|
3012
|
+
return { projectArg, postNumberArg, commentId, secondary };
|
|
3013
|
+
}
|
|
3014
|
+
async function resolveCommentFileInput(client, args) {
|
|
3015
|
+
const { projectArg, postNumberArg, commentId, secondary } = parseImpl(args);
|
|
3016
|
+
const { projectId, postId } = await resolvePostInput(client, {
|
|
3017
|
+
projectArg,
|
|
3018
|
+
postNumberArg,
|
|
3019
|
+
idOpt: args.idOpt,
|
|
3020
|
+
urlOpt: args.urlOpt
|
|
3021
|
+
});
|
|
3022
|
+
return { projectId, postId, commentId, secondary };
|
|
3023
|
+
}
|
|
3024
|
+
|
|
3025
|
+
// src/commands/post/comment/file/list.ts
|
|
2413
3026
|
function formatSize(bytes) {
|
|
2414
3027
|
if (bytes < 1024) return `${bytes}B`;
|
|
2415
3028
|
if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)}KB`;
|
|
2416
3029
|
return `${(bytes / (1024 * 1024)).toFixed(1)}MB`;
|
|
2417
3030
|
}
|
|
2418
|
-
var
|
|
3031
|
+
var listCommentFileCommand = new import_commander23.Command("list").description("\uB313\uAE00 \uCCA8\uBD80 \uD30C\uC77C \uBAA9\uB85D \uC870\uD68C").argument("[arg1]", "\uD504\uB85C\uC81D\uD2B8 \uCF54\uB4DC, Dooray URL, \uB610\uB294 (`--id`/`--url` \uBAA8\uB4DC\uC77C \uB54C) \uB313\uAE00 ID").argument("[arg2]", "\uC5C5\uBB34 \uBC88\uD638 (positional \uBAA8\uB4DC)").argument("[arg3]", "\uB313\uAE00 ID (positional 3\uAC1C \uBAA8\uB4DC)").option("--id <postId>", "Dooray post ID (project/post-number \uB300\uC2E0)").option("--url <url>", "Dooray \uC5C5\uBB34 URL (project/post-number \uB300\uC2E0)").option("--comment-id <logId>", "\uB313\uAE00 ID (positional \uB300\uCCB4)").action(async (arg1, arg2, arg3, opts) => {
|
|
3032
|
+
const globalOpts = listCommentFileCommand.optsWithGlobals();
|
|
3033
|
+
const config = await getConfigOrThrow();
|
|
3034
|
+
const client = new DoorayApiClient(config.apiKey, config.baseUrl);
|
|
3035
|
+
const { projectId, postId, commentId } = await resolveCommentFileInput(client, {
|
|
3036
|
+
arg1,
|
|
3037
|
+
arg2,
|
|
3038
|
+
arg3,
|
|
3039
|
+
idOpt: opts.id,
|
|
3040
|
+
urlOpt: opts.url,
|
|
3041
|
+
commentIdOpt: opts.commentId,
|
|
3042
|
+
requireSecondary: false
|
|
3043
|
+
});
|
|
3044
|
+
startSpinner("\uB313\uAE00 \uCCA8\uBD80 \uD30C\uC77C \uBAA9\uB85D \uC870\uD68C \uC911...");
|
|
3045
|
+
const res = await client.getPostComment(projectId, postId, commentId);
|
|
3046
|
+
const files = res.result.files ?? [];
|
|
3047
|
+
stopSpinner(true, `\uCCA8\uBD80 \uD30C\uC77C ${files.length}\uAC1C`);
|
|
3048
|
+
if (files.length === 0) {
|
|
3049
|
+
if (globalOpts.json) {
|
|
3050
|
+
process.stdout.write("[]\n");
|
|
3051
|
+
} else if (!globalOpts.quiet) {
|
|
3052
|
+
process.stdout.write("\uCCA8\uBD80 \uC5C6\uC74C\n");
|
|
3053
|
+
}
|
|
3054
|
+
return;
|
|
3055
|
+
}
|
|
3056
|
+
output(globalOpts, {
|
|
3057
|
+
headers: ["\uD30C\uC77C\uBA85", "\uD06C\uAE30", "ID"],
|
|
3058
|
+
rows: files.map((f) => [f.name, formatSize(f.size), f.id]),
|
|
3059
|
+
raw: files,
|
|
3060
|
+
ids: files.map((f) => f.id)
|
|
3061
|
+
});
|
|
3062
|
+
});
|
|
3063
|
+
|
|
3064
|
+
// src/commands/post/comment/file/upload.ts
|
|
3065
|
+
var import_commander24 = require("commander");
|
|
3066
|
+
var import_node_path4 = require("path");
|
|
3067
|
+
|
|
3068
|
+
// src/utils/comment-files.ts
|
|
3069
|
+
function appendFileReference(body, fileName, fileId) {
|
|
3070
|
+
const safeName = fileName.replace(/[\[\]]/g, "");
|
|
3071
|
+
const ref = ``;
|
|
3072
|
+
if (body.length === 0) return ref;
|
|
3073
|
+
const trailing = body.endsWith("\n") ? "" : "\n";
|
|
3074
|
+
return `${body}${trailing}
|
|
3075
|
+
${ref}`;
|
|
3076
|
+
}
|
|
3077
|
+
function removeFileReference(body, fileId) {
|
|
3078
|
+
const escaped = fileId.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
3079
|
+
const refSource = `!\\[[^\\]]*\\]\\(/files/${escaped}\\)`;
|
|
3080
|
+
const lineRe = new RegExp(`^[ \\t]*${refSource}[ \\t]*$\\n?`, "gm");
|
|
3081
|
+
const inlineRe = new RegExp(refSource, "g");
|
|
3082
|
+
return body.replace(lineRe, "").replace(inlineRe, "");
|
|
3083
|
+
}
|
|
3084
|
+
|
|
3085
|
+
// src/commands/post/comment/file/upload.ts
|
|
3086
|
+
var uploadCommentFileCommand = new import_commander24.Command("upload").description("\uB313\uAE00\uC5D0 \uD30C\uC77C \uC5C5\uB85C\uB4DC (post-level \uD30C\uC77C \uC5C5\uB85C\uB4DC + \uB313\uAE00 reference \uCD94\uAC00, ADR-024)").argument("[arg1]", "\uD504\uB85C\uC81D\uD2B8 \uCF54\uB4DC, Dooray URL, \uB610\uB294 (`--id`/`--url` \uBAA8\uB4DC\uC77C \uB54C) \uB313\uAE00 ID").argument("[arg2]", "\uC5C5\uBB34 \uBC88\uD638 \uB610\uB294 (`--id`/`--url` \uBAA8\uB4DC\uC77C \uB54C) \uD30C\uC77C \uACBD\uB85C").argument("[arg3]", "\uB313\uAE00 ID (positional \uBAA8\uB4DC)").argument("[arg4]", "\uD30C\uC77C \uACBD\uB85C (positional \uBAA8\uB4DC)").option("--id <postId>", "Dooray post ID (project/post-number \uB300\uC2E0)").option("--url <url>", "Dooray \uC5C5\uBB34 URL (project/post-number \uB300\uC2E0)").option("--comment-id <logId>", "\uB313\uAE00 ID (positional \uB300\uCCB4)").option("--file <path>", "\uC5C5\uB85C\uB4DC\uD560 \uD30C\uC77C \uACBD\uB85C (positional \uB300\uCCB4)").action(async (arg1, arg2, arg3, arg4, opts) => {
|
|
3087
|
+
const globalOpts = uploadCommentFileCommand.optsWithGlobals();
|
|
3088
|
+
const config = await getConfigOrThrow();
|
|
3089
|
+
const client = new DoorayApiClient(config.apiKey, config.baseUrl);
|
|
3090
|
+
const { projectId, postId, commentId, secondary: filePath } = await resolveCommentFileInput(client, {
|
|
3091
|
+
arg1,
|
|
3092
|
+
arg2,
|
|
3093
|
+
arg3,
|
|
3094
|
+
arg4,
|
|
3095
|
+
idOpt: opts.id,
|
|
3096
|
+
urlOpt: opts.url,
|
|
3097
|
+
commentIdOpt: opts.commentId,
|
|
3098
|
+
secondaryOpt: opts.file,
|
|
3099
|
+
requireSecondary: true,
|
|
3100
|
+
secondaryLabel: { positional: "4\uBC88\uC9F8", option: "--file", identifier: "<path>" }
|
|
3101
|
+
});
|
|
3102
|
+
startSpinner("\uD30C\uC77C \uC5C5\uB85C\uB4DC \uC911...");
|
|
3103
|
+
const uploadRes = await client.uploadPostFile(projectId, postId, filePath);
|
|
3104
|
+
const fileId = uploadRes.result.id;
|
|
3105
|
+
const fileName = (0, import_node_path4.basename)(filePath);
|
|
3106
|
+
stopSpinner(true, "\uC5C5\uB85C\uB4DC \uC644\uB8CC");
|
|
3107
|
+
startSpinner("\uB313\uAE00 reference \uCD94\uAC00 \uC911...");
|
|
3108
|
+
try {
|
|
3109
|
+
const commentRes = await client.getPostComment(projectId, postId, commentId);
|
|
3110
|
+
const currentBody = commentRes.result.body.content;
|
|
3111
|
+
const newBody = appendFileReference(currentBody, fileName, fileId);
|
|
3112
|
+
await client.updatePostComment(projectId, postId, commentId, {
|
|
3113
|
+
body: { mimeType: "text/x-markdown", content: newBody }
|
|
3114
|
+
});
|
|
3115
|
+
stopSpinner(true, "reference \uCD94\uAC00 \uC644\uB8CC");
|
|
3116
|
+
} catch {
|
|
3117
|
+
stopSpinner(false, "");
|
|
3118
|
+
throw new DoorayCliError(
|
|
3119
|
+
`\uC5C5\uB85C\uB4DC OK / \uB313\uAE00 reference \uCD94\uAC00 \uC2E4\uD328. fileId=${fileId} \u2014 'dooray post comment file delete' \uB610\uB294 \uC218\uB3D9 PUT \uC73C\uB85C \uC815\uB9AC\uD558\uC138\uC694.`,
|
|
3120
|
+
EXIT_API_ERROR
|
|
3121
|
+
);
|
|
3122
|
+
}
|
|
3123
|
+
if (globalOpts.json) {
|
|
3124
|
+
printJson({ fileId, fileName, commentId });
|
|
3125
|
+
} else if (globalOpts.quiet) {
|
|
3126
|
+
process.stdout.write(`${fileId}
|
|
3127
|
+
`);
|
|
3128
|
+
} else {
|
|
3129
|
+
process.stdout.write(`\uC5C5\uB85C\uB4DC + \uB313\uAE00 reference \uCD94\uAC00: fileId=${fileId}
|
|
3130
|
+
`);
|
|
3131
|
+
}
|
|
3132
|
+
});
|
|
3133
|
+
|
|
3134
|
+
// src/commands/post/comment/file/download.ts
|
|
3135
|
+
var import_commander25 = require("commander");
|
|
3136
|
+
var import_promises8 = require("fs/promises");
|
|
3137
|
+
var import_node_path5 = require("path");
|
|
3138
|
+
var downloadCommentFileCommand = new import_commander25.Command("download").description(
|
|
3139
|
+
"\uB313\uAE00\uC5D0 \uCCA8\uBD80\uB41C \uD30C\uC77C \uB2E4\uC6B4\uB85C\uB4DC (\uD604\uC7AC comment-id \uB294 \uBBF8\uC0AC\uC6A9 \u2014 \uBA58\uD0C8 \uBAA8\uB378 \uC77C\uAD00\uC131, \uBBF8\uB798 \uB313\uAE00 \uB2E8\uC704 \uAD8C\uD55C \uD638\uD658\uC6A9)"
|
|
3140
|
+
).argument("[arg1]", "\uD504\uB85C\uC81D\uD2B8 \uCF54\uB4DC, Dooray URL, \uB610\uB294 (`--id`/`--url` \uBAA8\uB4DC\uC77C \uB54C) \uB313\uAE00 ID").argument("[arg2]", "\uC5C5\uBB34 \uBC88\uD638 \uB610\uB294 (`--id`/`--url` \uBAA8\uB4DC\uC77C \uB54C) \uD30C\uC77C ID").argument("[arg3]", "\uB313\uAE00 ID (positional \uBAA8\uB4DC)").argument("[arg4]", "\uD30C\uC77C ID (positional \uBAA8\uB4DC)").option("--id <postId>", "Dooray post ID (project/post-number \uB300\uC2E0)").option("--url <url>", "Dooray \uC5C5\uBB34 URL (project/post-number \uB300\uC2E0)").option("--comment-id <logId>", "\uB313\uAE00 ID (positional \uB300\uCCB4)").option("--file-id <fileId>", "\uD30C\uC77C ID (positional \uB300\uCCB4)").option("--out <path>", "\uC800\uC7A5 \uACBD\uB85C (\uBBF8\uC9C0\uC815 \uC2DC \uD604\uC7AC \uB514\uB809\uD1A0\uB9AC\uC5D0 \uC6D0\uBCF8 \uD30C\uC77C\uBA85\uC73C\uB85C \uC800\uC7A5)", ".").action(async (arg1, arg2, arg3, arg4, opts) => {
|
|
3141
|
+
const config = await getConfigOrThrow();
|
|
3142
|
+
const client = new DoorayApiClient(config.apiKey, config.baseUrl);
|
|
3143
|
+
const { projectId, postId, secondary: fileId } = await resolveCommentFileInput(client, {
|
|
3144
|
+
arg1,
|
|
3145
|
+
arg2,
|
|
3146
|
+
arg3,
|
|
3147
|
+
arg4,
|
|
3148
|
+
idOpt: opts.id,
|
|
3149
|
+
urlOpt: opts.url,
|
|
3150
|
+
commentIdOpt: opts.commentId,
|
|
3151
|
+
secondaryOpt: opts.fileId,
|
|
3152
|
+
requireSecondary: true,
|
|
3153
|
+
secondaryLabel: FILE_ID_SECONDARY_LABEL
|
|
3154
|
+
});
|
|
3155
|
+
startSpinner("\uD30C\uC77C \uB2E4\uC6B4\uB85C\uB4DC \uC911...");
|
|
3156
|
+
const { buffer, fileName } = await client.downloadPostFile(projectId, postId, fileId);
|
|
3157
|
+
const safeName = (0, import_node_path5.basename)(fileName);
|
|
3158
|
+
const outputPath = (0, import_node_path5.join)(opts.out, safeName);
|
|
3159
|
+
await (0, import_promises8.writeFile)(outputPath, Buffer.from(buffer));
|
|
3160
|
+
stopSpinner(true, "\uB2E4\uC6B4\uB85C\uB4DC \uC644\uB8CC");
|
|
3161
|
+
process.stdout.write(`${outputPath}
|
|
3162
|
+
`);
|
|
3163
|
+
});
|
|
3164
|
+
|
|
3165
|
+
// src/commands/post/comment/file/delete.ts
|
|
3166
|
+
var import_commander26 = require("commander");
|
|
3167
|
+
var deleteCommentFileCommand = new import_commander26.Command("delete").description("\uB313\uAE00 \uCCA8\uBD80 \uD30C\uC77C \uC0AD\uC81C (\uB313\uAE00 \uBCF8\uBB38 reference \uC81C\uAC70 + \uD30C\uC77C \uC0AD\uC81C, ADR-024)").argument("[arg1]", "\uD504\uB85C\uC81D\uD2B8 \uCF54\uB4DC, Dooray URL, \uB610\uB294 (`--id`/`--url` \uBAA8\uB4DC\uC77C \uB54C) \uB313\uAE00 ID").argument("[arg2]", "\uC5C5\uBB34 \uBC88\uD638 \uB610\uB294 (`--id`/`--url` \uBAA8\uB4DC\uC77C \uB54C) \uD30C\uC77C ID").argument("[arg3]", "\uB313\uAE00 ID (positional \uBAA8\uB4DC)").argument("[arg4]", "\uD30C\uC77C ID (positional \uBAA8\uB4DC)").option("--id <postId>", "Dooray post ID (project/post-number \uB300\uC2E0)").option("--url <url>", "Dooray \uC5C5\uBB34 URL (project/post-number \uB300\uC2E0)").option("--comment-id <logId>", "\uB313\uAE00 ID (positional \uB300\uCCB4)").option("--file-id <fileId>", "\uD30C\uC77C ID (positional \uB300\uCCB4)").option("--yes", "\uD655\uC778 \uC5C6\uC774 \uC0AD\uC81C").action(async (arg1, arg2, arg3, arg4, opts) => {
|
|
3168
|
+
const config = await getConfigOrThrow();
|
|
3169
|
+
const client = new DoorayApiClient(config.apiKey, config.baseUrl);
|
|
3170
|
+
const { projectId, postId, commentId, secondary: fileId } = await resolveCommentFileInput(client, {
|
|
3171
|
+
arg1,
|
|
3172
|
+
arg2,
|
|
3173
|
+
arg3,
|
|
3174
|
+
arg4,
|
|
3175
|
+
idOpt: opts.id,
|
|
3176
|
+
urlOpt: opts.url,
|
|
3177
|
+
commentIdOpt: opts.commentId,
|
|
3178
|
+
secondaryOpt: opts.fileId,
|
|
3179
|
+
requireSecondary: true,
|
|
3180
|
+
secondaryLabel: FILE_ID_SECONDARY_LABEL
|
|
3181
|
+
});
|
|
3182
|
+
if (!opts.yes) {
|
|
3183
|
+
const { confirm: confirm2 } = await import("@inquirer/prompts");
|
|
3184
|
+
const ok = await confirm2({
|
|
3185
|
+
message: `\uB313\uAE00 \uBCF8\uBB38\uC5D0\uC11C reference \uB97C \uC81C\uAC70\uD558\uACE0 \uD30C\uC77C(${fileId})\uC744 \uC0AD\uC81C\uD569\uB2C8\uB2E4. \uAC19\uC740 post \uC758 \uB2E4\uB978 \uB313\uAE00\uC5D0\uC11C \uAC19\uC740 \uD30C\uC77C ID \uB97C \uCC38\uC870\uD558\uB294 \uACBD\uC6B0 broken \uB429\uB2C8\uB2E4. \uACC4\uC18D\uD558\uC2DC\uACA0\uC2B5\uB2C8\uAE4C?`
|
|
3186
|
+
});
|
|
3187
|
+
if (!ok) {
|
|
3188
|
+
process.stdout.write("\uCDE8\uC18C\uB418\uC5C8\uC2B5\uB2C8\uB2E4.\n");
|
|
3189
|
+
return;
|
|
3190
|
+
}
|
|
3191
|
+
}
|
|
3192
|
+
startSpinner("\uB313\uAE00 \uBCF8\uBB38 reference \uC81C\uAC70 \uC911...");
|
|
3193
|
+
try {
|
|
3194
|
+
const commentRes = await client.getPostComment(projectId, postId, commentId);
|
|
3195
|
+
const currentBody = commentRes.result.body.content;
|
|
3196
|
+
const newBody = removeFileReference(currentBody, fileId);
|
|
3197
|
+
await client.updatePostComment(projectId, postId, commentId, {
|
|
3198
|
+
body: { mimeType: "text/x-markdown", content: newBody }
|
|
3199
|
+
});
|
|
3200
|
+
stopSpinner(true, "reference \uC81C\uAC70 \uC644\uB8CC");
|
|
3201
|
+
} catch {
|
|
3202
|
+
stopSpinner(false, "");
|
|
3203
|
+
throw new DoorayCliError(
|
|
3204
|
+
`\uB313\uAE00 \uBCF8\uBB38 reference \uC81C\uAC70 \uC2E4\uD328. \uD30C\uC77C \uC0AD\uC81C\uB97C \uC9C4\uD589\uD558\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4. fileId=${fileId}`,
|
|
3205
|
+
EXIT_API_ERROR
|
|
3206
|
+
);
|
|
3207
|
+
}
|
|
3208
|
+
startSpinner("\uD30C\uC77C \uC0AD\uC81C \uC911...");
|
|
3209
|
+
try {
|
|
3210
|
+
await client.deletePostFile(projectId, postId, fileId);
|
|
3211
|
+
stopSpinner(true, "\uD30C\uC77C \uC0AD\uC81C \uC644\uB8CC");
|
|
3212
|
+
} catch {
|
|
3213
|
+
stopSpinner(false, "");
|
|
3214
|
+
throw new DoorayCliError(
|
|
3215
|
+
`\uB313\uAE00 \uBCF8\uBB38 reference \uC81C\uAC70 OK / \uD30C\uC77C \uC0AD\uC81C \uC2E4\uD328. 'dooray post file delete' \uB85C \uD6C4\uCC98\uB9AC\uD558\uC138\uC694. fileId=${fileId}`,
|
|
3216
|
+
EXIT_API_ERROR
|
|
3217
|
+
);
|
|
3218
|
+
}
|
|
3219
|
+
process.stdout.write(`\uD30C\uC77C(${fileId})\uC774 \uB313\uAE00(${commentId})\uC5D0\uC11C \uC0AD\uC81C\uB418\uC5C8\uC2B5\uB2C8\uB2E4.
|
|
3220
|
+
`);
|
|
3221
|
+
});
|
|
3222
|
+
|
|
3223
|
+
// src/commands/post/comment/file/index.ts
|
|
3224
|
+
var commentFileCommand = new import_commander27.Command("file").description("\uB313\uAE00 \uCCA8\uBD80 \uD30C\uC77C \uAD00\uB9AC (post-level files API + \uB313\uAE00 PUT \uD569\uC131, ADR-024)").addCommand(listCommentFileCommand).addCommand(uploadCommentFileCommand).addCommand(downloadCommentFileCommand).addCommand(deleteCommentFileCommand);
|
|
3225
|
+
|
|
3226
|
+
// src/commands/post/file/list.ts
|
|
3227
|
+
var import_commander28 = require("commander");
|
|
3228
|
+
function formatSize2(bytes) {
|
|
3229
|
+
if (bytes < 1024) return `${bytes}B`;
|
|
3230
|
+
if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)}KB`;
|
|
3231
|
+
return `${(bytes / (1024 * 1024)).toFixed(1)}MB`;
|
|
3232
|
+
}
|
|
3233
|
+
var fileListCommand = new import_commander28.Command("list").description("\uC5C5\uBB34 \uCCA8\uBD80\uD30C\uC77C \uBAA9\uB85D \uC870\uD68C").argument("[project]", "\uD504\uB85C\uC81D\uD2B8 \uCF54\uB4DC (\uB610\uB294 \uCCAB \uC778\uC790\uC5D0 Dooray URL)").argument("[post-number]", "\uC5C5\uBB34 \uBC88\uD638 (project\uC640 \uD568\uAED8 \uC0AC\uC6A9)").option("--id <postId>", "Dooray post ID (project/post-number \uB300\uC2E0)").option("--url <url>", "Dooray \uC5C5\uBB34 URL (project/post-number \uB300\uC2E0)").action(async (project, postNumberStr, opts) => {
|
|
2419
3234
|
const globalOpts = fileListCommand.optsWithGlobals();
|
|
2420
3235
|
const config = await getConfigOrThrow();
|
|
2421
3236
|
const client = new DoorayApiClient(config.apiKey, config.baseUrl);
|
|
@@ -2433,7 +3248,7 @@ var fileListCommand = new import_commander22.Command("list").description("\uC5C5
|
|
|
2433
3248
|
rows: res.result.map((f) => [
|
|
2434
3249
|
f.id,
|
|
2435
3250
|
f.name,
|
|
2436
|
-
|
|
3251
|
+
formatSize2(f.size),
|
|
2437
3252
|
f.mimeType,
|
|
2438
3253
|
f.createdAt
|
|
2439
3254
|
]),
|
|
@@ -2443,10 +3258,10 @@ var fileListCommand = new import_commander22.Command("list").description("\uC5C5
|
|
|
2443
3258
|
});
|
|
2444
3259
|
|
|
2445
3260
|
// src/commands/post/file/download.ts
|
|
2446
|
-
var
|
|
2447
|
-
var
|
|
2448
|
-
var
|
|
2449
|
-
var fileDownloadCommand = new
|
|
3261
|
+
var import_commander29 = require("commander");
|
|
3262
|
+
var import_promises9 = require("fs/promises");
|
|
3263
|
+
var import_node_path6 = require("path");
|
|
3264
|
+
var fileDownloadCommand = new import_commander29.Command("download").description("\uCCA8\uBD80\uD30C\uC77C \uB2E4\uC6B4\uB85C\uB4DC").argument("[arg1]", "\uD504\uB85C\uC81D\uD2B8 \uCF54\uB4DC, Dooray URL, \uB610\uB294 (`--id`/`--url` \uBAA8\uB4DC\uC77C \uB54C) \uD30C\uC77C ID").argument("[arg2]", "\uC5C5\uBB34 \uBC88\uD638 \uB610\uB294 (`--id`/`--url` \uBAA8\uB4DC\uC77C \uB54C) \uD30C\uC77C ID").argument("[arg3]", "\uD30C\uC77C ID (positional \uBAA8\uB4DC)").option("--id <postId>", "Dooray post ID (project/post-number \uB300\uC2E0)").option("--url <url>", "Dooray \uC5C5\uBB34 URL (project/post-number \uB300\uC2E0)").option("--file-id <fileId>", "\uD30C\uC77C ID (positional \uB300\uCCB4)").option("-o, --output <dir>", "\uC800\uC7A5 \uB514\uB809\uD1A0\uB9AC", ".").action(async (arg1, arg2, arg3, opts) => {
|
|
2450
3265
|
const config = await getConfigOrThrow();
|
|
2451
3266
|
const client = new DoorayApiClient(config.apiKey, config.baseUrl);
|
|
2452
3267
|
let projectArg;
|
|
@@ -2493,18 +3308,18 @@ var fileDownloadCommand = new import_commander23.Command("download").description
|
|
|
2493
3308
|
urlOpt: opts.url
|
|
2494
3309
|
});
|
|
2495
3310
|
const { buffer, fileName } = await client.downloadPostFile(projectId, postId, fileId);
|
|
2496
|
-
const outputPath = (0,
|
|
2497
|
-
await (0,
|
|
3311
|
+
const outputPath = (0, import_node_path6.join)(opts.output, fileName);
|
|
3312
|
+
await (0, import_promises9.writeFile)(outputPath, Buffer.from(buffer));
|
|
2498
3313
|
stopSpinner(true, "\uB2E4\uC6B4\uB85C\uB4DC \uC644\uB8CC");
|
|
2499
3314
|
process.stdout.write(`${outputPath}
|
|
2500
3315
|
`);
|
|
2501
3316
|
});
|
|
2502
3317
|
|
|
2503
3318
|
// src/commands/post/file/download-all.ts
|
|
2504
|
-
var
|
|
2505
|
-
var
|
|
2506
|
-
var
|
|
2507
|
-
var fileDownloadAllCommand = new
|
|
3319
|
+
var import_commander30 = require("commander");
|
|
3320
|
+
var import_promises10 = require("fs/promises");
|
|
3321
|
+
var import_node_path7 = require("path");
|
|
3322
|
+
var fileDownloadAllCommand = new import_commander30.Command("download-all").description("\uC5C5\uBB34\uC758 \uBAA8\uB4E0 \uCCA8\uBD80\uD30C\uC77C \uB2E4\uC6B4\uB85C\uB4DC").argument("[project]", "\uD504\uB85C\uC81D\uD2B8 \uCF54\uB4DC (\uB610\uB294 \uCCAB \uC778\uC790\uC5D0 Dooray URL)").argument("[post-number]", "\uC5C5\uBB34 \uBC88\uD638 (project\uC640 \uD568\uAED8 \uC0AC\uC6A9)").option("--id <postId>", "Dooray post ID (project/post-number \uB300\uC2E0)").option("--url <url>", "Dooray \uC5C5\uBB34 URL (project/post-number \uB300\uC2E0)").option("-o, --output <dir>", "\uC800\uC7A5 \uB514\uB809\uD1A0\uB9AC", ".").action(async (project, postNumberStr, opts) => {
|
|
2508
3323
|
const config = await getConfigOrThrow();
|
|
2509
3324
|
const client = new DoorayApiClient(config.apiKey, config.baseUrl);
|
|
2510
3325
|
const spinner = startSpinner("\uCCA8\uBD80\uD30C\uC77C \uBAA9\uB85D \uC870\uD68C \uC911...");
|
|
@@ -2520,13 +3335,13 @@ var fileDownloadAllCommand = new import_commander24.Command("download-all").desc
|
|
|
2520
3335
|
process.stdout.write("\uCCA8\uBD80\uD30C\uC77C\uC774 \uC5C6\uC2B5\uB2C8\uB2E4.\n");
|
|
2521
3336
|
return;
|
|
2522
3337
|
}
|
|
2523
|
-
await (0,
|
|
3338
|
+
await (0, import_promises10.mkdir)(opts.output, { recursive: true });
|
|
2524
3339
|
const downloaded = [];
|
|
2525
3340
|
for (const file of res.result) {
|
|
2526
3341
|
spinner.text = `\uB2E4\uC6B4\uB85C\uB4DC \uC911: ${file.name} (${downloaded.length + 1}/${res.result.length})`;
|
|
2527
3342
|
const { buffer, fileName } = await client.downloadPostFile(projectId, postId, file.id);
|
|
2528
|
-
const outputPath = (0,
|
|
2529
|
-
await (0,
|
|
3343
|
+
const outputPath = (0, import_node_path7.join)(opts.output, fileName);
|
|
3344
|
+
await (0, import_promises10.writeFile)(outputPath, Buffer.from(buffer));
|
|
2530
3345
|
downloaded.push(outputPath);
|
|
2531
3346
|
}
|
|
2532
3347
|
stopSpinner(true, `${downloaded.length}\uAC1C \uD30C\uC77C \uB2E4\uC6B4\uB85C\uB4DC \uC644\uB8CC`);
|
|
@@ -2537,9 +3352,9 @@ var fileDownloadAllCommand = new import_commander24.Command("download-all").desc
|
|
|
2537
3352
|
});
|
|
2538
3353
|
|
|
2539
3354
|
// src/commands/post/file/upload.ts
|
|
2540
|
-
var
|
|
2541
|
-
var
|
|
2542
|
-
var fileUploadCommand = new
|
|
3355
|
+
var import_commander31 = require("commander");
|
|
3356
|
+
var import_node_path8 = require("path");
|
|
3357
|
+
var fileUploadCommand = new import_commander31.Command("upload").description("\uCCA8\uBD80\uD30C\uC77C \uC5C5\uB85C\uB4DC").argument("[arg1]", "\uD504\uB85C\uC81D\uD2B8 \uCF54\uB4DC, Dooray URL, \uB610\uB294 (`--id`/`--url` \uBAA8\uB4DC\uC77C \uB54C) \uD30C\uC77C \uACBD\uB85C").argument("[arg2]", "\uC5C5\uBB34 \uBC88\uD638 \uB610\uB294 (`--id`/`--url` \uBAA8\uB4DC\uC77C \uB54C) \uD30C\uC77C \uACBD\uB85C").argument("[arg3]", "\uD30C\uC77C \uACBD\uB85C (positional \uBAA8\uB4DC)").option("--id <postId>", "Dooray post ID (project/post-number \uB300\uC2E0)").option("--url <url>", "Dooray \uC5C5\uBB34 URL (project/post-number \uB300\uC2E0)").option("--file <path>", "\uC5C5\uB85C\uB4DC\uD560 \uD30C\uC77C \uACBD\uB85C (positional \uB300\uCCB4)").action(async (arg1, arg2, arg3, opts) => {
|
|
2543
3358
|
const globalOpts = fileUploadCommand.optsWithGlobals();
|
|
2544
3359
|
const config = await getConfigOrThrow();
|
|
2545
3360
|
const client = new DoorayApiClient(config.apiKey, config.baseUrl);
|
|
@@ -2594,14 +3409,14 @@ var fileUploadCommand = new import_commander25.Command("upload").description("\u
|
|
|
2594
3409
|
process.stdout.write(`${res.result.id}
|
|
2595
3410
|
`);
|
|
2596
3411
|
} else {
|
|
2597
|
-
process.stdout.write(`\uD30C\uC77C \uC5C5\uB85C\uB4DC \uC644\uB8CC: ${(0,
|
|
3412
|
+
process.stdout.write(`\uD30C\uC77C \uC5C5\uB85C\uB4DC \uC644\uB8CC: ${(0, import_node_path8.basename)(filePath)} (ID: ${res.result.id})
|
|
2598
3413
|
`);
|
|
2599
3414
|
}
|
|
2600
3415
|
});
|
|
2601
3416
|
|
|
2602
3417
|
// src/commands/post/file/delete.ts
|
|
2603
|
-
var
|
|
2604
|
-
var fileDeleteCommand = new
|
|
3418
|
+
var import_commander32 = require("commander");
|
|
3419
|
+
var fileDeleteCommand = new import_commander32.Command("delete").description("\uCCA8\uBD80\uD30C\uC77C \uC0AD\uC81C").argument("[arg1]", "\uD504\uB85C\uC81D\uD2B8 \uCF54\uB4DC, Dooray URL, \uB610\uB294 (`--id`/`--url` \uBAA8\uB4DC\uC77C \uB54C) \uD30C\uC77C ID").argument("[arg2]", "\uC5C5\uBB34 \uBC88\uD638 \uB610\uB294 (`--id`/`--url` \uBAA8\uB4DC\uC77C \uB54C) \uD30C\uC77C ID").argument("[arg3]", "\uD30C\uC77C ID (positional 3\uAC1C \uBAA8\uB4DC)").option("--id <postId>", "Dooray post ID (project/post-number \uB300\uC2E0)").option("--url <url>", "Dooray \uC5C5\uBB34 URL (project/post-number \uB300\uC2E0)").option("--file-id <fileId>", "\uD30C\uC77C ID (positional \uB300\uCCB4)").action(async (arg1, arg2, arg3, opts) => {
|
|
2605
3420
|
const config = await getConfigOrThrow();
|
|
2606
3421
|
const client = new DoorayApiClient(config.apiKey, config.baseUrl);
|
|
2607
3422
|
let projectArg;
|
|
@@ -2654,7 +3469,7 @@ var fileDeleteCommand = new import_commander26.Command("delete").description("\u
|
|
|
2654
3469
|
});
|
|
2655
3470
|
|
|
2656
3471
|
// src/commands/wiki/list.ts
|
|
2657
|
-
var
|
|
3472
|
+
var import_commander33 = require("commander");
|
|
2658
3473
|
|
|
2659
3474
|
// src/formatters/wiki.ts
|
|
2660
3475
|
function formatWikiList(wikis, opts) {
|
|
@@ -2697,7 +3512,7 @@ function formatWikiPageDetail(page, opts) {
|
|
|
2697
3512
|
}
|
|
2698
3513
|
|
|
2699
3514
|
// src/commands/wiki/list.ts
|
|
2700
|
-
var wikiListCommand = new
|
|
3515
|
+
var wikiListCommand = new import_commander33.Command("list").description("\uC704\uD0A4 \uBAA9\uB85D \uC870\uD68C").option("--page <number>", "\uD398\uC774\uC9C0 \uBC88\uD638", "0").option("--size <number>", "\uD398\uC774\uC9C0 \uD06C\uAE30", "20").action(async (opts) => {
|
|
2701
3516
|
const globalOpts = wikiListCommand.optsWithGlobals();
|
|
2702
3517
|
const config = await getConfigOrThrow();
|
|
2703
3518
|
const client = new DoorayApiClient(config.apiKey, config.baseUrl);
|
|
@@ -2711,7 +3526,7 @@ var wikiListCommand = new import_commander27.Command("list").description("\uC704
|
|
|
2711
3526
|
});
|
|
2712
3527
|
|
|
2713
3528
|
// src/commands/wiki/pages.ts
|
|
2714
|
-
var
|
|
3529
|
+
var import_commander34 = require("commander");
|
|
2715
3530
|
|
|
2716
3531
|
// src/resolvers/wiki.ts
|
|
2717
3532
|
async function resolveWiki(client, projectCode) {
|
|
@@ -2755,7 +3570,7 @@ async function resolveWikiHomePageId(client, wikiId) {
|
|
|
2755
3570
|
}
|
|
2756
3571
|
|
|
2757
3572
|
// src/commands/wiki/pages.ts
|
|
2758
|
-
var wikiPagesCommand = new
|
|
3573
|
+
var wikiPagesCommand = new import_commander34.Command("pages").description("\uC704\uD0A4 \uD398\uC774\uC9C0 \uBAA9\uB85D \uC870\uD68C").argument("<project>", "\uD504\uB85C\uC81D\uD2B8 \uCF54\uB4DC \uB610\uB294 ID").option("--parent <page-id>", "\uBD80\uBAA8 \uD398\uC774\uC9C0 ID").action(async (project, opts) => {
|
|
2759
3574
|
const globalOpts = wikiPagesCommand.optsWithGlobals();
|
|
2760
3575
|
const config = await getConfigOrThrow();
|
|
2761
3576
|
const client = new DoorayApiClient(config.apiKey, config.baseUrl);
|
|
@@ -2767,8 +3582,8 @@ var wikiPagesCommand = new import_commander28.Command("pages").description("\uC7
|
|
|
2767
3582
|
});
|
|
2768
3583
|
|
|
2769
3584
|
// src/commands/wiki/page-get.ts
|
|
2770
|
-
var
|
|
2771
|
-
var wikiPageGetCommand = new
|
|
3585
|
+
var import_commander35 = require("commander");
|
|
3586
|
+
var wikiPageGetCommand = new import_commander35.Command("get").description("\uC704\uD0A4 \uD398\uC774\uC9C0 \uC0C1\uC138 \uC870\uD68C").argument("<project>", "\uD504\uB85C\uC81D\uD2B8 \uCF54\uB4DC \uB610\uB294 ID").argument("<page-id>", "\uD398\uC774\uC9C0 ID").action(async (project, pageId) => {
|
|
2772
3587
|
const globalOpts = wikiPageGetCommand.optsWithGlobals();
|
|
2773
3588
|
const config = await getConfigOrThrow();
|
|
2774
3589
|
const client = new DoorayApiClient(config.apiKey, config.baseUrl);
|
|
@@ -2780,8 +3595,8 @@ var wikiPageGetCommand = new import_commander29.Command("get").description("\uC7
|
|
|
2780
3595
|
});
|
|
2781
3596
|
|
|
2782
3597
|
// src/commands/wiki/page-create.ts
|
|
2783
|
-
var
|
|
2784
|
-
var wikiPageCreateCommand = new
|
|
3598
|
+
var import_commander36 = require("commander");
|
|
3599
|
+
var wikiPageCreateCommand = new import_commander36.Command("create").description("\uC704\uD0A4 \uD398\uC774\uC9C0 \uC0DD\uC131").argument("<project>", "\uD504\uB85C\uC81D\uD2B8 \uCF54\uB4DC \uB610\uB294 ID").requiredOption("--title <title>", "\uD398\uC774\uC9C0 \uC81C\uBAA9").option("--parent <page-id>", "\uBD80\uBAA8 \uD398\uC774\uC9C0 ID").option("--body <text>", "\uBCF8\uBB38 \uD14D\uC2A4\uD2B8 (- \uC785\uB825 \uC2DC stdin\uC5D0\uC11C \uC77D\uAE30)").option("--body-file <path>", "\uBCF8\uBB38 \uD30C\uC77C \uACBD\uB85C (- \uC785\uB825 \uC2DC stdin\uC5D0\uC11C \uC77D\uAE30)").action(async (project, opts) => {
|
|
2785
3600
|
const globalOpts = wikiPageCreateCommand.optsWithGlobals();
|
|
2786
3601
|
const config = await getConfigOrThrow();
|
|
2787
3602
|
const client = new DoorayApiClient(config.apiKey, config.baseUrl);
|
|
@@ -2806,8 +3621,8 @@ var wikiPageCreateCommand = new import_commander30.Command("create").description
|
|
|
2806
3621
|
});
|
|
2807
3622
|
|
|
2808
3623
|
// src/commands/wiki/page-edit.ts
|
|
2809
|
-
var
|
|
2810
|
-
var wikiPageEditCommand = new
|
|
3624
|
+
var import_commander37 = require("commander");
|
|
3625
|
+
var wikiPageEditCommand = new import_commander37.Command("edit").description("\uC704\uD0A4 \uD398\uC774\uC9C0 \uC218\uC815 (\uD50C\uB798\uADF8 \uC5C6\uC73C\uBA74 $EDITOR)").argument("<project>", "\uD504\uB85C\uC81D\uD2B8 \uCF54\uB4DC \uB610\uB294 ID").argument("<page-id>", "\uD398\uC774\uC9C0 ID").option("--title <title>", "\uD398\uC774\uC9C0 \uC81C\uBAA9 (\uC9C0\uC815 \uC2DC $EDITOR \uC0DD\uB7B5)").option("--body <text>", "\uBCF8\uBB38 \uD14D\uC2A4\uD2B8 (- \uC785\uB825 \uC2DC stdin\uC5D0\uC11C \uC77D\uAE30)").option("--body-file <path>", "\uBCF8\uBB38 \uD30C\uC77C \uACBD\uB85C (- \uC785\uB825 \uC2DC stdin\uC5D0\uC11C \uC77D\uAE30)").action(async (project, pageId, opts) => {
|
|
2811
3626
|
const config = await getConfigOrThrow();
|
|
2812
3627
|
const client = new DoorayApiClient(config.apiKey, config.baseUrl);
|
|
2813
3628
|
const hasTitle = opts.title != null;
|
|
@@ -2860,10 +3675,10 @@ var wikiPageEditCommand = new import_commander31.Command("edit").description("\u
|
|
|
2860
3675
|
});
|
|
2861
3676
|
|
|
2862
3677
|
// src/commands/member/index.ts
|
|
2863
|
-
var
|
|
3678
|
+
var import_commander41 = require("commander");
|
|
2864
3679
|
|
|
2865
3680
|
// src/commands/member/get.ts
|
|
2866
|
-
var
|
|
3681
|
+
var import_commander38 = require("commander");
|
|
2867
3682
|
|
|
2868
3683
|
// src/formatters/member.ts
|
|
2869
3684
|
function formatMemberDetail(member, opts) {
|
|
@@ -2893,9 +3708,23 @@ function formatMemberList(rows, opts) {
|
|
|
2893
3708
|
ids: rows.map((r) => r.id)
|
|
2894
3709
|
});
|
|
2895
3710
|
}
|
|
3711
|
+
function formatMemberSearchResults(members, opts) {
|
|
3712
|
+
output(opts, {
|
|
3713
|
+
headers: ["ID", "Name", "UserCode", "Nickname", "Email"],
|
|
3714
|
+
rows: members.map((m) => [
|
|
3715
|
+
m.id,
|
|
3716
|
+
m.name,
|
|
3717
|
+
m.userCode ?? "",
|
|
3718
|
+
m.nickname ?? "",
|
|
3719
|
+
m.externalEmailAddress ?? ""
|
|
3720
|
+
]),
|
|
3721
|
+
raw: members,
|
|
3722
|
+
ids: members.map((m) => m.id)
|
|
3723
|
+
});
|
|
3724
|
+
}
|
|
2896
3725
|
|
|
2897
3726
|
// src/commands/member/get.ts
|
|
2898
|
-
var memberGetCommand = new
|
|
3727
|
+
var memberGetCommand = new import_commander38.Command("get").description("\uBA64\uBC84 \uC0C1\uC138 \uC815\uBCF4 \uC870\uD68C (organizationMemberId)").argument("<member-id>", "\uC870\uD68C\uD560 organization member ID").action(async (memberId) => {
|
|
2899
3728
|
const globalOpts = memberGetCommand.optsWithGlobals();
|
|
2900
3729
|
const config = await getConfigOrThrow();
|
|
2901
3730
|
const client = new DoorayApiClient(config.apiKey, config.baseUrl);
|
|
@@ -2904,8 +3733,8 @@ var memberGetCommand = new import_commander32.Command("get").description("\uBA64
|
|
|
2904
3733
|
});
|
|
2905
3734
|
|
|
2906
3735
|
// src/commands/member/list.ts
|
|
2907
|
-
var
|
|
2908
|
-
var memberListCommand = new
|
|
3736
|
+
var import_commander39 = require("commander");
|
|
3737
|
+
var memberListCommand = new import_commander39.Command("list").description("\uD504\uB85C\uC81D\uD2B8 \uBA64\uBC84 \uBAA9\uB85D").argument("<project>", "\uD504\uB85C\uC81D\uD2B8 \uCF54\uB4DC \uB610\uB294 ID").action(async (project) => {
|
|
2909
3738
|
const globalOpts = memberListCommand.optsWithGlobals();
|
|
2910
3739
|
const config = await getConfigOrThrow();
|
|
2911
3740
|
const client = new DoorayApiClient(config.apiKey, config.baseUrl);
|
|
@@ -2919,13 +3748,48 @@ var memberListCommand = new import_commander33.Command("list").description("\uD5
|
|
|
2919
3748
|
);
|
|
2920
3749
|
});
|
|
2921
3750
|
|
|
3751
|
+
// src/commands/member/search.ts
|
|
3752
|
+
var import_commander40 = require("commander");
|
|
3753
|
+
var memberSearchCommand = new import_commander40.Command("search").description("organization \uC804\uCCB4\uC5D0\uC11C \uBA64\uBC84 \uAC80\uC0C9").argument("[keyword]", "\uC774\uB984 \uAC80\uC0C9\uC5B4 (--email/--user-code \uBBF8\uC9C0\uC815 \uC2DC name\uC73C\uB85C \uAC80\uC0C9)").option("--email <email>", "\uC678\uBD80 \uC774\uBA54\uC77C (\uCF64\uB9C8 \uAD6C\uBD84 \uAC00\uB2A5, exact match)").option("--user-code <code>", "\uC0AC\uBC88 like \uAC80\uC0C9").option("--user-code-exact <code>", "\uC0AC\uBC88 exact match").option("--page <n>", "\uD398\uC774\uC9C0 (\uAE30\uBCF8 0)", "0").option("--size <n>", "\uD398\uC774\uC9C0 \uD06C\uAE30 (\uAE30\uBCF8 20, max 100)", "20").action(async (keyword, opts) => {
|
|
3754
|
+
const globalOpts = memberSearchCommand.optsWithGlobals();
|
|
3755
|
+
const filterCount = [keyword, opts.email, opts.userCode, opts.userCodeExact].filter(Boolean).length;
|
|
3756
|
+
if (filterCount === 0) {
|
|
3757
|
+
throw new DoorayCliError(
|
|
3758
|
+
"\uAC80\uC0C9 \uC870\uAC74\uC774 \uD544\uC694\uD569\uB2C8\uB2E4. positional <keyword>(=name) \uB610\uB294 --email/--user-code/--user-code-exact \uC911 \uD558\uB098 \uC774\uC0C1.",
|
|
3759
|
+
EXIT_PARAM_ERROR
|
|
3760
|
+
);
|
|
3761
|
+
}
|
|
3762
|
+
if (keyword && (opts.email || opts.userCode || opts.userCodeExact)) {
|
|
3763
|
+
throw new DoorayCliError(
|
|
3764
|
+
"positional <keyword>(name)\uC640 --email/--user-code/--user-code-exact \uC635\uC158\uC740 \uB3D9\uC2DC \uC0AC\uC6A9 \uBD88\uAC00.",
|
|
3765
|
+
EXIT_PARAM_ERROR
|
|
3766
|
+
);
|
|
3767
|
+
}
|
|
3768
|
+
const config = await getConfigOrThrow();
|
|
3769
|
+
const client = new DoorayApiClient(config.apiKey, config.baseUrl);
|
|
3770
|
+
const size = Math.min(Math.max(1, Number(opts.size) || 20), 100);
|
|
3771
|
+
const page = Math.max(0, Number(opts.page) || 0);
|
|
3772
|
+
startSpinner("\uBA64\uBC84 \uAC80\uC0C9 \uC911...");
|
|
3773
|
+
const res = await client.searchMembers({
|
|
3774
|
+
...keyword && { name: keyword },
|
|
3775
|
+
...opts.email && { externalEmailAddresses: opts.email },
|
|
3776
|
+
...opts.userCode && { userCode: opts.userCode },
|
|
3777
|
+
...opts.userCodeExact && { userCodeExact: opts.userCodeExact },
|
|
3778
|
+
page,
|
|
3779
|
+
size
|
|
3780
|
+
});
|
|
3781
|
+
stopSpinner(true, `${res.totalCount}\uAC74 (\uC774 \uD398\uC774\uC9C0 ${res.result.length})`);
|
|
3782
|
+
formatMemberSearchResults(res.result, globalOpts);
|
|
3783
|
+
});
|
|
3784
|
+
|
|
2922
3785
|
// src/commands/member/index.ts
|
|
2923
|
-
var memberCommand = new
|
|
3786
|
+
var memberCommand = new import_commander41.Command("member").description("Dooray \uBA64\uBC84 \uC870\uD68C");
|
|
2924
3787
|
memberCommand.addCommand(memberGetCommand);
|
|
2925
3788
|
memberCommand.addCommand(memberListCommand);
|
|
3789
|
+
memberCommand.addCommand(memberSearchCommand);
|
|
2926
3790
|
|
|
2927
3791
|
// src/commands/mail/list.ts
|
|
2928
|
-
var
|
|
3792
|
+
var import_commander42 = require("commander");
|
|
2929
3793
|
|
|
2930
3794
|
// src/api/imapClient.ts
|
|
2931
3795
|
var import_imapflow = require("imapflow");
|
|
@@ -2966,7 +3830,7 @@ async function listMails(config, opts) {
|
|
|
2966
3830
|
if (opts.search) query.subject = opts.search;
|
|
2967
3831
|
if (Object.keys(query).length === 0) query.all = true;
|
|
2968
3832
|
const uids = await client.search(query, { uid: true });
|
|
2969
|
-
if (uids.length === 0) return [];
|
|
3833
|
+
if (!Array.isArray(uids) || uids.length === 0) return [];
|
|
2970
3834
|
const sorted = uids.sort((a, b) => b - a).slice(0, limit);
|
|
2971
3835
|
const uidSet = sorted.join(",");
|
|
2972
3836
|
const messages = [];
|
|
@@ -2975,15 +3839,17 @@ async function listMails(config, opts) {
|
|
|
2975
3839
|
flags: true,
|
|
2976
3840
|
envelope: true
|
|
2977
3841
|
}, { uid: true })) {
|
|
3842
|
+
const { envelope, flags } = msg;
|
|
3843
|
+
if (!envelope || !flags) continue;
|
|
2978
3844
|
messages.push({
|
|
2979
3845
|
uid: msg.uid,
|
|
2980
|
-
subject:
|
|
2981
|
-
from:
|
|
2982
|
-
to: (
|
|
3846
|
+
subject: envelope.subject ?? "(\uC81C\uBAA9 \uC5C6\uC74C)",
|
|
3847
|
+
from: envelope.from?.[0] ? `${envelope.from[0].name || ""} <${envelope.from[0].address || ""}>` : "(unknown)",
|
|
3848
|
+
to: (envelope.to ?? []).map(
|
|
2983
3849
|
(t) => `${t.name || ""} <${t.address || ""}>`
|
|
2984
3850
|
),
|
|
2985
|
-
date:
|
|
2986
|
-
isRead:
|
|
3851
|
+
date: envelope.date ?? null,
|
|
3852
|
+
isRead: flags.has("\\Seen")
|
|
2987
3853
|
});
|
|
2988
3854
|
}
|
|
2989
3855
|
messages.sort((a, b) => b.uid - a.uid);
|
|
@@ -3010,17 +3876,24 @@ async function getMail(config, uid) {
|
|
|
3010
3876
|
if (!msg) {
|
|
3011
3877
|
throw new DoorayCliError(`\uBA54\uC77C\uC744 \uCC3E\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4: UID ${uid}`, 1);
|
|
3012
3878
|
}
|
|
3013
|
-
const
|
|
3014
|
-
|
|
3879
|
+
const { envelope, flags, source } = msg;
|
|
3880
|
+
if (!envelope || !flags || !source) {
|
|
3881
|
+
throw new DoorayCliError(
|
|
3882
|
+
`\uBA54\uC77C \uBA54\uD0C0\uB370\uC774\uD130\uAC00 \uBD88\uC644\uC804\uD569\uB2C8\uB2E4 (UID ${uid}): envelope/flags/source \uB204\uB77D`,
|
|
3883
|
+
1
|
|
3884
|
+
);
|
|
3885
|
+
}
|
|
3886
|
+
const parsed = await (0, import_mailparser.simpleParser)(source);
|
|
3887
|
+
const body = parsed.text || (parsed.html || "") || "(\uBCF8\uBB38 \uC5C6\uC74C)";
|
|
3015
3888
|
return {
|
|
3016
3889
|
uid: msg.uid,
|
|
3017
|
-
subject:
|
|
3018
|
-
from:
|
|
3019
|
-
to: (
|
|
3890
|
+
subject: envelope.subject ?? "(\uC81C\uBAA9 \uC5C6\uC74C)",
|
|
3891
|
+
from: envelope.from?.[0] ? `${envelope.from[0].name || ""} <${envelope.from[0].address || ""}>` : "(unknown)",
|
|
3892
|
+
to: (envelope.to ?? []).map(
|
|
3020
3893
|
(t) => `${t.name || ""} <${t.address || ""}>`
|
|
3021
3894
|
),
|
|
3022
|
-
date:
|
|
3023
|
-
isRead:
|
|
3895
|
+
date: envelope.date ?? null,
|
|
3896
|
+
isRead: flags.has("\\Seen"),
|
|
3024
3897
|
body
|
|
3025
3898
|
};
|
|
3026
3899
|
} finally {
|
|
@@ -3033,7 +3906,7 @@ async function getMail(config, uid) {
|
|
|
3033
3906
|
|
|
3034
3907
|
// src/commands/mail/list.ts
|
|
3035
3908
|
var import_chalk5 = __toESM(require("chalk"));
|
|
3036
|
-
var mailListCommand = new
|
|
3909
|
+
var mailListCommand = new import_commander42.Command("list").description("\uBA54\uC77C \uBAA9\uB85D \uC870\uD68C").option("--unread", "\uC548\uC77D\uC740 \uBA54\uC77C\uB9CC").option("--search <keyword>", "\uC81C\uBAA9 \uAC80\uC0C9").option("--size <number>", "\uC870\uD68C \uAC1C\uC218", "20").action(async (opts) => {
|
|
3037
3910
|
const globalOpts = mailListCommand.optsWithGlobals();
|
|
3038
3911
|
const config = await getConfigOrThrow();
|
|
3039
3912
|
startSpinner("\uBA54\uC77C \uC870\uD68C \uC911...");
|
|
@@ -3065,9 +3938,9 @@ var mailListCommand = new import_commander35.Command("list").description("\uBA54
|
|
|
3065
3938
|
});
|
|
3066
3939
|
|
|
3067
3940
|
// src/commands/mail/get.ts
|
|
3068
|
-
var
|
|
3941
|
+
var import_commander43 = require("commander");
|
|
3069
3942
|
var import_chalk6 = __toESM(require("chalk"));
|
|
3070
|
-
var mailGetCommand = new
|
|
3943
|
+
var mailGetCommand = new import_commander43.Command("get").description("\uBA54\uC77C \uC0C1\uC138 \uC870\uD68C").argument("<uid>", "\uBA54\uC77C UID").action(async (uid) => {
|
|
3071
3944
|
const globalOpts = mailGetCommand.optsWithGlobals();
|
|
3072
3945
|
const config = await getConfigOrThrow();
|
|
3073
3946
|
startSpinner("\uBA54\uC77C \uC870\uD68C \uC911...");
|
|
@@ -3098,8 +3971,8 @@ ${mail.body}
|
|
|
3098
3971
|
});
|
|
3099
3972
|
|
|
3100
3973
|
// src/commands/mail/send.ts
|
|
3101
|
-
var
|
|
3102
|
-
var
|
|
3974
|
+
var import_commander44 = require("commander");
|
|
3975
|
+
var import_promises11 = require("fs/promises");
|
|
3103
3976
|
|
|
3104
3977
|
// src/api/smtpClient.ts
|
|
3105
3978
|
var import_nodemailer = __toESM(require("nodemailer"));
|
|
@@ -3148,12 +4021,12 @@ async function sendMail(config, opts) {
|
|
|
3148
4021
|
}
|
|
3149
4022
|
|
|
3150
4023
|
// src/commands/mail/send.ts
|
|
3151
|
-
var mailSendCommand = new
|
|
4024
|
+
var mailSendCommand = new import_commander44.Command("send").description("\uBA54\uC77C \uBC1C\uC1A1").requiredOption("--to <addresses...>", "\uBC1B\uB294\uC0AC\uB78C \uC774\uBA54\uC77C (\uBCF5\uC218 \uAC00\uB2A5)").requiredOption("--subject <title>", "\uC81C\uBAA9").option("--body <text>", "\uBCF8\uBB38").option("--body-file <path>", "\uBCF8\uBB38 \uD30C\uC77C \uACBD\uB85C").option("--cc <addresses...>", "\uCC38\uC870").option("--bcc <addresses...>", "\uC228\uC740\uCC38\uC870").option("--html", "\uBCF8\uBB38\uC744 HTML\uB85C \uC804\uC1A1").action(async (opts) => {
|
|
3152
4025
|
const globalOpts = mailSendCommand.optsWithGlobals();
|
|
3153
4026
|
const config = await getConfigOrThrow();
|
|
3154
4027
|
let body = opts.body ?? "";
|
|
3155
4028
|
if (opts.bodyFile) {
|
|
3156
|
-
body = await (0,
|
|
4029
|
+
body = await (0, import_promises11.readFile)(opts.bodyFile, "utf-8");
|
|
3157
4030
|
}
|
|
3158
4031
|
if (!body) {
|
|
3159
4032
|
process.stderr.write("\uC624\uB958: --body \uB610\uB294 --body-file\uC744 \uC9C0\uC815\uD558\uC138\uC694\n");
|
|
@@ -3183,8 +4056,8 @@ var mailSendCommand = new import_commander37.Command("send").description("\uBA54
|
|
|
3183
4056
|
});
|
|
3184
4057
|
|
|
3185
4058
|
// src/commands/mail/reply.ts
|
|
3186
|
-
var
|
|
3187
|
-
var
|
|
4059
|
+
var import_commander45 = require("commander");
|
|
4060
|
+
var import_promises12 = require("fs/promises");
|
|
3188
4061
|
var import_imapflow2 = require("imapflow");
|
|
3189
4062
|
async function getMessageId(config, uid) {
|
|
3190
4063
|
const imap = getImapConfigOrThrow(config);
|
|
@@ -3203,7 +4076,8 @@ async function getMessageId(config, uid) {
|
|
|
3203
4076
|
uid: true,
|
|
3204
4077
|
envelope: true
|
|
3205
4078
|
}, { uid: true });
|
|
3206
|
-
|
|
4079
|
+
if (!msg) return null;
|
|
4080
|
+
return msg.envelope?.messageId ?? null;
|
|
3207
4081
|
} finally {
|
|
3208
4082
|
lock.release();
|
|
3209
4083
|
}
|
|
@@ -3211,12 +4085,12 @@ async function getMessageId(config, uid) {
|
|
|
3211
4085
|
await client.logout();
|
|
3212
4086
|
}
|
|
3213
4087
|
}
|
|
3214
|
-
var mailReplyCommand = new
|
|
4088
|
+
var mailReplyCommand = new import_commander45.Command("reply").description("\uBA54\uC77C \uB2F5\uC7A5").argument("<uid>", "\uC6D0\uBCF8 \uBA54\uC77C UID").option("--body <text>", "\uB2F5\uC7A5 \uBCF8\uBB38").option("--body-file <path>", "\uB2F5\uC7A5 \uBCF8\uBB38 \uD30C\uC77C \uACBD\uB85C").option("--cc <addresses...>", "\uCC38\uC870").option("--html", "\uBCF8\uBB38\uC744 HTML\uB85C \uC804\uC1A1").action(async (uid, opts) => {
|
|
3215
4089
|
const globalOpts = mailReplyCommand.optsWithGlobals();
|
|
3216
4090
|
const config = await getConfigOrThrow();
|
|
3217
4091
|
let body = opts.body ?? "";
|
|
3218
4092
|
if (opts.bodyFile) {
|
|
3219
|
-
body = await (0,
|
|
4093
|
+
body = await (0, import_promises12.readFile)(opts.bodyFile, "utf-8");
|
|
3220
4094
|
}
|
|
3221
4095
|
if (!body) {
|
|
3222
4096
|
process.stderr.write("\uC624\uB958: --body \uB610\uB294 --body-file\uC744 \uC9C0\uC815\uD558\uC138\uC694\n");
|
|
@@ -3252,29 +4126,29 @@ var mailReplyCommand = new import_commander38.Command("reply").description("\uBA
|
|
|
3252
4126
|
});
|
|
3253
4127
|
|
|
3254
4128
|
// src/commands/feedback.ts
|
|
3255
|
-
var
|
|
4129
|
+
var import_commander46 = require("commander");
|
|
3256
4130
|
var import_node_child_process2 = require("child_process");
|
|
3257
4131
|
var import_node_util = require("util");
|
|
3258
|
-
var
|
|
3259
|
-
var
|
|
3260
|
-
var
|
|
4132
|
+
var import_promises15 = require("fs/promises");
|
|
4133
|
+
var import_node_os4 = require("os");
|
|
4134
|
+
var import_node_path11 = require("path");
|
|
3261
4135
|
var import_node_crypto = require("crypto");
|
|
3262
4136
|
var import_prompts = require("@inquirer/prompts");
|
|
3263
4137
|
|
|
3264
4138
|
// src/utils/feedback-meta.ts
|
|
3265
|
-
var
|
|
3266
|
-
var
|
|
4139
|
+
var import_promises13 = require("fs/promises");
|
|
4140
|
+
var import_node_path9 = require("path");
|
|
3267
4141
|
async function readCliVersion() {
|
|
3268
4142
|
const entry = process.argv[1];
|
|
3269
|
-
const here = entry ? (0,
|
|
4143
|
+
const here = entry ? (0, import_node_path9.dirname)(entry) : process.cwd();
|
|
3270
4144
|
const candidates = [
|
|
3271
|
-
(0,
|
|
3272
|
-
(0,
|
|
3273
|
-
(0,
|
|
4145
|
+
(0, import_node_path9.join)(here, "package.json"),
|
|
4146
|
+
(0, import_node_path9.join)(here, "..", "package.json"),
|
|
4147
|
+
(0, import_node_path9.join)(here, "..", "..", "package.json")
|
|
3274
4148
|
];
|
|
3275
4149
|
for (const p of candidates) {
|
|
3276
4150
|
try {
|
|
3277
|
-
const raw = await (0,
|
|
4151
|
+
const raw = await (0, import_promises13.readFile)(p, "utf-8");
|
|
3278
4152
|
const pkg = JSON.parse(raw);
|
|
3279
4153
|
if (pkg.name === "@bifos/dooray-cli" && typeof pkg.version === "string") {
|
|
3280
4154
|
return pkg.version;
|
|
@@ -3292,6 +4166,19 @@ function collectMeta(version) {
|
|
|
3292
4166
|
arch: process.arch
|
|
3293
4167
|
};
|
|
3294
4168
|
}
|
|
4169
|
+
function buildLastRunBlock(last) {
|
|
4170
|
+
return [
|
|
4171
|
+
"## \uC9C1\uC804 \uC2E4\uD589 (\uC790\uB3D9 \uCCA8\uBD80)",
|
|
4172
|
+
"",
|
|
4173
|
+
"```",
|
|
4174
|
+
`$ ${last.argv.join(" ")}`,
|
|
4175
|
+
last.errorMessage.replace(/```/g, "'''"),
|
|
4176
|
+
"```",
|
|
4177
|
+
"",
|
|
4178
|
+
`- exit code: ${last.exitCode}`,
|
|
4179
|
+
`- \uC2DC\uAC01: ${last.timestamp}`
|
|
4180
|
+
].join("\n");
|
|
4181
|
+
}
|
|
3295
4182
|
function buildIssueBody(userBody, meta) {
|
|
3296
4183
|
return [
|
|
3297
4184
|
"## \uD658\uACBD",
|
|
@@ -3306,6 +4193,32 @@ function buildIssueBody(userBody, meta) {
|
|
|
3306
4193
|
].join("\n");
|
|
3307
4194
|
}
|
|
3308
4195
|
|
|
4196
|
+
// src/cache/last-run.ts
|
|
4197
|
+
var import_promises14 = require("fs/promises");
|
|
4198
|
+
var import_node_path10 = require("path");
|
|
4199
|
+
var import_node_os3 = require("os");
|
|
4200
|
+
var LAST_RUN_PATH = (0, import_node_path10.join)((0, import_node_os3.homedir)(), ".dooray", "last-run.json");
|
|
4201
|
+
function isLastRun(obj) {
|
|
4202
|
+
if (typeof obj !== "object" || obj === null) return false;
|
|
4203
|
+
const o = obj;
|
|
4204
|
+
return Array.isArray(o.argv) && o.argv.every((a) => typeof a === "string") && typeof o.exitCode === "number" && typeof o.errorMessage === "string" && typeof o.timestamp === "string";
|
|
4205
|
+
}
|
|
4206
|
+
async function readLastRun() {
|
|
4207
|
+
try {
|
|
4208
|
+
const raw = await (0, import_promises14.readFile)(LAST_RUN_PATH, "utf-8");
|
|
4209
|
+
const parsed = JSON.parse(raw);
|
|
4210
|
+
return isLastRun(parsed) ? parsed : null;
|
|
4211
|
+
} catch {
|
|
4212
|
+
return null;
|
|
4213
|
+
}
|
|
4214
|
+
}
|
|
4215
|
+
async function writeLastRun(data) {
|
|
4216
|
+
await (0, import_promises14.mkdir)((0, import_node_path10.join)((0, import_node_os3.homedir)(), ".dooray"), { recursive: true });
|
|
4217
|
+
const tmp2 = LAST_RUN_PATH + ".tmp";
|
|
4218
|
+
await (0, import_promises14.writeFile)(tmp2, JSON.stringify(data, null, 2) + "\n", { mode: 384 });
|
|
4219
|
+
await (0, import_promises14.rename)(tmp2, LAST_RUN_PATH);
|
|
4220
|
+
}
|
|
4221
|
+
|
|
3309
4222
|
// src/commands/feedback.ts
|
|
3310
4223
|
var execFileAsync = (0, import_node_util.promisify)(import_node_child_process2.execFile);
|
|
3311
4224
|
var TARGET_REPO = "jon890/dooray-cli";
|
|
@@ -3321,18 +4234,36 @@ async function ensureGhInstalled() {
|
|
|
3321
4234
|
}
|
|
3322
4235
|
async function readBody(opts) {
|
|
3323
4236
|
if (opts.body) return opts.body;
|
|
3324
|
-
if (opts.bodyFile) return await (0,
|
|
4237
|
+
if (opts.bodyFile) return await (0, import_promises15.readFile)(opts.bodyFile, "utf-8");
|
|
3325
4238
|
return void 0;
|
|
3326
4239
|
}
|
|
3327
|
-
var feedbackCommand = new
|
|
4240
|
+
var feedbackCommand = new import_commander46.Command("feedback").description("dooray-cli\uC5D0 \uB300\uD55C GitHub issue \uB4F1\uB85D (gh CLI \uC704\uC784)").option("--title <text>", "\uC774\uC288 \uC81C\uBAA9 (\uC5C6\uC73C\uBA74 \uC778\uD130\uB799\uD2F0\uBE0C)").option("--body <text>", "\uC774\uC288 \uBCF8\uBB38").option("--body-file <path>", "\uBCF8\uBB38 \uD30C\uC77C \uACBD\uB85C").option(
|
|
3328
4241
|
"--label <name>",
|
|
3329
4242
|
"\uB77C\uBCA8 (\uBC18\uBCF5 \uAC00\uB2A5)",
|
|
3330
4243
|
(value, prev) => [...prev, value],
|
|
3331
4244
|
[]
|
|
3332
|
-
).option("--dry-run", "gh \uD638\uCD9C \uC5C6\uC774 \uBCF8\uBB38\uB9CC \uBBF8\uB9AC\uBCF4\uAE30").action(async (opts) => {
|
|
4245
|
+
).option("--last", "\uC9C1\uC804 \uC2E4\uD589\uD55C dooray \uBA85\uB839\uC758 argv + \uC5D0\uB7EC\uB97C \uBCF8\uBB38 \uC0C1\uB2E8\uC5D0 \uC790\uB3D9 \uCCA8\uBD80").option("--dry-run", "gh \uD638\uCD9C \uC5C6\uC774 \uBCF8\uBB38\uB9CC \uBBF8\uB9AC\uBCF4\uAE30").action(async (opts) => {
|
|
3333
4246
|
let title = opts.title;
|
|
3334
4247
|
let userBody = await readBody(opts);
|
|
3335
4248
|
let labels = [...opts.label];
|
|
4249
|
+
if (opts.last) {
|
|
4250
|
+
const last = await readLastRun();
|
|
4251
|
+
if (!last) {
|
|
4252
|
+
throw new DoorayCliError(
|
|
4253
|
+
"\uAE30\uB85D\uB41C \uC9C1\uC804 \uC2E4\uD589\uC774 \uC5C6\uC2B5\uB2C8\uB2E4. config.json\uC5D0 trackLastRun: true \uC124\uC815 \uD6C4 dooray \uBA85\uB839 \uC2E4\uD589 \uC2DC \uC790\uB3D9 \uAE30\uB85D\uB429\uB2C8\uB2E4.\n \uC124\uC815: dooray config set track-last-run true",
|
|
4254
|
+
EXIT_PARAM_ERROR
|
|
4255
|
+
);
|
|
4256
|
+
}
|
|
4257
|
+
const lastBlock = buildLastRunBlock(last);
|
|
4258
|
+
if (userBody == null) {
|
|
4259
|
+
userBody = await (0, import_prompts.editor)({
|
|
4260
|
+
message: "\uBCF8\uBB38 \uC791\uC131 ($EDITOR\uAC00 \uC5F4\uB9BC)",
|
|
4261
|
+
default: lastBlock + "\n\n"
|
|
4262
|
+
});
|
|
4263
|
+
} else {
|
|
4264
|
+
userBody = lastBlock + "\n\n" + userBody;
|
|
4265
|
+
}
|
|
4266
|
+
}
|
|
3336
4267
|
if (!title) {
|
|
3337
4268
|
title = await (0, import_prompts.input)({ message: "\uC774\uC288 \uC81C\uBAA9" });
|
|
3338
4269
|
}
|
|
@@ -3397,8 +4328,8 @@ var feedbackCommand = new import_commander39.Command("feedback").description("do
|
|
|
3397
4328
|
}
|
|
3398
4329
|
}
|
|
3399
4330
|
await ensureGhInstalled();
|
|
3400
|
-
const bodyFile = (0,
|
|
3401
|
-
await (0,
|
|
4331
|
+
const bodyFile = (0, import_node_path11.join)((0, import_node_os4.tmpdir)(), `dooray-feedback-${(0, import_node_crypto.randomUUID)()}.md`);
|
|
4332
|
+
await (0, import_promises15.writeFile)(bodyFile, issueBody);
|
|
3402
4333
|
try {
|
|
3403
4334
|
const args = [
|
|
3404
4335
|
"issue",
|
|
@@ -3425,27 +4356,68 @@ gh \uC778\uC99D \uC548 \uB418\uC5B4 \uC788\uC73C\uBA74: gh auth login`,
|
|
|
3425
4356
|
EXIT_PARAM_ERROR
|
|
3426
4357
|
);
|
|
3427
4358
|
} finally {
|
|
3428
|
-
await (0,
|
|
4359
|
+
await (0, import_promises15.unlink)(bodyFile).catch(() => {
|
|
3429
4360
|
});
|
|
3430
4361
|
}
|
|
3431
4362
|
});
|
|
3432
4363
|
|
|
4364
|
+
// src/utils/argv-sanitize.ts
|
|
4365
|
+
var KEY_VALUE_PATTERNS = [
|
|
4366
|
+
/^(--api-key|--token|--password)=(.+)$/
|
|
4367
|
+
];
|
|
4368
|
+
var SEPARATED_KEYS = /* @__PURE__ */ new Set(["--api-key", "--token", "--password"]);
|
|
4369
|
+
function sanitizeArgv(argv) {
|
|
4370
|
+
const out = [];
|
|
4371
|
+
for (let i = 0; i < argv.length; i++) {
|
|
4372
|
+
const a = argv[i];
|
|
4373
|
+
let kvMatch = null;
|
|
4374
|
+
for (const re of KEY_VALUE_PATTERNS) {
|
|
4375
|
+
const m = re.exec(a);
|
|
4376
|
+
if (m) {
|
|
4377
|
+
kvMatch = m;
|
|
4378
|
+
break;
|
|
4379
|
+
}
|
|
4380
|
+
}
|
|
4381
|
+
if (kvMatch) {
|
|
4382
|
+
out.push(`${kvMatch[1]}=***`);
|
|
4383
|
+
continue;
|
|
4384
|
+
}
|
|
4385
|
+
if (SEPARATED_KEYS.has(a)) {
|
|
4386
|
+
out.push(a);
|
|
4387
|
+
if (i + 1 < argv.length) {
|
|
4388
|
+
out.push("***");
|
|
4389
|
+
i++;
|
|
4390
|
+
}
|
|
4391
|
+
continue;
|
|
4392
|
+
}
|
|
4393
|
+
if (/^Authorization\s*:/i.test(a) || /^Bearer\s+\S+/.test(a)) {
|
|
4394
|
+
out.push(a.replace(/(Authorization\s*:\s*).+/i, "$1***").replace(/^(Bearer\s+).+/i, "$1***"));
|
|
4395
|
+
continue;
|
|
4396
|
+
}
|
|
4397
|
+
out.push(a);
|
|
4398
|
+
}
|
|
4399
|
+
return out;
|
|
4400
|
+
}
|
|
4401
|
+
|
|
3433
4402
|
// src/index.ts
|
|
3434
|
-
var program = new
|
|
3435
|
-
program.name("dooray").description("Dooray REST API CLI").version("0.
|
|
4403
|
+
var program = new import_commander47.Command();
|
|
4404
|
+
program.name("dooray").description("Dooray REST API CLI").version("0.7.0").option("--json", "JSON \uD615\uC2DD\uC73C\uB85C \uCD9C\uB825").option("--quiet", "ID\uB9CC \uCD9C\uB825").option("--no-color", "\uC0C9\uC0C1 \uBE44\uD65C\uC131\uD654");
|
|
3436
4405
|
program.hook("preAction", () => {
|
|
3437
4406
|
const opts = program.opts();
|
|
3438
4407
|
if (opts.color === false || process.env.NO_COLOR) {
|
|
3439
4408
|
import_chalk7.default.level = 0;
|
|
3440
4409
|
}
|
|
4410
|
+
if (opts.json || opts.quiet) {
|
|
4411
|
+
setQuiet(true);
|
|
4412
|
+
}
|
|
3441
4413
|
});
|
|
3442
|
-
var projectCommand = new
|
|
4414
|
+
var projectCommand = new import_commander47.Command("project").description("\uD504\uB85C\uC81D\uD2B8 \uAD00\uB828 \uBA85\uB839");
|
|
3443
4415
|
projectCommand.addCommand(projectListCommand);
|
|
3444
4416
|
projectCommand.addCommand(projectMembersCommand);
|
|
3445
4417
|
projectCommand.addCommand(projectWorkflowsCommand);
|
|
3446
4418
|
projectCommand.addCommand(projectGroupsCommand);
|
|
3447
4419
|
projectCommand.addCommand(projectTagsCommand);
|
|
3448
|
-
var postCommand = new
|
|
4420
|
+
var postCommand = new import_commander47.Command("post").description("\uC5C5\uBB34 \uAD00\uB828 \uBA85\uB839");
|
|
3449
4421
|
postCommand.addCommand(postListCommand);
|
|
3450
4422
|
postCommand.addCommand(postSearchCommand);
|
|
3451
4423
|
postCommand.addCommand(postGetCommand);
|
|
@@ -3453,29 +4425,31 @@ postCommand.addCommand(postEditCommand);
|
|
|
3453
4425
|
postCommand.addCommand(postCreateCommand);
|
|
3454
4426
|
postCommand.addCommand(postDoneCommand);
|
|
3455
4427
|
postCommand.addCommand(postWorkflowCommand);
|
|
3456
|
-
var commentCommand = new
|
|
4428
|
+
var commentCommand = new import_commander47.Command("comment").description("\uB313\uAE00 \uAD00\uB828 \uBA85\uB839");
|
|
3457
4429
|
commentCommand.addCommand(commentListCommand);
|
|
3458
4430
|
commentCommand.addCommand(commentLatestCommand);
|
|
4431
|
+
commentCommand.addCommand(commentGetCommand);
|
|
3459
4432
|
commentCommand.addCommand(commentAddCommand);
|
|
3460
4433
|
commentCommand.addCommand(commentEditCommand);
|
|
3461
4434
|
commentCommand.addCommand(commentDeleteCommand);
|
|
4435
|
+
commentCommand.addCommand(commentFileCommand);
|
|
3462
4436
|
postCommand.addCommand(commentCommand);
|
|
3463
|
-
var fileCommand = new
|
|
4437
|
+
var fileCommand = new import_commander47.Command("file").description("\uCCA8\uBD80\uD30C\uC77C \uAD00\uB828 \uBA85\uB839");
|
|
3464
4438
|
fileCommand.addCommand(fileListCommand);
|
|
3465
4439
|
fileCommand.addCommand(fileDownloadCommand);
|
|
3466
4440
|
fileCommand.addCommand(fileDownloadAllCommand);
|
|
3467
4441
|
fileCommand.addCommand(fileUploadCommand);
|
|
3468
4442
|
fileCommand.addCommand(fileDeleteCommand);
|
|
3469
4443
|
postCommand.addCommand(fileCommand);
|
|
3470
|
-
var wikiCommand = new
|
|
4444
|
+
var wikiCommand = new import_commander47.Command("wiki").description("\uC704\uD0A4 \uAD00\uB828 \uBA85\uB839");
|
|
3471
4445
|
wikiCommand.addCommand(wikiListCommand);
|
|
3472
4446
|
wikiCommand.addCommand(wikiPagesCommand);
|
|
3473
|
-
var wikiPageCommand = new
|
|
4447
|
+
var wikiPageCommand = new import_commander47.Command("page").description("\uC704\uD0A4 \uD398\uC774\uC9C0 \uAD00\uB828 \uBA85\uB839");
|
|
3474
4448
|
wikiPageCommand.addCommand(wikiPageGetCommand);
|
|
3475
4449
|
wikiPageCommand.addCommand(wikiPageCreateCommand);
|
|
3476
4450
|
wikiPageCommand.addCommand(wikiPageEditCommand);
|
|
3477
4451
|
wikiCommand.addCommand(wikiPageCommand);
|
|
3478
|
-
var mailCommand = new
|
|
4452
|
+
var mailCommand = new import_commander47.Command("mail").description("\uBA54\uC77C \uAD00\uB828 \uBA85\uB839");
|
|
3479
4453
|
mailCommand.addCommand(mailListCommand);
|
|
3480
4454
|
mailCommand.addCommand(mailGetCommand);
|
|
3481
4455
|
mailCommand.addCommand(mailSendCommand);
|
|
@@ -3490,11 +4464,24 @@ program.addCommand(postCommand);
|
|
|
3490
4464
|
program.addCommand(wikiCommand);
|
|
3491
4465
|
program.addCommand(mailCommand);
|
|
3492
4466
|
program.addCommand(feedbackCommand);
|
|
3493
|
-
program.parseAsync().catch((err) => {
|
|
3494
|
-
|
|
3495
|
-
|
|
3496
|
-
|
|
4467
|
+
program.parseAsync().catch(async (err) => {
|
|
4468
|
+
const errorMessage = err instanceof Error ? err.message : String(err);
|
|
4469
|
+
const exitCode = err instanceof DoorayCliError ? err.exitCode : 1;
|
|
4470
|
+
try {
|
|
4471
|
+
const config = await getConfig();
|
|
4472
|
+
const sanitized = sanitizeArgv(process.argv.slice(2));
|
|
4473
|
+
const firstNonFlag = sanitized.find((a) => !a.startsWith("-"));
|
|
4474
|
+
const isFeedbackCommand = firstNonFlag === "feedback";
|
|
4475
|
+
if (config?.trackLastRun && !isFeedbackCommand) {
|
|
4476
|
+
await writeLastRun({
|
|
4477
|
+
argv: ["dooray", ...sanitized],
|
|
4478
|
+
exitCode,
|
|
4479
|
+
errorMessage,
|
|
4480
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
4481
|
+
});
|
|
4482
|
+
}
|
|
4483
|
+
} catch {
|
|
3497
4484
|
}
|
|
3498
|
-
process.stderr.write(import_chalk7.default.red(`\uC624\uB958: ${
|
|
3499
|
-
process.exit(
|
|
4485
|
+
process.stderr.write(import_chalk7.default.red(`\uC624\uB958: ${errorMessage}`) + "\n");
|
|
4486
|
+
process.exit(exitCode);
|
|
3500
4487
|
});
|