@bifos/dooray-cli 0.3.1 → 0.5.2

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/dist/index.js CHANGED
@@ -24,8 +24,8 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
24
24
  ));
25
25
 
26
26
  // src/index.ts
27
- var import_commander32 = require("commander");
28
- var import_chalk6 = __toESM(require("chalk"));
27
+ var import_commander33 = require("commander");
28
+ var import_chalk7 = __toESM(require("chalk"));
29
29
 
30
30
  // src/commands/config.ts
31
31
  var import_commander = require("commander");
@@ -53,8 +53,15 @@ var EXIT_PARAM_ERROR = 3;
53
53
  var EXIT_CONFIG_ERROR = 4;
54
54
 
55
55
  // src/config/types.ts
56
+ var API_ENDPOINTS = {
57
+ "\uBBFC\uAC04 \uD074\uB77C\uC6B0\uB4DC": "https://api.dooray.com",
58
+ "\uACF5\uACF5 \uD074\uB77C\uC6B0\uB4DC": "https://api.gov-dooray.com",
59
+ "\uACF5\uACF5 \uC5C5\uBB34\uB9DD \uD074\uB77C\uC6B0\uB4DC": "https://api.gov-dooray.co.kr",
60
+ "\uAE08\uC735 \uD074\uB77C\uC6B0\uB4DC": "https://api.dooray.co.kr"
61
+ };
56
62
  var DEFAULTS = {
57
63
  baseUrl: "https://api.dooray.com",
64
+ tenantName: "nhnent",
58
65
  imapHost: "imap.dooray.com",
59
66
  imapPort: 993,
60
67
  smtpHost: "smtp.dooray.com",
@@ -79,7 +86,7 @@ async function getConfigOrThrow() {
79
86
  const config = await getConfig();
80
87
  if (!config || !config.apiKey || !config.baseUrl) {
81
88
  throw new DoorayCliError(
82
- "\uC124\uC815\uC774 \uC644\uB8CC\uB418\uC9C0 \uC54A\uC558\uC2B5\uB2C8\uB2E4. \uBA3C\uC800 \uC124\uC815\uC744 \uC9C4\uD589\uD558\uC138\uC694:\n dooray config set api-key <YOUR_API_KEY>\n dooray config set base-url <YOUR_BASE_URL>",
89
+ "\uC124\uC815\uC774 \uC644\uB8CC\uB418\uC9C0 \uC54A\uC558\uC2B5\uB2C8\uB2E4. \uBA3C\uC800 \uCD08\uAE30 \uC124\uC815\uC744 \uC9C4\uD589\uD558\uC138\uC694:\n dooray setup",
83
90
  EXIT_CONFIG_ERROR
84
91
  );
85
92
  }
@@ -114,18 +121,25 @@ async function setConfigValue(key, value) {
114
121
  case "smtp-host":
115
122
  config.smtpHost = value;
116
123
  break;
124
+ case "tenant-name":
125
+ config.tenantName = value;
126
+ break;
117
127
  case "smtp-port":
118
128
  config.smtpPort = parseInt(value, 10);
119
129
  break;
120
130
  default:
121
131
  throw new DoorayCliError(
122
132
  `\uC54C \uC218 \uC5C6\uB294 \uC124\uC815 \uD0A4: ${key}
123
- \uC0AC\uC6A9 \uAC00\uB2A5\uD55C \uD0A4: api-key, base-url, imap-host, imap-port, imap-username, imap-password, smtp-host, smtp-port`,
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`,
124
134
  EXIT_CONFIG_ERROR
125
135
  );
126
136
  }
127
137
  await (0, import_promises.writeFile)(CONFIG_PATH, JSON.stringify(config, null, 2) + "\n");
128
138
  }
139
+ async function saveConfig(config) {
140
+ await ensureDir();
141
+ await (0, import_promises.writeFile)(CONFIG_PATH, JSON.stringify(config, null, 2) + "\n");
142
+ }
129
143
 
130
144
  // src/commands/config.ts
131
145
  function maskApiKey(key) {
@@ -181,23 +195,25 @@ var import_node_os2 = require("os");
181
195
  var CACHE_DIR = (0, import_node_path2.join)((0, import_node_os2.homedir)(), ".dooray", "cache");
182
196
  var ME_PATH = (0, import_node_path2.join)(CACHE_DIR, "me.json");
183
197
  var PROJECTS_PATH = (0, import_node_path2.join)(CACHE_DIR, "projects.json");
198
+ var PROJECTS_PRIVATE_PATH = (0, import_node_path2.join)(CACHE_DIR, "projects-private.json");
184
199
  var MEMBERS_DIR = (0, import_node_path2.join)(CACHE_DIR, "members");
185
200
  var WORKFLOWS_DIR = (0, import_node_path2.join)(CACHE_DIR, "workflows");
201
+ var WIKIS_PATH = (0, import_node_path2.join)(CACHE_DIR, "wikis.json");
186
202
  async function ensureDir2(dir) {
187
203
  await (0, import_promises2.mkdir)(dir, { recursive: true });
188
204
  }
189
- async function readJson(path) {
205
+ async function readJson(path3) {
190
206
  try {
191
- const raw = await (0, import_promises2.readFile)(path, "utf-8");
207
+ const raw = await (0, import_promises2.readFile)(path3, "utf-8");
192
208
  return JSON.parse(raw);
193
209
  } catch {
194
210
  return null;
195
211
  }
196
212
  }
197
- async function writeJson(path, data) {
198
- const dir = path.substring(0, path.lastIndexOf("/"));
213
+ async function writeJson(path3, data) {
214
+ const dir = path3.substring(0, path3.lastIndexOf("/"));
199
215
  await ensureDir2(dir);
200
- await (0, import_promises2.writeFile)(path, JSON.stringify(data, null, 2) + "\n");
216
+ await (0, import_promises2.writeFile)(path3, JSON.stringify(data, null, 2) + "\n");
201
217
  }
202
218
  function isExpired(updatedAt, ttlMs) {
203
219
  if (!updatedAt) return true;
@@ -218,6 +234,12 @@ async function getProjects() {
218
234
  async function setProjects(items) {
219
235
  await writeJson(PROJECTS_PATH, { updatedAt: now(), data: items });
220
236
  }
237
+ async function getPrivateProjects() {
238
+ return readJson(PROJECTS_PRIVATE_PATH);
239
+ }
240
+ async function setPrivateProjects(items) {
241
+ await writeJson(PROJECTS_PRIVATE_PATH, { updatedAt: now(), data: items });
242
+ }
221
243
  function membersPath(projectId) {
222
244
  return (0, import_node_path2.join)(MEMBERS_DIR, `${projectId}.json`);
223
245
  }
@@ -236,6 +258,12 @@ async function getWorkflows(projectId) {
236
258
  async function setWorkflows(projectId, items) {
237
259
  await writeJson(workflowsPath(projectId), { updatedAt: now(), data: items });
238
260
  }
261
+ async function getWikis() {
262
+ return readJson(WIKIS_PATH);
263
+ }
264
+ async function setWikis(items) {
265
+ await writeJson(WIKIS_PATH, { updatedAt: now(), data: items });
266
+ }
239
267
  async function clearCache() {
240
268
  try {
241
269
  await (0, import_promises2.rm)(CACHE_DIR, { recursive: true, force: true });
@@ -275,11 +303,24 @@ cacheCommand.command("refresh").description("\uCE90\uC2DC \uAC31\uC2E0 (API \uD0
275
303
  // src/commands/doctor.ts
276
304
  var import_commander3 = require("commander");
277
305
  var import_chalk3 = __toESM(require("chalk"));
306
+ var import_path = __toESM(require("path"));
307
+ var import_promises4 = __toESM(require("fs/promises"));
278
308
 
279
309
  // src/api/client.ts
280
310
  var import_ky = __toESM(require("ky"));
281
311
  var import_promises3 = require("fs/promises");
282
312
  var import_node_path3 = require("path");
313
+
314
+ // src/utils/dooray-message.ts
315
+ function normalizeDoorayMessage(raw) {
316
+ try {
317
+ return decodeURIComponent(raw.replace(/\+/g, " "));
318
+ } catch {
319
+ return raw;
320
+ }
321
+ }
322
+
323
+ // src/api/client.ts
283
324
  function joinIds(ids) {
284
325
  return ids && ids.length > 0 ? ids.join(",") : void 0;
285
326
  }
@@ -290,7 +331,7 @@ async function toDoorayCliError(error) {
290
331
  try {
291
332
  const body = await error.response.json();
292
333
  throw new DoorayCliError(
293
- `API \uD638\uCD9C \uC2E4\uD328: ${body.header.resultMessage}`,
334
+ `API \uD638\uCD9C \uC2E4\uD328: ${normalizeDoorayMessage(body.header.resultMessage)}`,
294
335
  exitCode
295
336
  );
296
337
  } catch (e) {
@@ -524,6 +565,20 @@ var DoorayApiClient = class {
524
565
  return toDoorayCliError(e);
525
566
  }
526
567
  }
568
+ async updateWikiPageTitle(wikiId, pageId, body) {
569
+ try {
570
+ return await this.api.put(`wiki/v1/wikis/${wikiId}/pages/${pageId}/title`, { json: body }).json();
571
+ } catch (e) {
572
+ return toDoorayCliError(e);
573
+ }
574
+ }
575
+ async updateWikiPageContent(wikiId, pageId, body) {
576
+ try {
577
+ return await this.api.put(`wiki/v1/wikis/${wikiId}/pages/${pageId}/content`, { json: body }).json();
578
+ } catch (e) {
579
+ return toDoorayCliError(e);
580
+ }
581
+ }
527
582
  // ─── Post Files ─────────────────────────────────────
528
583
  async getPostFiles(projectId, postId) {
529
584
  try {
@@ -622,6 +677,7 @@ var PROJECTS_TTL_MS = 36e5;
622
677
  var MEMBERS_TTL_MS = 36e5;
623
678
  var WORKFLOWS_TTL_MS = 864e5;
624
679
  var ME_TTL_MS = 864e5;
680
+ var WIKIS_TTL_MS = 864e5;
625
681
 
626
682
  // src/resolvers/me.ts
627
683
  async function ensureMe(client) {
@@ -661,27 +717,198 @@ var doctorCommand = new import_commander3.Command("doctor").description("\uC124\
661
717
  console.log(` \uD504\uB85C\uC81D\uD2B8: ${stats.projectCount}\uAC1C`);
662
718
  console.log(` \uBA64\uBC84: ${stats.memberProjectCount}\uAC1C \uD504\uB85C\uC81D\uD2B8`);
663
719
  console.log(` \uC6CC\uD06C\uD50C\uB85C\uC6B0: ${stats.workflowProjectCount}\uAC1C \uD504\uB85C\uC81D\uD2B8`);
720
+ const claudeDir = import_path.default.join(
721
+ process.env.HOME ?? process.env.USERPROFILE ?? "",
722
+ ".claude"
723
+ );
724
+ const claudeDirExists = await import_promises4.default.access(claudeDir).then(() => true).catch(() => false);
725
+ if (claudeDirExists) {
726
+ console.log(import_chalk3.default.bold("\n\u{1F527} Claude Code \uC2A4\uD0AC\n"));
727
+ const skillDst = import_path.default.join(claudeDir, "skills", "dooray-cli");
728
+ try {
729
+ const stat2 = await import_promises4.default.lstat(skillDst);
730
+ if (stat2.isSymbolicLink()) {
731
+ const target = await import_promises4.default.readlink(skillDst);
732
+ const targetExists = await import_promises4.default.access(target).then(() => true).catch(() => false);
733
+ if (targetExists) {
734
+ console.log(` dooray-cli: ${import_chalk3.default.green("\u2705 \uC124\uCE58\uB428 (\uC2EC\uBCFC\uB9AD \uB9C1\uD06C)")}`);
735
+ } else {
736
+ console.log(
737
+ ` dooray-cli: ${import_chalk3.default.yellow("\u26A0\uFE0F \uB9C1\uD06C \uAE68\uC9D0 \u2014 dooray setup\uC73C\uB85C \uC7AC\uC124\uCE58")}`
738
+ );
739
+ }
740
+ } else {
741
+ console.log(` dooray-cli: ${import_chalk3.default.green("\u2705 \uC124\uCE58\uB428 (\uBCF5\uC0AC\uBCF8)")}`);
742
+ }
743
+ } catch {
744
+ console.log(
745
+ ` dooray-cli: ${import_chalk3.default.red("\u274C \uBBF8\uC124\uCE58 \u2014 dooray setup\uC73C\uB85C \uC124\uCE58")}`
746
+ );
747
+ }
748
+ }
664
749
  console.log();
665
750
  if (apiKeyOk && baseUrlOk) {
666
751
  console.log(import_chalk3.default.green("\u2713 \uAE30\uBCF8 \uC124\uC815\uC774 \uC644\uB8CC\uB418\uC5C8\uC2B5\uB2C8\uB2E4."));
667
752
  } else {
668
753
  console.log(import_chalk3.default.yellow("\u26A0 \uC124\uC815\uC774 \uD544\uC694\uD569\uB2C8\uB2E4:"));
669
- if (!apiKeyOk) console.log(import_chalk3.default.yellow(" dooray config set api-key <YOUR_API_KEY>"));
670
- if (!baseUrlOk) console.log(import_chalk3.default.yellow(" dooray config set base-url <YOUR_BASE_URL>"));
754
+ console.log(import_chalk3.default.yellow(" dooray setup"));
671
755
  }
672
756
  console.log();
673
757
  });
674
758
 
675
- // src/commands/project/list.ts
759
+ // src/commands/setup.ts
676
760
  var import_commander4 = require("commander");
761
+ var import_chalk4 = __toESM(require("chalk"));
762
+ var import_path2 = __toESM(require("path"));
763
+ var import_promises5 = __toESM(require("fs/promises"));
764
+ var setupCommand = new import_commander4.Command("setup").description("\uB300\uD654\uD615 \uCD08\uAE30 \uC124\uC815 \uB9C8\uBC95\uC0AC").action(async () => {
765
+ const { input, select, password, confirm } = await import("@inquirer/prompts");
766
+ const existing = await getConfig();
767
+ try {
768
+ const tenantName = await input({
769
+ message: "\uD14C\uB10C\uD2B8\uBA85\uC744 \uC785\uB825\uD558\uC138\uC694",
770
+ default: existing?.tenantName ?? DEFAULTS.tenantName,
771
+ theme: { prefix: "\u{1F3E2}" }
772
+ });
773
+ console.log(
774
+ import_chalk4.default.gray(
775
+ ` \uC811\uC18D URL: https://${tenantName}.dooray.com`
776
+ )
777
+ );
778
+ const endpointChoices = Object.entries(API_ENDPOINTS).map(
779
+ ([name, url]) => ({
780
+ name: `${name} (${url})`,
781
+ value: url
782
+ })
783
+ );
784
+ const defaultEndpoint = existing?.baseUrl ?? API_ENDPOINTS["\uBBFC\uAC04 \uD074\uB77C\uC6B0\uB4DC"];
785
+ const baseUrl = await select({
786
+ message: "API Endpoint\uB97C \uC120\uD0DD\uD558\uC138\uC694",
787
+ choices: endpointChoices,
788
+ default: defaultEndpoint,
789
+ theme: { prefix: "\u{1F310}" }
790
+ });
791
+ let apiKey = "";
792
+ let meName = "";
793
+ let verified = false;
794
+ while (!verified) {
795
+ apiKey = await password({
796
+ message: `API Key\uB97C \uC785\uB825\uD558\uC138\uC694 (\uBC1C\uAE09: https://${tenantName}.dooray.com/setting/api/token)`,
797
+ mask: "*",
798
+ theme: { prefix: "\u{1F511}" }
799
+ });
800
+ if (!apiKey) {
801
+ console.log(import_chalk4.default.red(" \u2717 API Key\uB294 \uD544\uC218\uC785\uB2C8\uB2E4."));
802
+ continue;
803
+ }
804
+ try {
805
+ const client = new DoorayApiClient(apiKey, baseUrl);
806
+ await client.getProjects({ page: 0, size: 1 });
807
+ const me = await ensureMe(client);
808
+ meName = me.name;
809
+ console.log(import_chalk4.default.green(` \u2713 API \uC5F0\uACB0 \uC131\uACF5 (${meName})`));
810
+ verified = true;
811
+ } catch {
812
+ console.log(
813
+ import_chalk4.default.red(" \u2717 \uC5F0\uACB0 \uC2E4\uD328 \u2014 API Key\uB97C \uD655\uC778\uD574\uC8FC\uC138\uC694")
814
+ );
815
+ }
816
+ }
817
+ const useMail = await confirm({
818
+ message: "\uBA54\uC77C \uAE30\uB2A5\uC744 \uC0AC\uC6A9\uD558\uC2DC\uACA0\uC2B5\uB2C8\uAE4C?",
819
+ default: !!existing?.imapUsername,
820
+ theme: { prefix: "\u{1F4E7}" }
821
+ });
822
+ let imapUsername;
823
+ let imapPassword;
824
+ if (useMail) {
825
+ imapUsername = await input({
826
+ message: `IMAP \uC0AC\uC6A9\uC790 \uC774\uBA54\uC77C (\uD655\uC778: https://${tenantName}.dooray.com/setting/mail/general/read)`,
827
+ default: existing?.imapUsername,
828
+ theme: { prefix: "\u{1F4E8}" }
829
+ });
830
+ imapPassword = await password({
831
+ message: "IMAP \uBE44\uBC00\uBC88\uD638",
832
+ mask: "*",
833
+ theme: { prefix: "\u{1F512}" }
834
+ });
835
+ }
836
+ const claudeDir = import_path2.default.join(
837
+ process.env.HOME ?? process.env.USERPROFILE ?? "",
838
+ ".claude"
839
+ );
840
+ const claudeDirExists = await import_promises5.default.access(claudeDir).then(() => true).catch(() => false);
841
+ if (claudeDirExists) {
842
+ const isNpx = /_npx[/\\]/.test(__dirname) || /\.npm[/\\]_npx/.test(__dirname) || /npx-/.test(__dirname);
843
+ if (isNpx) {
844
+ console.log(
845
+ import_chalk4.default.yellow(
846
+ " \u26A0 npx \uD658\uACBD\uC5D0\uC11C\uB294 \uC2A4\uD0AC \uC124\uCE58\uAC00 \uBD88\uAC00\uD569\uB2C8\uB2E4. npm i -g @bifos/dooray-cli \uD6C4 \uB2E4\uC2DC \uC2DC\uB3C4\uD558\uC138\uC694."
847
+ )
848
+ );
849
+ } else {
850
+ const installSkill = await confirm({
851
+ message: "Claude Code \uC2A4\uD0AC\uC744 \uC124\uCE58\uD558\uC2DC\uACA0\uC2B5\uB2C8\uAE4C?",
852
+ default: true,
853
+ theme: { prefix: "\u{1F527}" }
854
+ });
855
+ if (installSkill) {
856
+ try {
857
+ const skillSrc = import_path2.default.resolve(__dirname, "../skills/dooray-cli");
858
+ const skillsDir = import_path2.default.join(claudeDir, "skills");
859
+ const skillDst = import_path2.default.join(skillsDir, "dooray-cli");
860
+ await import_promises5.default.mkdir(skillsDir, { recursive: true });
861
+ await import_promises5.default.lstat(skillDst).then(() => import_promises5.default.rm(skillDst, { recursive: true, force: true })).catch(() => {
862
+ });
863
+ await import_promises5.default.symlink(skillSrc, skillDst);
864
+ console.log(import_chalk4.default.green(" \u2713 Claude Code \uC2A4\uD0AC \uC124\uCE58 \uC644\uB8CC"));
865
+ } catch (err) {
866
+ console.log(
867
+ import_chalk4.default.yellow(
868
+ ` \u26A0 \uC2A4\uD0AC \uC124\uCE58 \uC2E4\uD328: ${err instanceof Error ? err.message : String(err)}`
869
+ )
870
+ );
871
+ }
872
+ }
873
+ }
874
+ }
875
+ const config = {
876
+ version: 1,
877
+ apiKey,
878
+ baseUrl,
879
+ tenantName,
880
+ imapHost: useMail ? DEFAULTS.imapHost : existing?.imapHost,
881
+ imapPort: useMail ? DEFAULTS.imapPort : existing?.imapPort,
882
+ imapUsername: imapUsername ?? existing?.imapUsername,
883
+ imapPassword: imapPassword ?? existing?.imapPassword,
884
+ smtpHost: useMail ? DEFAULTS.smtpHost : existing?.smtpHost,
885
+ smtpPort: useMail ? DEFAULTS.smtpPort : existing?.smtpPort
886
+ };
887
+ await saveConfig(config);
888
+ console.log(
889
+ import_chalk4.default.green(
890
+ "\n\u2713 \uC124\uC815 \uC644\uB8CC. dooray doctor\uB85C \uC0C1\uD0DC\uB97C \uD655\uC778\uD560 \uC218 \uC788\uC2B5\uB2C8\uB2E4."
891
+ )
892
+ );
893
+ } catch (err) {
894
+ if (err != null && typeof err === "object" && "name" in err && err.name === "ExitPromptError") {
895
+ console.log(import_chalk4.default.yellow("\n\uC124\uC815\uC774 \uCDE8\uC18C\uB418\uC5C8\uC2B5\uB2C8\uB2E4."));
896
+ return;
897
+ }
898
+ throw err;
899
+ }
900
+ });
901
+
902
+ // src/commands/project/list.ts
903
+ var import_commander5 = require("commander");
677
904
 
678
905
  // src/resolvers/project.ts
679
- async function fetchAllProjects(client) {
906
+ async function fetchAllProjects(client, options) {
680
907
  const all = [];
681
908
  let page = 0;
682
909
  const size = 100;
683
910
  while (true) {
684
- const res = await client.getProjects({ page, size });
911
+ const res = await client.getProjects({ page, size, type: options?.type });
685
912
  for (const p of res.result) {
686
913
  all.push({
687
914
  id: p.id,
@@ -703,12 +930,27 @@ async function ensureProjects(client) {
703
930
  await setProjects(items);
704
931
  return items;
705
932
  }
933
+ async function ensurePrivateProjects(client) {
934
+ const entry = await getPrivateProjects();
935
+ if (entry && !isExpired(entry.updatedAt, PROJECTS_TTL_MS)) {
936
+ return entry.data;
937
+ }
938
+ const items = await fetchAllProjects(client, { type: "private" });
939
+ await setPrivateProjects(items);
940
+ return items;
941
+ }
706
942
  async function resolveProject(client, input) {
707
943
  const projects = await ensureProjects(client);
708
944
  const match = projects.find((p) => p.code === input || p.id === input);
709
945
  if (match) return match.id;
946
+ const privateCached = await getPrivateProjects();
947
+ if (privateCached && !isExpired(privateCached.updatedAt, PROJECTS_TTL_MS)) {
948
+ const privateMatch = privateCached.data.find((p) => p.code === input || p.id === input);
949
+ if (privateMatch) return privateMatch.id;
950
+ }
710
951
  throw new DoorayCliError(
711
- `\uD504\uB85C\uC81D\uD2B8\uB97C \uCC3E\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4: ${input}`,
952
+ `\uD504\uB85C\uC81D\uD2B8\uB97C \uCC3E\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4: ${input}
953
+ \uAC1C\uC778 \uD504\uB85C\uC81D\uD2B8\uB77C\uBA74: dooray project list --type private \uB85C \uCE90\uC2DC\uB97C \uAC31\uC2E0\uD558\uC138\uC694`,
712
954
  EXIT_PARAM_ERROR
713
955
  );
714
956
  }
@@ -756,13 +998,16 @@ function stopSpinner(success, text) {
756
998
  }
757
999
 
758
1000
  // src/commands/project/list.ts
759
- var projectListCommand = new import_commander4.Command("list").description("\uD504\uB85C\uC81D\uD2B8 \uBAA9\uB85D \uC870\uD68C").option("-s, --search <keyword>", "code \uD544\uD130\uB9C1").action(async (opts) => {
1001
+ var projectListCommand = new import_commander5.Command("list").description("\uD504\uB85C\uC81D\uD2B8 \uBAA9\uB85D \uC870\uD68C").option("-s, --search <keyword>", "code \uD544\uD130\uB9C1").addOption(
1002
+ new import_commander5.Option("-t, --type <type>", "\uD504\uB85C\uC81D\uD2B8 \uD0C0\uC785 \uD544\uD130").choices(["public", "private"]).default("public")
1003
+ ).action(async (opts) => {
760
1004
  const globalOpts = projectListCommand.optsWithGlobals();
761
1005
  const config = await getConfigOrThrow();
762
1006
  const client = new DoorayApiClient(config.apiKey, config.baseUrl);
763
- startSpinner("\uD504\uB85C\uC81D\uD2B8 \uBAA9\uB85D \uC870\uD68C \uC911...");
764
- const projects = await ensureProjects(client);
765
- stopSpinner(true, "\uD504\uB85C\uC81D\uD2B8 \uBAA9\uB85D \uC870\uD68C \uC644\uB8CC");
1007
+ const isPrivate = opts.type === "private";
1008
+ startSpinner(isPrivate ? "\uAC1C\uC778 \uD504\uB85C\uC81D\uD2B8 \uBAA9\uB85D \uC870\uD68C \uC911..." : "\uD504\uB85C\uC81D\uD2B8 \uBAA9\uB85D \uC870\uD68C \uC911...");
1009
+ const projects = isPrivate ? await ensurePrivateProjects(client) : await ensureProjects(client);
1010
+ stopSpinner(true, isPrivate ? "\uAC1C\uC778 \uD504\uB85C\uC81D\uD2B8 \uBAA9\uB85D \uC870\uD68C \uC644\uB8CC" : "\uD504\uB85C\uC81D\uD2B8 \uBAA9\uB85D \uC870\uD68C \uC644\uB8CC");
766
1011
  let filtered = projects;
767
1012
  if (opts.search) {
768
1013
  const keyword = opts.search.toLowerCase();
@@ -777,7 +1022,7 @@ var projectListCommand = new import_commander4.Command("list").description("\uD5
777
1022
  });
778
1023
 
779
1024
  // src/commands/project/members.ts
780
- var import_commander5 = require("commander");
1025
+ var import_commander6 = require("commander");
781
1026
 
782
1027
  // src/resolvers/member.ts
783
1028
  async function fetchAllMembers(client, projectId) {
@@ -839,7 +1084,7 @@ ${candidates}`,
839
1084
  }
840
1085
 
841
1086
  // src/commands/project/members.ts
842
- var projectMembersCommand = new import_commander5.Command("members").description("\uD504\uB85C\uC81D\uD2B8 \uBA64\uBC84 \uBAA9\uB85D \uC870\uD68C").argument("<project>", "\uD504\uB85C\uC81D\uD2B8 \uCF54\uB4DC \uB610\uB294 ID").action(async (project) => {
1087
+ var projectMembersCommand = new import_commander6.Command("members").description("\uD504\uB85C\uC81D\uD2B8 \uBA64\uBC84 \uBAA9\uB85D \uC870\uD68C").argument("<project>", "\uD504\uB85C\uC81D\uD2B8 \uCF54\uB4DC \uB610\uB294 ID").action(async (project) => {
843
1088
  const globalOpts = projectMembersCommand.optsWithGlobals();
844
1089
  const config = await getConfigOrThrow();
845
1090
  const client = new DoorayApiClient(config.apiKey, config.baseUrl);
@@ -859,7 +1104,7 @@ var projectMembersCommand = new import_commander5.Command("members").description
859
1104
  });
860
1105
 
861
1106
  // src/commands/project/workflows.ts
862
- var import_commander6 = require("commander");
1107
+ var import_commander7 = require("commander");
863
1108
 
864
1109
  // src/resolvers/workflow.ts
865
1110
  async function ensureWorkflows(client, projectId) {
@@ -888,7 +1133,7 @@ async function resolveWorkflow(client, projectId, input) {
888
1133
  }
889
1134
 
890
1135
  // src/commands/project/workflows.ts
891
- var projectWorkflowsCommand = new import_commander6.Command("workflows").description("\uD504\uB85C\uC81D\uD2B8 \uC6CC\uD06C\uD50C\uB85C\uC6B0 \uBAA9\uB85D \uC870\uD68C").argument("<project>", "\uD504\uB85C\uC81D\uD2B8 \uCF54\uB4DC \uB610\uB294 ID").action(async (project) => {
1136
+ var projectWorkflowsCommand = new import_commander7.Command("workflows").description("\uD504\uB85C\uC81D\uD2B8 \uC6CC\uD06C\uD50C\uB85C\uC6B0 \uBAA9\uB85D \uC870\uD68C").argument("<project>", "\uD504\uB85C\uC81D\uD2B8 \uCF54\uB4DC \uB610\uB294 ID").action(async (project) => {
892
1137
  const globalOpts = projectWorkflowsCommand.optsWithGlobals();
893
1138
  const config = await getConfigOrThrow();
894
1139
  const client = new DoorayApiClient(config.apiKey, config.baseUrl);
@@ -910,7 +1155,7 @@ var projectWorkflowsCommand = new import_commander6.Command("workflows").descrip
910
1155
  });
911
1156
 
912
1157
  // src/commands/post/list.ts
913
- var import_commander7 = require("commander");
1158
+ var import_commander8 = require("commander");
914
1159
 
915
1160
  // src/formatters/post.ts
916
1161
  function formatPostList(posts, opts) {
@@ -961,7 +1206,7 @@ function formatCommentList(comments, opts) {
961
1206
  }
962
1207
 
963
1208
  // src/commands/post/list.ts
964
- var postListCommand = new import_commander7.Command("list").description("\uC5C5\uBB34 \uBAA9\uB85D \uC870\uD68C").argument("<project>", "\uD504\uB85C\uC81D\uD2B8 \uCF54\uB4DC \uB610\uB294 ID").option("--subject <keyword>", "\uC81C\uBAA9 \uD0A4\uC6CC\uB4DC \uD544\uD130\uB9C1").option("--all", "\uC804\uCCB4 \uD398\uC774\uC9C0\uB124\uC774\uC158 (\uBAA8\uB4E0 \uACB0\uACFC \uC870\uD68C)").option("--page <number>", "\uD398\uC774\uC9C0 \uBC88\uD638", "0").option("--size <number>", "\uD398\uC774\uC9C0 \uD06C\uAE30", "20").action(async (project, opts) => {
1209
+ var postListCommand = new import_commander8.Command("list").description("\uC5C5\uBB34 \uBAA9\uB85D \uC870\uD68C").argument("<project>", "\uD504\uB85C\uC81D\uD2B8 \uCF54\uB4DC \uB610\uB294 ID").option("--subject <keyword>", "\uC81C\uBAA9 \uD0A4\uC6CC\uB4DC \uD544\uD130\uB9C1").option("--all", "\uC804\uCCB4 \uD398\uC774\uC9C0\uB124\uC774\uC158 (\uBAA8\uB4E0 \uACB0\uACFC \uC870\uD68C)").option("--page <number>", "\uD398\uC774\uC9C0 \uBC88\uD638", "0").option("--size <number>", "\uD398\uC774\uC9C0 \uD06C\uAE30", "20").action(async (project, opts) => {
965
1210
  const globalOpts = postListCommand.optsWithGlobals();
966
1211
  const config = await getConfigOrThrow();
967
1212
  const client = new DoorayApiClient(config.apiKey, config.baseUrl);
@@ -995,8 +1240,8 @@ var postListCommand = new import_commander7.Command("list").description("\uC5C5\
995
1240
  });
996
1241
 
997
1242
  // src/commands/post/search.ts
998
- var import_commander8 = require("commander");
999
- var postSearchCommand = new import_commander8.Command("search").description("\uC5C5\uBB34 \uAC80\uC0C9 (\uC81C\uBAA9 \uD0A4\uC6CC\uB4DC)").argument("<project>", "\uD504\uB85C\uC81D\uD2B8 \uCF54\uB4DC \uB610\uB294 ID").argument("<keyword>", "\uAC80\uC0C9 \uD0A4\uC6CC\uB4DC").action(async (project, keyword) => {
1243
+ var import_commander9 = require("commander");
1244
+ var postSearchCommand = new import_commander9.Command("search").description("\uC5C5\uBB34 \uAC80\uC0C9 (\uC81C\uBAA9 \uD0A4\uC6CC\uB4DC)").argument("<project>", "\uD504\uB85C\uC81D\uD2B8 \uCF54\uB4DC \uB610\uB294 ID").argument("<keyword>", "\uAC80\uC0C9 \uD0A4\uC6CC\uB4DC").action(async (project, keyword) => {
1000
1245
  const globalOpts = postSearchCommand.optsWithGlobals();
1001
1246
  const config = await getConfigOrThrow();
1002
1247
  const client = new DoorayApiClient(config.apiKey, config.baseUrl);
@@ -1008,7 +1253,7 @@ var postSearchCommand = new import_commander8.Command("search").description("\uC
1008
1253
  });
1009
1254
 
1010
1255
  // src/commands/post/get.ts
1011
- var import_commander9 = require("commander");
1256
+ var import_commander10 = require("commander");
1012
1257
 
1013
1258
  // src/resolvers/post.ts
1014
1259
  async function resolvePost(client, projectId, postNumber) {
@@ -1025,7 +1270,7 @@ async function resolvePost(client, projectId, postNumber) {
1025
1270
  }
1026
1271
 
1027
1272
  // src/commands/post/get.ts
1028
- var postGetCommand = new import_commander9.Command("get").description("\uC5C5\uBB34 \uC0C1\uC138 \uC870\uD68C").argument("<project>", "\uD504\uB85C\uC81D\uD2B8 \uCF54\uB4DC \uB610\uB294 ID").argument("<post-number>", "\uC5C5\uBB34 \uBC88\uD638").action(async (project, postNumberStr) => {
1273
+ var postGetCommand = new import_commander10.Command("get").description("\uC5C5\uBB34 \uC0C1\uC138 \uC870\uD68C").argument("<project>", "\uD504\uB85C\uC81D\uD2B8 \uCF54\uB4DC \uB610\uB294 ID").argument("<post-number>", "\uC5C5\uBB34 \uBC88\uD638").action(async (project, postNumberStr) => {
1029
1274
  const globalOpts = postGetCommand.optsWithGlobals();
1030
1275
  const config = await getConfigOrThrow();
1031
1276
  const client = new DoorayApiClient(config.apiKey, config.baseUrl);
@@ -1038,12 +1283,11 @@ var postGetCommand = new import_commander9.Command("get").description("\uC5C5\uB
1038
1283
  });
1039
1284
 
1040
1285
  // src/commands/post/edit.ts
1041
- var import_commander10 = require("commander");
1042
- var import_promises5 = __toESM(require("fs/promises"));
1286
+ var import_commander11 = require("commander");
1043
1287
 
1044
1288
  // src/editor/index.ts
1045
1289
  var import_node_child_process = require("child_process");
1046
- var import_promises4 = __toESM(require("fs/promises"));
1290
+ var import_promises6 = __toESM(require("fs/promises"));
1047
1291
  var import_tmp = __toESM(require("tmp"));
1048
1292
  var import_js_yaml = __toESM(require("js-yaml"));
1049
1293
  function openInEditor(content) {
@@ -1057,7 +1301,7 @@ function openInEditor(content) {
1057
1301
  const tmpFile = import_tmp.default.fileSync({ prefix: "dooray-", postfix: ".md" });
1058
1302
  return new Promise(async (resolve, reject) => {
1059
1303
  try {
1060
- await import_promises4.default.writeFile(tmpFile.name, content, "utf-8");
1304
+ await import_promises6.default.writeFile(tmpFile.name, content, "utf-8");
1061
1305
  const child = (0, import_node_child_process.spawn)(editor, [tmpFile.name], {
1062
1306
  stdio: "inherit"
1063
1307
  });
@@ -1073,7 +1317,7 @@ function openInEditor(content) {
1073
1317
  EXIT_PARAM_ERROR
1074
1318
  );
1075
1319
  }
1076
- const result = await import_promises4.default.readFile(tmpFile.name, "utf-8");
1320
+ const result = await import_promises6.default.readFile(tmpFile.name, "utf-8");
1077
1321
  resolve(result);
1078
1322
  } catch (e) {
1079
1323
  reject(e);
@@ -1166,14 +1410,25 @@ function parseWikiFrontmatter(content) {
1166
1410
  };
1167
1411
  }
1168
1412
 
1169
- // src/commands/post/edit.ts
1170
- async function resolveUsers(client, projectId, emails) {
1171
- const users = [];
1172
- for (const email of emails) {
1173
- const memberId = await resolveMember(client, projectId, email);
1174
- users.push({ type: "member", member: { organizationMemberId: memberId } });
1413
+ // src/utils/body-input.ts
1414
+ var import_promises7 = require("fs/promises");
1415
+ async function readBodyInput(opts) {
1416
+ if (opts.body != null && opts.bodyFile != null) {
1417
+ throw new DoorayCliError(
1418
+ "--body\uC640 --body-file\uC740 \uD568\uAED8 \uC0AC\uC6A9\uD560 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4.",
1419
+ EXIT_PARAM_ERROR
1420
+ );
1175
1421
  }
1176
- return users;
1422
+ if (opts.bodyFile) {
1423
+ if (opts.bodyFile === "-") return readStdin();
1424
+ return (0, import_promises7.readFile)(opts.bodyFile, "utf-8");
1425
+ }
1426
+ if (opts.body === "-") return readStdin();
1427
+ return opts.body ?? "";
1428
+ }
1429
+ async function readBodyInputOrNull(opts) {
1430
+ if (opts.body == null && opts.bodyFile == null) return null;
1431
+ return readBodyInput(opts);
1177
1432
  }
1178
1433
  async function readStdin() {
1179
1434
  if (process.stdin.isTTY) {
@@ -1188,18 +1443,17 @@ async function readStdin() {
1188
1443
  }
1189
1444
  return Buffer.concat(chunks).toString("utf-8");
1190
1445
  }
1191
- async function resolveBody(opts) {
1192
- if (opts.body) {
1193
- if (opts.body === "-") return readStdin();
1194
- return opts.body;
1195
- }
1196
- if (opts.bodyFile) {
1197
- if (opts.bodyFile === "-") return readStdin();
1198
- return import_promises5.default.readFile(opts.bodyFile, "utf-8");
1446
+
1447
+ // src/commands/post/edit.ts
1448
+ async function resolveUsers(client, projectId, emails) {
1449
+ const users = [];
1450
+ for (const email of emails) {
1451
+ const memberId = await resolveMember(client, projectId, email);
1452
+ users.push({ type: "member", member: { organizationMemberId: memberId } });
1199
1453
  }
1200
- return null;
1454
+ return users;
1201
1455
  }
1202
- var postEditCommand = new import_commander10.Command("edit").description("\uC5C5\uBB34 \uC218\uC815 ($EDITOR \uB610\uB294 --subject/--body \uC635\uC158)").argument("<project>", "\uD504\uB85C\uC81D\uD2B8 \uCF54\uB4DC \uB610\uB294 ID").argument("<post-number>", "\uC5C5\uBB34 \uBC88\uD638").option("--subject <title>", "\uC81C\uBAA9 \uBCC0\uACBD (non-interactive)").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) => {
1456
+ var postEditCommand = new import_commander11.Command("edit").description("\uC5C5\uBB34 \uC218\uC815 ($EDITOR \uB610\uB294 --title/--body \uC635\uC158)").argument("<project>", "\uD504\uB85C\uC81D\uD2B8 \uCF54\uB4DC \uB610\uB294 ID").argument("<post-number>", "\uC5C5\uBB34 \uBC88\uD638").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) => {
1203
1457
  const config = await getConfigOrThrow();
1204
1458
  const client = new DoorayApiClient(config.apiKey, config.baseUrl);
1205
1459
  startSpinner("\uC5C5\uBB34 \uC870\uD68C \uC911...");
@@ -1209,9 +1463,15 @@ var postEditCommand = new import_commander10.Command("edit").description("\uC5C5
1209
1463
  const post = res.result;
1210
1464
  const members = await ensureMembers(client, projectId);
1211
1465
  stopSpinner(true, "\uC5C5\uBB34 \uC870\uD68C \uC644\uB8CC");
1212
- const nonInteractive = opts.subject || opts.body || opts.bodyFile;
1466
+ const title = opts.title ?? opts.subject;
1467
+ if (opts.subject && !opts.title) {
1468
+ process.stderr.write(
1469
+ "\u26A0 --subject\uB294 deprecated\uC785\uB2C8\uB2E4. \uB300\uC2E0 --title\uC744 \uC0AC\uC6A9\uD574\uC8FC\uC138\uC694.\n"
1470
+ );
1471
+ }
1472
+ const nonInteractive = title || opts.body || opts.bodyFile;
1213
1473
  if (nonInteractive) {
1214
- const newBody = await resolveBody(opts);
1474
+ const newBody = await readBodyInputOrNull(opts);
1215
1475
  startSpinner("\uC5C5\uBB34 \uC218\uC815 \uC911...");
1216
1476
  const toUsers = post.users.to.map((u) => ({
1217
1477
  type: u.type,
@@ -1226,7 +1486,7 @@ var postEditCommand = new import_commander10.Command("edit").description("\uC5C5
1226
1486
  group: u.group
1227
1487
  }));
1228
1488
  await client.updatePost(projectId, postId, {
1229
- subject: opts.subject ?? post.subject,
1489
+ subject: title ?? post.subject,
1230
1490
  body: {
1231
1491
  mimeType: "text/x-markdown",
1232
1492
  content: newBody ?? post.body.content
@@ -1263,33 +1523,7 @@ var postEditCommand = new import_commander10.Command("edit").description("\uC5C5
1263
1523
  });
1264
1524
 
1265
1525
  // src/commands/post/create.ts
1266
- var import_commander11 = require("commander");
1267
- var import_promises6 = __toESM(require("fs/promises"));
1268
- async function readBody(opts) {
1269
- if (opts.bodyFile) {
1270
- if (opts.bodyFile === "-") {
1271
- return readStdin2();
1272
- }
1273
- return import_promises6.default.readFile(opts.bodyFile, "utf-8");
1274
- }
1275
- if (opts.body === "-") {
1276
- return readStdin2();
1277
- }
1278
- return "";
1279
- }
1280
- async function readStdin2() {
1281
- if (process.stdin.isTTY) {
1282
- throw new DoorayCliError(
1283
- "stdin\uC5D0\uC11C \uC77D\uC73C\uB824\uBA74 \uD30C\uC774\uD504\uB85C \uB370\uC774\uD130\uB97C \uC804\uB2EC\uD574\uC8FC\uC138\uC694.",
1284
- EXIT_PARAM_ERROR
1285
- );
1286
- }
1287
- const chunks = [];
1288
- for await (const chunk of process.stdin) {
1289
- chunks.push(chunk);
1290
- }
1291
- return Buffer.concat(chunks).toString("utf-8");
1292
- }
1526
+ var import_commander12 = require("commander");
1293
1527
  async function resolveUsers2(client, projectId, inputs) {
1294
1528
  const users = [];
1295
1529
  for (const input of inputs) {
@@ -1298,17 +1532,29 @@ async function resolveUsers2(client, projectId, inputs) {
1298
1532
  }
1299
1533
  return users;
1300
1534
  }
1301
- var postCreateCommand = new import_commander11.Command("create").description("\uC5C5\uBB34 \uC0DD\uC131").argument("<project>", "\uD504\uB85C\uC81D\uD2B8 \uCF54\uB4DC \uB610\uB294 ID").requiredOption("--subject <title>", "\uC5C5\uBB34 \uC81C\uBAA9").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)").action(async (project, opts) => {
1535
+ var postCreateCommand = new import_commander12.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)").action(async (project, opts) => {
1302
1536
  const globalOpts = postCreateCommand.optsWithGlobals();
1303
1537
  const config = await getConfigOrThrow();
1304
1538
  const client = new DoorayApiClient(config.apiKey, config.baseUrl);
1305
- const bodyContent = await readBody(opts);
1539
+ const subject = opts.title ?? opts.subject;
1540
+ if (!subject) {
1541
+ throw new DoorayCliError(
1542
+ "--title\uC774 \uD544\uC694\uD569\uB2C8\uB2E4.",
1543
+ EXIT_PARAM_ERROR
1544
+ );
1545
+ }
1546
+ if (opts.subject && !opts.title) {
1547
+ process.stderr.write(
1548
+ "\u26A0 --subject\uB294 deprecated\uC785\uB2C8\uB2E4. \uB300\uC2E0 --title\uC744 \uC0AC\uC6A9\uD574\uC8FC\uC138\uC694.\n"
1549
+ );
1550
+ }
1551
+ const bodyContent = await readBodyInput(opts);
1306
1552
  startSpinner("\uC5C5\uBB34 \uC0DD\uC131 \uC911...");
1307
1553
  const projectId = await resolveProject(client, project);
1308
1554
  const toUsers = opts.to ? await resolveUsers2(client, projectId, opts.to) : [];
1309
1555
  const ccUsers = opts.cc ? await resolveUsers2(client, projectId, opts.cc) : [];
1310
1556
  const res = await client.createPost(projectId, {
1311
- subject: opts.subject,
1557
+ subject,
1312
1558
  body: { mimeType: "text/x-markdown", content: bodyContent },
1313
1559
  users: { to: toUsers, cc: ccUsers },
1314
1560
  priority: opts.priority,
@@ -1326,8 +1572,8 @@ var postCreateCommand = new import_commander11.Command("create").description("\u
1326
1572
  });
1327
1573
 
1328
1574
  // src/commands/post/done.ts
1329
- var import_commander12 = require("commander");
1330
- var postDoneCommand = new import_commander12.Command("done").description("\uC5C5\uBB34 \uC644\uB8CC \uCC98\uB9AC").argument("<project>", "\uD504\uB85C\uC81D\uD2B8 \uCF54\uB4DC \uB610\uB294 ID").argument("<post-number>", "\uC5C5\uBB34 \uBC88\uD638").action(async (project, postNumberStr) => {
1575
+ var import_commander13 = require("commander");
1576
+ var postDoneCommand = new import_commander13.Command("done").description("\uC5C5\uBB34 \uC644\uB8CC \uCC98\uB9AC").argument("<project>", "\uD504\uB85C\uC81D\uD2B8 \uCF54\uB4DC \uB610\uB294 ID").argument("<post-number>", "\uC5C5\uBB34 \uBC88\uD638").action(async (project, postNumberStr) => {
1331
1577
  const config = await getConfigOrThrow();
1332
1578
  const client = new DoorayApiClient(config.apiKey, config.baseUrl);
1333
1579
  startSpinner("\uC5C5\uBB34 \uC644\uB8CC \uCC98\uB9AC \uC911...");
@@ -1340,8 +1586,8 @@ var postDoneCommand = new import_commander12.Command("done").description("\uC5C5
1340
1586
  });
1341
1587
 
1342
1588
  // src/commands/post/workflow.ts
1343
- var import_commander13 = require("commander");
1344
- var postWorkflowCommand = new import_commander13.Command("workflow").description("\uC5C5\uBB34 \uC6CC\uD06C\uD50C\uB85C\uC6B0 \uBCC0\uACBD").argument("<project>", "\uD504\uB85C\uC81D\uD2B8 \uCF54\uB4DC \uB610\uB294 ID").argument("<post-number>", "\uC5C5\uBB34 \uBC88\uD638").argument("<workflow>", "\uC6CC\uD06C\uD50C\uB85C\uC6B0 \uC774\uB984 \uB610\uB294 \uD074\uB798\uC2A4").action(async (project, postNumberStr, workflow) => {
1589
+ var import_commander14 = require("commander");
1590
+ var postWorkflowCommand = new import_commander14.Command("workflow").description("\uC5C5\uBB34 \uC6CC\uD06C\uD50C\uB85C\uC6B0 \uBCC0\uACBD").argument("<project>", "\uD504\uB85C\uC81D\uD2B8 \uCF54\uB4DC \uB610\uB294 ID").argument("<post-number>", "\uC5C5\uBB34 \uBC88\uD638").argument("<workflow>", "\uC6CC\uD06C\uD50C\uB85C\uC6B0 \uC774\uB984 \uB610\uB294 \uD074\uB798\uC2A4").action(async (project, postNumberStr, workflow) => {
1345
1591
  const config = await getConfigOrThrow();
1346
1592
  const client = new DoorayApiClient(config.apiKey, config.baseUrl);
1347
1593
  startSpinner("\uC6CC\uD06C\uD50C\uB85C\uC6B0 \uBCC0\uACBD \uC911...");
@@ -1355,8 +1601,8 @@ var postWorkflowCommand = new import_commander13.Command("workflow").description
1355
1601
  });
1356
1602
 
1357
1603
  // src/commands/post/comment/list.ts
1358
- var import_commander14 = require("commander");
1359
- var commentListCommand = new import_commander14.Command("list").description("\uB313\uAE00 \uBAA9\uB85D \uC870\uD68C").argument("<project>", "\uD504\uB85C\uC81D\uD2B8 \uCF54\uB4DC \uB610\uB294 ID").argument("<post-number>", "\uC5C5\uBB34 \uBC88\uD638").option("--page <number>", "\uD398\uC774\uC9C0 \uBC88\uD638", "0").option("--size <number>", "\uD398\uC774\uC9C0 \uD06C\uAE30", "20").action(async (project, postNumberStr, opts) => {
1604
+ var import_commander15 = require("commander");
1605
+ var commentListCommand = new import_commander15.Command("list").description("\uB313\uAE00 \uBAA9\uB85D \uC870\uD68C").argument("<project>", "\uD504\uB85C\uC81D\uD2B8 \uCF54\uB4DC \uB610\uB294 ID").argument("<post-number>", "\uC5C5\uBB34 \uBC88\uD638").option("--page <number>", "\uD398\uC774\uC9C0 \uBC88\uD638", "0").option("--size <number>", "\uD398\uC774\uC9C0 \uD06C\uAE30", "20").action(async (project, postNumberStr, opts) => {
1360
1606
  const globalOpts = commentListCommand.optsWithGlobals();
1361
1607
  const config = await getConfigOrThrow();
1362
1608
  const client = new DoorayApiClient(config.apiKey, config.baseUrl);
@@ -1372,37 +1618,12 @@ var commentListCommand = new import_commander14.Command("list").description("\uB
1372
1618
  });
1373
1619
 
1374
1620
  // src/commands/post/comment/add.ts
1375
- var import_commander15 = require("commander");
1376
- var import_promises7 = __toESM(require("fs/promises"));
1377
- async function readStdin3() {
1378
- if (process.stdin.isTTY) {
1379
- throw new DoorayCliError(
1380
- "stdin\uC5D0\uC11C \uC77D\uC73C\uB824\uBA74 \uD30C\uC774\uD504\uB85C \uB370\uC774\uD130\uB97C \uC804\uB2EC\uD574\uC8FC\uC138\uC694.",
1381
- EXIT_PARAM_ERROR
1382
- );
1383
- }
1384
- const chunks = [];
1385
- for await (const chunk of process.stdin) {
1386
- chunks.push(chunk);
1387
- }
1388
- return Buffer.concat(chunks).toString("utf-8");
1389
- }
1390
- async function resolveBody2(opts) {
1391
- if (opts.body) {
1392
- if (opts.body === "-") return readStdin3();
1393
- return opts.body;
1394
- }
1395
- if (opts.bodyFile) {
1396
- if (opts.bodyFile === "-") return readStdin3();
1397
- return import_promises7.default.readFile(opts.bodyFile, "utf-8");
1398
- }
1399
- return null;
1400
- }
1401
- var commentAddCommand = new import_commander15.Command("add").description("\uB313\uAE00 \uCD94\uAC00").argument("<project>", "\uD504\uB85C\uC81D\uD2B8 \uCF54\uB4DC \uB610\uB294 ID").argument("<post-number>", "\uC5C5\uBB34 \uBC88\uD638").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)").action(async (project, postNumberStr, opts) => {
1621
+ var import_commander16 = require("commander");
1622
+ var commentAddCommand = new import_commander16.Command("add").description("\uB313\uAE00 \uCD94\uAC00").argument("<project>", "\uD504\uB85C\uC81D\uD2B8 \uCF54\uB4DC \uB610\uB294 ID").argument("<post-number>", "\uC5C5\uBB34 \uBC88\uD638").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)").action(async (project, postNumberStr, opts) => {
1402
1623
  const globalOpts = commentAddCommand.optsWithGlobals();
1403
1624
  const config = await getConfigOrThrow();
1404
1625
  const client = new DoorayApiClient(config.apiKey, config.baseUrl);
1405
- let bodyContent = await resolveBody2(opts);
1626
+ let bodyContent = await readBodyInputOrNull(opts);
1406
1627
  if (bodyContent == null) {
1407
1628
  bodyContent = await openInEditor("");
1408
1629
  if (!bodyContent.trim()) {
@@ -1428,33 +1649,8 @@ var commentAddCommand = new import_commander15.Command("add").description("\uB31
1428
1649
  });
1429
1650
 
1430
1651
  // src/commands/post/comment/edit.ts
1431
- var import_commander16 = require("commander");
1432
- var import_promises8 = __toESM(require("fs/promises"));
1433
- async function readStdin4() {
1434
- if (process.stdin.isTTY) {
1435
- throw new DoorayCliError(
1436
- "stdin\uC5D0\uC11C \uC77D\uC73C\uB824\uBA74 \uD30C\uC774\uD504\uB85C \uB370\uC774\uD130\uB97C \uC804\uB2EC\uD574\uC8FC\uC138\uC694.",
1437
- EXIT_PARAM_ERROR
1438
- );
1439
- }
1440
- const chunks = [];
1441
- for await (const chunk of process.stdin) {
1442
- chunks.push(chunk);
1443
- }
1444
- return Buffer.concat(chunks).toString("utf-8");
1445
- }
1446
- async function resolveBody3(opts) {
1447
- if (opts.body) {
1448
- if (opts.body === "-") return readStdin4();
1449
- return opts.body;
1450
- }
1451
- if (opts.bodyFile) {
1452
- if (opts.bodyFile === "-") return readStdin4();
1453
- return import_promises8.default.readFile(opts.bodyFile, "utf-8");
1454
- }
1455
- return null;
1456
- }
1457
- var commentEditCommand = new import_commander16.Command("edit").description("\uB313\uAE00 \uC218\uC815 ($EDITOR \uB610\uB294 --body \uC635\uC158)").argument("<project>", "\uD504\uB85C\uC81D\uD2B8 \uCF54\uB4DC \uB610\uB294 ID").argument("<post-number>", "\uC5C5\uBB34 \uBC88\uD638").argument("<comment-id>", "\uB313\uAE00 ID").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)").action(async (project, postNumberStr, commentId, opts) => {
1652
+ var import_commander17 = require("commander");
1653
+ var commentEditCommand = new import_commander17.Command("edit").description("\uB313\uAE00 \uC218\uC815 ($EDITOR \uB610\uB294 --body \uC635\uC158)").argument("<project>", "\uD504\uB85C\uC81D\uD2B8 \uCF54\uB4DC \uB610\uB294 ID").argument("<post-number>", "\uC5C5\uBB34 \uBC88\uD638").argument("<comment-id>", "\uB313\uAE00 ID").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)").action(async (project, postNumberStr, commentId, opts) => {
1458
1654
  const config = await getConfigOrThrow();
1459
1655
  const client = new DoorayApiClient(config.apiKey, config.baseUrl);
1460
1656
  startSpinner("\uB313\uAE00 \uC870\uD68C \uC911...");
@@ -1468,7 +1664,7 @@ var commentEditCommand = new import_commander16.Command("edit").description("\uB
1468
1664
  `);
1469
1665
  process.exit(1);
1470
1666
  }
1471
- let edited = await resolveBody3(opts);
1667
+ let edited = await readBodyInputOrNull(opts);
1472
1668
  if (edited == null) {
1473
1669
  const original = comment.body.content;
1474
1670
  edited = await openInEditor(original);
@@ -1487,8 +1683,8 @@ var commentEditCommand = new import_commander16.Command("edit").description("\uB
1487
1683
  });
1488
1684
 
1489
1685
  // src/commands/post/comment/delete.ts
1490
- var import_commander17 = require("commander");
1491
- var commentDeleteCommand = new import_commander17.Command("delete").description("\uB313\uAE00 \uC0AD\uC81C").argument("<project>", "\uD504\uB85C\uC81D\uD2B8 \uCF54\uB4DC \uB610\uB294 ID").argument("<post-number>", "\uC5C5\uBB34 \uBC88\uD638").argument("<comment-id>", "\uB313\uAE00 ID").action(async (project, postNumberStr, commentId) => {
1686
+ var import_commander18 = require("commander");
1687
+ var commentDeleteCommand = new import_commander18.Command("delete").description("\uB313\uAE00 \uC0AD\uC81C").argument("<project>", "\uD504\uB85C\uC81D\uD2B8 \uCF54\uB4DC \uB610\uB294 ID").argument("<post-number>", "\uC5C5\uBB34 \uBC88\uD638").argument("<comment-id>", "\uB313\uAE00 ID").action(async (project, postNumberStr, commentId) => {
1492
1688
  const config = await getConfigOrThrow();
1493
1689
  const client = new DoorayApiClient(config.apiKey, config.baseUrl);
1494
1690
  startSpinner("\uB313\uAE00 \uC0AD\uC81C \uC911...");
@@ -1501,13 +1697,13 @@ var commentDeleteCommand = new import_commander17.Command("delete").description(
1501
1697
  });
1502
1698
 
1503
1699
  // src/commands/post/file/list.ts
1504
- var import_commander18 = require("commander");
1700
+ var import_commander19 = require("commander");
1505
1701
  function formatSize(bytes) {
1506
1702
  if (bytes < 1024) return `${bytes}B`;
1507
1703
  if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)}KB`;
1508
1704
  return `${(bytes / (1024 * 1024)).toFixed(1)}MB`;
1509
1705
  }
1510
- var fileListCommand = new import_commander18.Command("list").description("\uC5C5\uBB34 \uCCA8\uBD80\uD30C\uC77C \uBAA9\uB85D \uC870\uD68C").argument("<project>", "\uD504\uB85C\uC81D\uD2B8 \uCF54\uB4DC \uB610\uB294 ID").argument("<post-number>", "\uC5C5\uBB34 \uBC88\uD638").action(async (project, postNumberStr) => {
1706
+ var fileListCommand = new import_commander19.Command("list").description("\uC5C5\uBB34 \uCCA8\uBD80\uD30C\uC77C \uBAA9\uB85D \uC870\uD68C").argument("<project>", "\uD504\uB85C\uC81D\uD2B8 \uCF54\uB4DC \uB610\uB294 ID").argument("<post-number>", "\uC5C5\uBB34 \uBC88\uD638").action(async (project, postNumberStr) => {
1511
1707
  const globalOpts = fileListCommand.optsWithGlobals();
1512
1708
  const config = await getConfigOrThrow();
1513
1709
  const client = new DoorayApiClient(config.apiKey, config.baseUrl);
@@ -1531,10 +1727,10 @@ var fileListCommand = new import_commander18.Command("list").description("\uC5C5
1531
1727
  });
1532
1728
 
1533
1729
  // src/commands/post/file/download.ts
1534
- var import_commander19 = require("commander");
1535
- var import_promises9 = require("fs/promises");
1730
+ var import_commander20 = require("commander");
1731
+ var import_promises8 = require("fs/promises");
1536
1732
  var import_node_path4 = require("path");
1537
- var fileDownloadCommand = new import_commander19.Command("download").description("\uCCA8\uBD80\uD30C\uC77C \uB2E4\uC6B4\uB85C\uB4DC").argument("<project>", "\uD504\uB85C\uC81D\uD2B8 \uCF54\uB4DC \uB610\uB294 ID").argument("<post-number>", "\uC5C5\uBB34 \uBC88\uD638").argument("<file-id>", "\uD30C\uC77C ID").option("-o, --output <dir>", "\uC800\uC7A5 \uB514\uB809\uD1A0\uB9AC", ".").action(async (project, postNumberStr, fileId, opts) => {
1733
+ var fileDownloadCommand = new import_commander20.Command("download").description("\uCCA8\uBD80\uD30C\uC77C \uB2E4\uC6B4\uB85C\uB4DC").argument("<project>", "\uD504\uB85C\uC81D\uD2B8 \uCF54\uB4DC \uB610\uB294 ID").argument("<post-number>", "\uC5C5\uBB34 \uBC88\uD638").argument("<file-id>", "\uD30C\uC77C ID").option("-o, --output <dir>", "\uC800\uC7A5 \uB514\uB809\uD1A0\uB9AC", ".").action(async (project, postNumberStr, fileId, opts) => {
1538
1734
  const config = await getConfigOrThrow();
1539
1735
  const client = new DoorayApiClient(config.apiKey, config.baseUrl);
1540
1736
  startSpinner("\uD30C\uC77C \uB2E4\uC6B4\uB85C\uB4DC \uC911...");
@@ -1542,17 +1738,17 @@ var fileDownloadCommand = new import_commander19.Command("download").description
1542
1738
  const postId = await resolvePost(client, projectId, Number(postNumberStr));
1543
1739
  const { buffer, fileName } = await client.downloadPostFile(projectId, postId, fileId);
1544
1740
  const outputPath = (0, import_node_path4.join)(opts.output, fileName);
1545
- await (0, import_promises9.writeFile)(outputPath, Buffer.from(buffer));
1741
+ await (0, import_promises8.writeFile)(outputPath, Buffer.from(buffer));
1546
1742
  stopSpinner(true, "\uB2E4\uC6B4\uB85C\uB4DC \uC644\uB8CC");
1547
1743
  process.stdout.write(`${outputPath}
1548
1744
  `);
1549
1745
  });
1550
1746
 
1551
1747
  // src/commands/post/file/download-all.ts
1552
- var import_commander20 = require("commander");
1553
- var import_promises10 = require("fs/promises");
1748
+ var import_commander21 = require("commander");
1749
+ var import_promises9 = require("fs/promises");
1554
1750
  var import_node_path5 = require("path");
1555
- var fileDownloadAllCommand = new import_commander20.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 ID").argument("<post-number>", "\uC5C5\uBB34 \uBC88\uD638").option("-o, --output <dir>", "\uC800\uC7A5 \uB514\uB809\uD1A0\uB9AC", ".").action(async (project, postNumberStr, opts) => {
1751
+ var fileDownloadAllCommand = new import_commander21.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 ID").argument("<post-number>", "\uC5C5\uBB34 \uBC88\uD638").option("-o, --output <dir>", "\uC800\uC7A5 \uB514\uB809\uD1A0\uB9AC", ".").action(async (project, postNumberStr, opts) => {
1556
1752
  const config = await getConfigOrThrow();
1557
1753
  const client = new DoorayApiClient(config.apiKey, config.baseUrl);
1558
1754
  const spinner = startSpinner("\uCCA8\uBD80\uD30C\uC77C \uBAA9\uB85D \uC870\uD68C \uC911...");
@@ -1564,26 +1760,26 @@ var fileDownloadAllCommand = new import_commander20.Command("download-all").desc
1564
1760
  process.stdout.write("\uCCA8\uBD80\uD30C\uC77C\uC774 \uC5C6\uC2B5\uB2C8\uB2E4.\n");
1565
1761
  return;
1566
1762
  }
1567
- await (0, import_promises10.mkdir)(opts.output, { recursive: true });
1763
+ await (0, import_promises9.mkdir)(opts.output, { recursive: true });
1568
1764
  const downloaded = [];
1569
1765
  for (const file of res.result) {
1570
1766
  spinner.text = `\uB2E4\uC6B4\uB85C\uB4DC \uC911: ${file.name} (${downloaded.length + 1}/${res.result.length})`;
1571
1767
  const { buffer, fileName } = await client.downloadPostFile(projectId, postId, file.id);
1572
1768
  const outputPath = (0, import_node_path5.join)(opts.output, fileName);
1573
- await (0, import_promises10.writeFile)(outputPath, Buffer.from(buffer));
1769
+ await (0, import_promises9.writeFile)(outputPath, Buffer.from(buffer));
1574
1770
  downloaded.push(outputPath);
1575
1771
  }
1576
1772
  stopSpinner(true, `${downloaded.length}\uAC1C \uD30C\uC77C \uB2E4\uC6B4\uB85C\uB4DC \uC644\uB8CC`);
1577
- for (const path of downloaded) {
1578
- process.stdout.write(`${path}
1773
+ for (const path3 of downloaded) {
1774
+ process.stdout.write(`${path3}
1579
1775
  `);
1580
1776
  }
1581
1777
  });
1582
1778
 
1583
1779
  // src/commands/post/file/upload.ts
1584
- var import_commander21 = require("commander");
1780
+ var import_commander22 = require("commander");
1585
1781
  var import_node_path6 = require("path");
1586
- var fileUploadCommand = new import_commander21.Command("upload").description("\uCCA8\uBD80\uD30C\uC77C \uC5C5\uB85C\uB4DC").argument("<project>", "\uD504\uB85C\uC81D\uD2B8 \uCF54\uB4DC \uB610\uB294 ID").argument("<post-number>", "\uC5C5\uBB34 \uBC88\uD638").argument("<file-path>", "\uC5C5\uB85C\uB4DC\uD560 \uD30C\uC77C \uACBD\uB85C").action(async (project, postNumberStr, filePath) => {
1782
+ var fileUploadCommand = new import_commander22.Command("upload").description("\uCCA8\uBD80\uD30C\uC77C \uC5C5\uB85C\uB4DC").argument("<project>", "\uD504\uB85C\uC81D\uD2B8 \uCF54\uB4DC \uB610\uB294 ID").argument("<post-number>", "\uC5C5\uBB34 \uBC88\uD638").argument("<file-path>", "\uC5C5\uB85C\uB4DC\uD560 \uD30C\uC77C \uACBD\uB85C").action(async (project, postNumberStr, filePath) => {
1587
1783
  const globalOpts = fileUploadCommand.optsWithGlobals();
1588
1784
  const config = await getConfigOrThrow();
1589
1785
  const client = new DoorayApiClient(config.apiKey, config.baseUrl);
@@ -1604,8 +1800,8 @@ var fileUploadCommand = new import_commander21.Command("upload").description("\u
1604
1800
  });
1605
1801
 
1606
1802
  // src/commands/post/file/delete.ts
1607
- var import_commander22 = require("commander");
1608
- var fileDeleteCommand = new import_commander22.Command("delete").description("\uCCA8\uBD80\uD30C\uC77C \uC0AD\uC81C").argument("<project>", "\uD504\uB85C\uC81D\uD2B8 \uCF54\uB4DC \uB610\uB294 ID").argument("<post-number>", "\uC5C5\uBB34 \uBC88\uD638").argument("<file-id>", "\uD30C\uC77C ID").action(async (project, postNumberStr, fileId) => {
1803
+ var import_commander23 = require("commander");
1804
+ var fileDeleteCommand = new import_commander23.Command("delete").description("\uCCA8\uBD80\uD30C\uC77C \uC0AD\uC81C").argument("<project>", "\uD504\uB85C\uC81D\uD2B8 \uCF54\uB4DC \uB610\uB294 ID").argument("<post-number>", "\uC5C5\uBB34 \uBC88\uD638").argument("<file-id>", "\uD30C\uC77C ID").action(async (project, postNumberStr, fileId) => {
1609
1805
  const config = await getConfigOrThrow();
1610
1806
  const client = new DoorayApiClient(config.apiKey, config.baseUrl);
1611
1807
  startSpinner("\uD30C\uC77C \uC0AD\uC81C \uC911...");
@@ -1618,7 +1814,7 @@ var fileDeleteCommand = new import_commander22.Command("delete").description("\u
1618
1814
  });
1619
1815
 
1620
1816
  // src/commands/wiki/list.ts
1621
- var import_commander23 = require("commander");
1817
+ var import_commander24 = require("commander");
1622
1818
 
1623
1819
  // src/formatters/wiki.ts
1624
1820
  function formatWikiList(wikis, opts) {
@@ -1661,7 +1857,7 @@ function formatWikiPageDetail(page, opts) {
1661
1857
  }
1662
1858
 
1663
1859
  // src/commands/wiki/list.ts
1664
- var wikiListCommand = new import_commander23.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) => {
1860
+ var wikiListCommand = new import_commander24.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) => {
1665
1861
  const globalOpts = wikiListCommand.optsWithGlobals();
1666
1862
  const config = await getConfigOrThrow();
1667
1863
  const client = new DoorayApiClient(config.apiKey, config.baseUrl);
@@ -1675,7 +1871,7 @@ var wikiListCommand = new import_commander23.Command("list").description("\uC704
1675
1871
  });
1676
1872
 
1677
1873
  // src/commands/wiki/pages.ts
1678
- var import_commander24 = require("commander");
1874
+ var import_commander25 = require("commander");
1679
1875
 
1680
1876
  // src/resolvers/wiki.ts
1681
1877
  async function resolveWiki(client, projectCode) {
@@ -1692,9 +1888,34 @@ async function resolveWiki(client, projectCode) {
1692
1888
  }
1693
1889
  return project.wikiId;
1694
1890
  }
1891
+ async function resolveWikiHomePageId(client, wikiId) {
1892
+ const cached = await getWikis();
1893
+ const fresh = cached && !isExpired(cached.updatedAt, WIKIS_TTL_MS);
1894
+ let wikis;
1895
+ if (fresh) {
1896
+ wikis = cached.data;
1897
+ } else {
1898
+ const res = await client.getWikis({ size: 100 });
1899
+ wikis = res.result.map((w) => ({
1900
+ id: w.id,
1901
+ projectId: w.project.id,
1902
+ name: w.name,
1903
+ homePageId: w.home.pageId
1904
+ }));
1905
+ await setWikis(wikis);
1906
+ }
1907
+ const wiki = wikis.find((w) => w.id === wikiId);
1908
+ if (!wiki?.homePageId) {
1909
+ throw new DoorayCliError(
1910
+ `\uC704\uD0A4\uC758 home \uD398\uC774\uC9C0\uB97C \uCC3E\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4 (wikiId: ${wikiId})`,
1911
+ EXIT_API_ERROR
1912
+ );
1913
+ }
1914
+ return wiki.homePageId;
1915
+ }
1695
1916
 
1696
1917
  // src/commands/wiki/pages.ts
1697
- var wikiPagesCommand = new import_commander24.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) => {
1918
+ var wikiPagesCommand = new import_commander25.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) => {
1698
1919
  const globalOpts = wikiPagesCommand.optsWithGlobals();
1699
1920
  const config = await getConfigOrThrow();
1700
1921
  const client = new DoorayApiClient(config.apiKey, config.baseUrl);
@@ -1706,8 +1927,8 @@ var wikiPagesCommand = new import_commander24.Command("pages").description("\uC7
1706
1927
  });
1707
1928
 
1708
1929
  // src/commands/wiki/page-get.ts
1709
- var import_commander25 = require("commander");
1710
- var wikiPageGetCommand = new import_commander25.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) => {
1930
+ var import_commander26 = require("commander");
1931
+ var wikiPageGetCommand = new import_commander26.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) => {
1711
1932
  const globalOpts = wikiPageGetCommand.optsWithGlobals();
1712
1933
  const config = await getConfigOrThrow();
1713
1934
  const client = new DoorayApiClient(config.apiKey, config.baseUrl);
@@ -1719,44 +1940,19 @@ var wikiPageGetCommand = new import_commander25.Command("get").description("\uC7
1719
1940
  });
1720
1941
 
1721
1942
  // src/commands/wiki/page-create.ts
1722
- var import_commander26 = require("commander");
1723
- var import_promises11 = __toESM(require("fs/promises"));
1724
- async function readBody2(opts) {
1725
- if (opts.bodyFile) {
1726
- if (opts.bodyFile === "-") {
1727
- return readStdin5();
1728
- }
1729
- return import_promises11.default.readFile(opts.bodyFile, "utf-8");
1730
- }
1731
- if (opts.body === "-") {
1732
- return readStdin5();
1733
- }
1734
- return "";
1735
- }
1736
- async function readStdin5() {
1737
- if (process.stdin.isTTY) {
1738
- throw new DoorayCliError(
1739
- "stdin\uC5D0\uC11C \uC77D\uC73C\uB824\uBA74 \uD30C\uC774\uD504\uB85C \uB370\uC774\uD130\uB97C \uC804\uB2EC\uD574\uC8FC\uC138\uC694.",
1740
- EXIT_PARAM_ERROR
1741
- );
1742
- }
1743
- const chunks = [];
1744
- for await (const chunk of process.stdin) {
1745
- chunks.push(chunk);
1746
- }
1747
- return Buffer.concat(chunks).toString("utf-8");
1748
- }
1749
- var wikiPageCreateCommand = new import_commander26.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) => {
1943
+ var import_commander27 = require("commander");
1944
+ var wikiPageCreateCommand = new import_commander27.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) => {
1750
1945
  const globalOpts = wikiPageCreateCommand.optsWithGlobals();
1751
1946
  const config = await getConfigOrThrow();
1752
1947
  const client = new DoorayApiClient(config.apiKey, config.baseUrl);
1753
- const bodyContent = await readBody2(opts);
1948
+ const bodyContent = await readBodyInput(opts);
1754
1949
  startSpinner("\uC704\uD0A4 \uD398\uC774\uC9C0 \uC0DD\uC131 \uC911...");
1755
1950
  const wikiId = await resolveWiki(client, project);
1951
+ const parentPageId = opts.parent ?? await resolveWikiHomePageId(client, wikiId);
1756
1952
  const res = await client.createWikiPage(wikiId, {
1757
1953
  subject: opts.title,
1758
1954
  body: { mimeType: "text/x-markdown", content: bodyContent },
1759
- parentPageId: opts.parent ?? ""
1955
+ parentPageId
1760
1956
  });
1761
1957
  stopSpinner(true, "\uC704\uD0A4 \uD398\uC774\uC9C0 \uC0DD\uC131 \uC644\uB8CC");
1762
1958
  if (globalOpts.json) {
@@ -1770,34 +1966,61 @@ var wikiPageCreateCommand = new import_commander26.Command("create").description
1770
1966
  });
1771
1967
 
1772
1968
  // src/commands/wiki/page-edit.ts
1773
- var import_commander27 = require("commander");
1774
- var wikiPageEditCommand = new import_commander27.Command("edit").description("\uC704\uD0A4 \uD398\uC774\uC9C0 \uC218\uC815 ($EDITOR)").argument("<project>", "\uD504\uB85C\uC81D\uD2B8 \uCF54\uB4DC \uB610\uB294 ID").argument("<page-id>", "\uD398\uC774\uC9C0 ID").action(async (project, pageId) => {
1969
+ var import_commander28 = require("commander");
1970
+ var wikiPageEditCommand = new import_commander28.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) => {
1775
1971
  const config = await getConfigOrThrow();
1776
1972
  const client = new DoorayApiClient(config.apiKey, config.baseUrl);
1777
- startSpinner("\uC704\uD0A4 \uD398\uC774\uC9C0 \uC870\uD68C \uC911...");
1973
+ const hasTitle = opts.title != null;
1974
+ const hasBody = opts.body != null || opts.bodyFile != null;
1975
+ const nonInteractive = hasTitle || hasBody;
1976
+ startSpinner("\uC704\uD0A4 \uC815\uBCF4 \uC870\uD68C \uC911...");
1778
1977
  const wikiId = await resolveWiki(client, project);
1779
- const res = await client.getWikiPage(wikiId, pageId);
1780
- const page = res.result;
1781
- stopSpinner(true, "\uC704\uD0A4 \uD398\uC774\uC9C0 \uC870\uD68C \uC644\uB8CC");
1782
- const original = serializeWikiFrontmatter(page);
1783
- const edited = await openInEditor(original);
1784
- if (original === edited) {
1785
- process.stdout.write("\uBCC0\uACBD\uC0AC\uD56D \uC5C6\uC74C\n");
1978
+ if (!nonInteractive) {
1979
+ const res = await client.getWikiPage(wikiId, pageId);
1980
+ const page = res.result;
1981
+ stopSpinner(true, "\uC704\uD0A4 \uD398\uC774\uC9C0 \uC870\uD68C \uC644\uB8CC");
1982
+ const original = serializeWikiFrontmatter(page);
1983
+ const edited = await openInEditor(original);
1984
+ if (original === edited) {
1985
+ process.stdout.write("\uBCC0\uACBD\uC0AC\uD56D \uC5C6\uC74C\n");
1986
+ return;
1987
+ }
1988
+ const parsed = parseWikiFrontmatter(edited);
1989
+ startSpinner("\uC704\uD0A4 \uD398\uC774\uC9C0 \uC218\uC815 \uC911...");
1990
+ await client.updateWikiPage(wikiId, pageId, {
1991
+ subject: parsed.title,
1992
+ body: { mimeType: "text/x-markdown", content: parsed.body }
1993
+ });
1994
+ stopSpinner(true, "\uC704\uD0A4 \uD398\uC774\uC9C0 \uC218\uC815 \uC644\uB8CC");
1995
+ process.stdout.write(`\uC704\uD0A4 \uD398\uC774\uC9C0\uAC00 \uC218\uC815\uB418\uC5C8\uC2B5\uB2C8\uB2E4: ${pageId}
1996
+ `);
1786
1997
  return;
1787
1998
  }
1788
- const parsed = parseWikiFrontmatter(edited);
1789
- startSpinner("\uC704\uD0A4 \uD398\uC774\uC9C0 \uC218\uC815 \uC911...");
1790
- await client.updateWikiPage(wikiId, pageId, {
1791
- subject: parsed.title,
1792
- body: { mimeType: "text/x-markdown", content: parsed.body }
1793
- });
1999
+ stopSpinner(true, "\uC704\uD0A4 \uC815\uBCF4 \uC870\uD68C \uC644\uB8CC");
2000
+ if (hasTitle && hasBody) {
2001
+ const bodyContent = await readBodyInput(opts);
2002
+ startSpinner("\uC704\uD0A4 \uD398\uC774\uC9C0 \uC218\uC815 \uC911...");
2003
+ await client.updateWikiPage(wikiId, pageId, {
2004
+ subject: opts.title,
2005
+ body: { mimeType: "text/x-markdown", content: bodyContent }
2006
+ });
2007
+ } else if (hasTitle) {
2008
+ startSpinner("\uC704\uD0A4 \uD398\uC774\uC9C0 \uC81C\uBAA9 \uC218\uC815 \uC911...");
2009
+ await client.updateWikiPageTitle(wikiId, pageId, { subject: opts.title });
2010
+ } else {
2011
+ const bodyContent = await readBodyInput(opts);
2012
+ startSpinner("\uC704\uD0A4 \uD398\uC774\uC9C0 \uBCF8\uBB38 \uC218\uC815 \uC911...");
2013
+ await client.updateWikiPageContent(wikiId, pageId, {
2014
+ body: { mimeType: "text/x-markdown", content: bodyContent }
2015
+ });
2016
+ }
1794
2017
  stopSpinner(true, "\uC704\uD0A4 \uD398\uC774\uC9C0 \uC218\uC815 \uC644\uB8CC");
1795
2018
  process.stdout.write(`\uC704\uD0A4 \uD398\uC774\uC9C0\uAC00 \uC218\uC815\uB418\uC5C8\uC2B5\uB2C8\uB2E4: ${pageId}
1796
2019
  `);
1797
2020
  });
1798
2021
 
1799
2022
  // src/commands/mail/list.ts
1800
- var import_commander28 = require("commander");
2023
+ var import_commander29 = require("commander");
1801
2024
 
1802
2025
  // src/api/imapClient.ts
1803
2026
  var import_imapflow = require("imapflow");
@@ -1904,8 +2127,8 @@ async function getMail(config, uid) {
1904
2127
  }
1905
2128
 
1906
2129
  // src/commands/mail/list.ts
1907
- var import_chalk4 = __toESM(require("chalk"));
1908
- var mailListCommand = new import_commander28.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) => {
2130
+ var import_chalk5 = __toESM(require("chalk"));
2131
+ var mailListCommand = new import_commander29.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) => {
1909
2132
  const globalOpts = mailListCommand.optsWithGlobals();
1910
2133
  const config = await getConfigOrThrow();
1911
2134
  startSpinner("\uBA54\uC77C \uC870\uD68C \uC911...");
@@ -1919,7 +2142,7 @@ var mailListCommand = new import_commander28.Command("list").description("\uBA54
1919
2142
  headers: ["UID", "\uC77D\uC74C", "\uB0A0\uC9DC", "\uBCF4\uB0B8\uC0AC\uB78C", "\uC81C\uBAA9"],
1920
2143
  rows: mails.map((m) => [
1921
2144
  String(m.uid),
1922
- m.isRead ? "\u2713" : import_chalk4.default.red("\u2717"),
2145
+ m.isRead ? "\u2713" : import_chalk5.default.red("\u2717"),
1923
2146
  m.date ? m.date.toLocaleDateString("ko-KR") : "",
1924
2147
  m.from.replace(/<.*>/, "").trim() || m.from,
1925
2148
  m.subject
@@ -1937,9 +2160,9 @@ var mailListCommand = new import_commander28.Command("list").description("\uBA54
1937
2160
  });
1938
2161
 
1939
2162
  // src/commands/mail/get.ts
1940
- var import_commander29 = require("commander");
1941
- var import_chalk5 = __toESM(require("chalk"));
1942
- var mailGetCommand = new import_commander29.Command("get").description("\uBA54\uC77C \uC0C1\uC138 \uC870\uD68C").argument("<uid>", "\uBA54\uC77C UID").action(async (uid) => {
2163
+ var import_commander30 = require("commander");
2164
+ var import_chalk6 = __toESM(require("chalk"));
2165
+ var mailGetCommand = new import_commander30.Command("get").description("\uBA54\uC77C \uC0C1\uC138 \uC870\uD68C").argument("<uid>", "\uBA54\uC77C UID").action(async (uid) => {
1943
2166
  const globalOpts = mailGetCommand.optsWithGlobals();
1944
2167
  const config = await getConfigOrThrow();
1945
2168
  startSpinner("\uBA54\uC77C \uC870\uD68C \uC911...");
@@ -1957,11 +2180,11 @@ var mailGetCommand = new import_commander29.Command("get").description("\uBA54\u
1957
2180
  });
1958
2181
  } else {
1959
2182
  process.stdout.write(
1960
- `${import_chalk5.default.bold("\uC81C\uBAA9:")} ${mail.subject}
1961
- ${import_chalk5.default.bold("\uBCF4\uB0B8\uC0AC\uB78C:")} ${mail.from}
1962
- ${import_chalk5.default.bold("\uBC1B\uB294\uC0AC\uB78C:")} ${mail.to.join(", ")}
1963
- ${import_chalk5.default.bold("\uB0A0\uC9DC:")} ${mail.date?.toLocaleString("ko-KR") ?? ""}
1964
- ${import_chalk5.default.bold("\uC77D\uC74C:")} ${mail.isRead ? "\uC608" : "\uC544\uB2C8\uC624"}
2183
+ `${import_chalk6.default.bold("\uC81C\uBAA9:")} ${mail.subject}
2184
+ ${import_chalk6.default.bold("\uBCF4\uB0B8\uC0AC\uB78C:")} ${mail.from}
2185
+ ${import_chalk6.default.bold("\uBC1B\uB294\uC0AC\uB78C:")} ${mail.to.join(", ")}
2186
+ ${import_chalk6.default.bold("\uB0A0\uC9DC:")} ${mail.date?.toLocaleString("ko-KR") ?? ""}
2187
+ ${import_chalk6.default.bold("\uC77D\uC74C:")} ${mail.isRead ? "\uC608" : "\uC544\uB2C8\uC624"}
1965
2188
 
1966
2189
  ${mail.body}
1967
2190
  `
@@ -1970,8 +2193,8 @@ ${mail.body}
1970
2193
  });
1971
2194
 
1972
2195
  // src/commands/mail/send.ts
1973
- var import_commander30 = require("commander");
1974
- var import_promises12 = require("fs/promises");
2196
+ var import_commander31 = require("commander");
2197
+ var import_promises10 = require("fs/promises");
1975
2198
 
1976
2199
  // src/api/smtpClient.ts
1977
2200
  var import_nodemailer = __toESM(require("nodemailer"));
@@ -2020,12 +2243,12 @@ async function sendMail(config, opts) {
2020
2243
  }
2021
2244
 
2022
2245
  // src/commands/mail/send.ts
2023
- var mailSendCommand = new import_commander30.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) => {
2246
+ var mailSendCommand = new import_commander31.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) => {
2024
2247
  const globalOpts = mailSendCommand.optsWithGlobals();
2025
2248
  const config = await getConfigOrThrow();
2026
2249
  let body = opts.body ?? "";
2027
2250
  if (opts.bodyFile) {
2028
- body = await (0, import_promises12.readFile)(opts.bodyFile, "utf-8");
2251
+ body = await (0, import_promises10.readFile)(opts.bodyFile, "utf-8");
2029
2252
  }
2030
2253
  if (!body) {
2031
2254
  process.stderr.write("\uC624\uB958: --body \uB610\uB294 --body-file\uC744 \uC9C0\uC815\uD558\uC138\uC694\n");
@@ -2055,8 +2278,8 @@ var mailSendCommand = new import_commander30.Command("send").description("\uBA54
2055
2278
  });
2056
2279
 
2057
2280
  // src/commands/mail/reply.ts
2058
- var import_commander31 = require("commander");
2059
- var import_promises13 = require("fs/promises");
2281
+ var import_commander32 = require("commander");
2282
+ var import_promises11 = require("fs/promises");
2060
2283
  var import_imapflow2 = require("imapflow");
2061
2284
  async function getMessageId(config, uid) {
2062
2285
  const imap = getImapConfigOrThrow(config);
@@ -2083,12 +2306,12 @@ async function getMessageId(config, uid) {
2083
2306
  await client.logout();
2084
2307
  }
2085
2308
  }
2086
- var mailReplyCommand = new import_commander31.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) => {
2309
+ var mailReplyCommand = new import_commander32.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) => {
2087
2310
  const globalOpts = mailReplyCommand.optsWithGlobals();
2088
2311
  const config = await getConfigOrThrow();
2089
2312
  let body = opts.body ?? "";
2090
2313
  if (opts.bodyFile) {
2091
- body = await (0, import_promises13.readFile)(opts.bodyFile, "utf-8");
2314
+ body = await (0, import_promises11.readFile)(opts.bodyFile, "utf-8");
2092
2315
  }
2093
2316
  if (!body) {
2094
2317
  process.stderr.write("\uC624\uB958: --body \uB610\uB294 --body-file\uC744 \uC9C0\uC815\uD558\uC138\uC694\n");
@@ -2124,19 +2347,19 @@ var mailReplyCommand = new import_commander31.Command("reply").description("\uBA
2124
2347
  });
2125
2348
 
2126
2349
  // src/index.ts
2127
- var program = new import_commander32.Command();
2128
- program.name("dooray").description("Dooray REST API CLI").version("0.3.1").option("--json", "JSON \uD615\uC2DD\uC73C\uB85C \uCD9C\uB825").option("--quiet", "ID\uB9CC \uCD9C\uB825").option("--no-color", "\uC0C9\uC0C1 \uBE44\uD65C\uC131\uD654");
2350
+ var program = new import_commander33.Command();
2351
+ program.name("dooray").description("Dooray REST API CLI").version("0.5.2").option("--json", "JSON \uD615\uC2DD\uC73C\uB85C \uCD9C\uB825").option("--quiet", "ID\uB9CC \uCD9C\uB825").option("--no-color", "\uC0C9\uC0C1 \uBE44\uD65C\uC131\uD654");
2129
2352
  program.hook("preAction", () => {
2130
2353
  const opts = program.opts();
2131
2354
  if (opts.color === false || process.env.NO_COLOR) {
2132
- import_chalk6.default.level = 0;
2355
+ import_chalk7.default.level = 0;
2133
2356
  }
2134
2357
  });
2135
- var projectCommand = new import_commander32.Command("project").description("\uD504\uB85C\uC81D\uD2B8 \uAD00\uB828 \uBA85\uB839");
2358
+ var projectCommand = new import_commander33.Command("project").description("\uD504\uB85C\uC81D\uD2B8 \uAD00\uB828 \uBA85\uB839");
2136
2359
  projectCommand.addCommand(projectListCommand);
2137
2360
  projectCommand.addCommand(projectMembersCommand);
2138
2361
  projectCommand.addCommand(projectWorkflowsCommand);
2139
- var postCommand = new import_commander32.Command("post").description("\uC5C5\uBB34 \uAD00\uB828 \uBA85\uB839");
2362
+ var postCommand = new import_commander33.Command("post").description("\uC5C5\uBB34 \uAD00\uB828 \uBA85\uB839");
2140
2363
  postCommand.addCommand(postListCommand);
2141
2364
  postCommand.addCommand(postSearchCommand);
2142
2365
  postCommand.addCommand(postGetCommand);
@@ -2144,32 +2367,33 @@ postCommand.addCommand(postEditCommand);
2144
2367
  postCommand.addCommand(postCreateCommand);
2145
2368
  postCommand.addCommand(postDoneCommand);
2146
2369
  postCommand.addCommand(postWorkflowCommand);
2147
- var commentCommand = new import_commander32.Command("comment").description("\uB313\uAE00 \uAD00\uB828 \uBA85\uB839");
2370
+ var commentCommand = new import_commander33.Command("comment").description("\uB313\uAE00 \uAD00\uB828 \uBA85\uB839");
2148
2371
  commentCommand.addCommand(commentListCommand);
2149
2372
  commentCommand.addCommand(commentAddCommand);
2150
2373
  commentCommand.addCommand(commentEditCommand);
2151
2374
  commentCommand.addCommand(commentDeleteCommand);
2152
2375
  postCommand.addCommand(commentCommand);
2153
- var fileCommand = new import_commander32.Command("file").description("\uCCA8\uBD80\uD30C\uC77C \uAD00\uB828 \uBA85\uB839");
2376
+ var fileCommand = new import_commander33.Command("file").description("\uCCA8\uBD80\uD30C\uC77C \uAD00\uB828 \uBA85\uB839");
2154
2377
  fileCommand.addCommand(fileListCommand);
2155
2378
  fileCommand.addCommand(fileDownloadCommand);
2156
2379
  fileCommand.addCommand(fileDownloadAllCommand);
2157
2380
  fileCommand.addCommand(fileUploadCommand);
2158
2381
  fileCommand.addCommand(fileDeleteCommand);
2159
2382
  postCommand.addCommand(fileCommand);
2160
- var wikiCommand = new import_commander32.Command("wiki").description("\uC704\uD0A4 \uAD00\uB828 \uBA85\uB839");
2383
+ var wikiCommand = new import_commander33.Command("wiki").description("\uC704\uD0A4 \uAD00\uB828 \uBA85\uB839");
2161
2384
  wikiCommand.addCommand(wikiListCommand);
2162
2385
  wikiCommand.addCommand(wikiPagesCommand);
2163
- var wikiPageCommand = new import_commander32.Command("page").description("\uC704\uD0A4 \uD398\uC774\uC9C0 \uAD00\uB828 \uBA85\uB839");
2386
+ var wikiPageCommand = new import_commander33.Command("page").description("\uC704\uD0A4 \uD398\uC774\uC9C0 \uAD00\uB828 \uBA85\uB839");
2164
2387
  wikiPageCommand.addCommand(wikiPageGetCommand);
2165
2388
  wikiPageCommand.addCommand(wikiPageCreateCommand);
2166
2389
  wikiPageCommand.addCommand(wikiPageEditCommand);
2167
2390
  wikiCommand.addCommand(wikiPageCommand);
2168
- var mailCommand = new import_commander32.Command("mail").description("\uBA54\uC77C \uAD00\uB828 \uBA85\uB839");
2391
+ var mailCommand = new import_commander33.Command("mail").description("\uBA54\uC77C \uAD00\uB828 \uBA85\uB839");
2169
2392
  mailCommand.addCommand(mailListCommand);
2170
2393
  mailCommand.addCommand(mailGetCommand);
2171
2394
  mailCommand.addCommand(mailSendCommand);
2172
2395
  mailCommand.addCommand(mailReplyCommand);
2396
+ program.addCommand(setupCommand);
2173
2397
  program.addCommand(configCommand);
2174
2398
  program.addCommand(cacheCommand);
2175
2399
  program.addCommand(doctorCommand);
@@ -2179,9 +2403,9 @@ program.addCommand(wikiCommand);
2179
2403
  program.addCommand(mailCommand);
2180
2404
  program.parseAsync().catch((err) => {
2181
2405
  if (err instanceof DoorayCliError) {
2182
- process.stderr.write(import_chalk6.default.red(`\uC624\uB958: ${err.message}`) + "\n");
2406
+ process.stderr.write(import_chalk7.default.red(`\uC624\uB958: ${err.message}`) + "\n");
2183
2407
  process.exit(err.exitCode);
2184
2408
  }
2185
- process.stderr.write(import_chalk6.default.red(`\uC624\uB958: ${err.message}`) + "\n");
2409
+ process.stderr.write(import_chalk7.default.red(`\uC624\uB958: ${err.message}`) + "\n");
2186
2410
  process.exit(1);
2187
2411
  });