@bifos/dooray-cli 0.15.1 → 0.16.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 +131 -656
- package/dist/index.js +97 -50
- package/package.json +1 -1
- package/skills/dooray-cli/SKILL.md +204 -47
- package/skills/dooray-cli/references/comment.md +21 -17
- package/skills/dooray-cli/references/common.md +22 -20
- package/skills/dooray-cli/references/mention-link.md +49 -73
- package/skills/dooray-cli/references/post.md +76 -149
- package/skills/dooray-cli/references/wiki.md +32 -64
- package/skills/dooray-cli/references/workflow.md +24 -63
- package/skills/dooray-cli/references/intent-map.md +0 -92
package/dist/index.js
CHANGED
|
@@ -385,7 +385,7 @@ var import_node_path3 = __toESM(require("path"));
|
|
|
385
385
|
var import_node_os3 = require("os");
|
|
386
386
|
|
|
387
387
|
// src/version.ts
|
|
388
|
-
var CLI_VERSION = true ? "0.
|
|
388
|
+
var CLI_VERSION = true ? "0.16.0" : "0.0.0-dev";
|
|
389
389
|
|
|
390
390
|
// src/skill/context.ts
|
|
391
391
|
function resolveSkillDataRoot(homeDir, xdgDataHome = process.env.XDG_DATA_HOME) {
|
|
@@ -2300,7 +2300,7 @@ async function resolveMemberGroup(client, projectId, input2) {
|
|
|
2300
2300
|
}
|
|
2301
2301
|
const adapter = valid.map((g) => ({ name: g.code, id: g.id, code: g.code }));
|
|
2302
2302
|
const match = matchByName(adapter, input2, "\uADF8\uB8F9", (g) => `${g.code} (${g.id})`, {
|
|
2303
|
-
helpHint: "\uC804\uCCB4 \uBAA9\uB85D: `dooray project groups <project>` / id \uC9C1\uC811 \uC785\uB825\uB3C4 \uAC00\uB2A5 (15+\uC790\uB9AC numeric \u2014 code \uB204\uB77D \uADF8\uB8F9\uB3C4 \uB9E4\uCE6D
|
|
2303
|
+
helpHint: "\uC804\uCCB4 \uBAA9\uB85D: `dooray project groups <project>` / id \uC9C1\uC811 \uC785\uB825\uB3C4 \uAC00\uB2A5 (15+\uC790\uB9AC numeric \u2014 code \uB204\uB77D \uADF8\uB8F9\uB3C4 \uB9E4\uCE6D)"
|
|
2304
2304
|
});
|
|
2305
2305
|
return { id: match.id, code: match.code };
|
|
2306
2306
|
}
|
|
@@ -3235,6 +3235,7 @@ var postEditCommand = new import_commander15.Command("edit").description("\uC5C5
|
|
|
3235
3235
|
const toGroups = (opts.toGroup ?? []).filter((s) => s.length > 0);
|
|
3236
3236
|
const tagAdditions = (opts.tag ?? []).filter((s) => s.length > 0);
|
|
3237
3237
|
const tagRemovals = (opts.tagRemove ?? []).filter((s) => s.length > 0);
|
|
3238
|
+
const hasParticipantChange = ccNames.length > 0 || ccGroups.length > 0 || !!opts.ccClear || toNames.length > 0 || toGroups.length > 0 || !!opts.toClear;
|
|
3238
3239
|
const hasTagChange = tagAdditions.length > 0 || tagRemovals.length > 0 || !!opts.tagClear;
|
|
3239
3240
|
startSpinner("\uC5C5\uBB34 \uC870\uD68C \uC911...");
|
|
3240
3241
|
const { projectId, postId, postNumber, projectCode } = await resolvePostInput(client, {
|
|
@@ -3253,7 +3254,7 @@ var postEditCommand = new import_commander15.Command("edit").description("\uC5C5
|
|
|
3253
3254
|
"\u26A0 --subject\uB294 deprecated\uC785\uB2C8\uB2E4. \uB300\uC2E0 --title\uC744 \uC0AC\uC6A9\uD574\uC8FC\uC138\uC694.\n"
|
|
3254
3255
|
);
|
|
3255
3256
|
}
|
|
3256
|
-
const nonInteractive = title || opts.body || opts.bodyFile || hasTagChange;
|
|
3257
|
+
const nonInteractive = title || opts.body || opts.bodyFile || hasTagChange || hasParticipantChange;
|
|
3257
3258
|
if (nonInteractive) {
|
|
3258
3259
|
let newBody = await readBodyInputOrNull(opts);
|
|
3259
3260
|
if (newBody != null && !opts.dryRun) {
|
|
@@ -3368,11 +3369,6 @@ var postEditCommand = new import_commander15.Command("edit").description("\uC5C5
|
|
|
3368
3369
|
"\u26A0 --link-task \uB294 --title/--body \uC640 \uD568\uAED8 \uC0AC\uC6A9 \uC2DC\uC5D0\uB9CC \uC801\uC6A9\uB429\uB2C8\uB2E4.\n"
|
|
3369
3370
|
);
|
|
3370
3371
|
}
|
|
3371
|
-
if (ccNames.length > 0 || ccGroups.length > 0 || opts.ccClear || toNames.length > 0 || toGroups.length > 0 || opts.toClear) {
|
|
3372
|
-
process.stderr.write(
|
|
3373
|
-
"\u26A0 --cc/--cc-group/--cc-clear/--to/--to-group/--to-clear \uB294 --title/--body \uC640 \uD568\uAED8 \uC0AC\uC6A9 \uC2DC\uC5D0\uB9CC \uC801\uC6A9\uB429\uB2C8\uB2E4.\n"
|
|
3374
|
-
);
|
|
3375
|
-
}
|
|
3376
3372
|
if (opts.parent) {
|
|
3377
3373
|
process.stderr.write(
|
|
3378
3374
|
"\u26A0 --parent \uB294 --title/--body \uC640 \uD568\uAED8 \uC0AC\uC6A9 \uC2DC\uC5D0\uB9CC \uC801\uC6A9\uB429\uB2C8\uB2E4.\n"
|
|
@@ -3451,7 +3447,7 @@ function postUserToCreate(u) {
|
|
|
3451
3447
|
group: u.group
|
|
3452
3448
|
};
|
|
3453
3449
|
}
|
|
3454
|
-
var postCreateCommand = new import_commander16.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("--to-group <code>", "\uB2F4\uB2F9\uC790(to) \uADF8\uB8F9 \uCD94\uAC00 (\uBC18\uBCF5 \uAC00\uB2A5, \uADF8\uB8F9 \uCF54\uB4DC \uBD80\uBD84\uC77C\uCE58)", (v, prev) => [...prev, v], []).option("--cc <members...>", "\uCC38\uC870\uC790 (\uC774\uB984 \uB610\uB294 \uC774\uBA54\uC77C, \uC5EC\uB7EC \uBA85 \uAC00\uB2A5)").option("--cc-group <code>", "\uCC38\uC870\uC790(cc) \uADF8\uB8F9 \uCD94\uAC00 (\uBC18\uBCF5 \uAC00\uB2A5, \uADF8\uB8F9 \uCF54\uB4DC \uBD80\uBD84\uC77C\uCE58)", (v, prev) => [...prev, v], []).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("--template <ref>", "\uD15C\uD50C\uB9BF \uC774\uB984 \uB610\uB294 ID \u2014 body/users/tags \uC790\uB3D9 \uCC44\uC6C0 (\uC0AC\uC6A9\uC790 \uC635\uC158 \uC6B0\uC120
|
|
3450
|
+
var postCreateCommand = new import_commander16.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("--to-group <code>", "\uB2F4\uB2F9\uC790(to) \uADF8\uB8F9 \uCD94\uAC00 (\uBC18\uBCF5 \uAC00\uB2A5, \uADF8\uB8F9 \uCF54\uB4DC \uBD80\uBD84\uC77C\uCE58)", (v, prev) => [...prev, v], []).option("--cc <members...>", "\uCC38\uC870\uC790 (\uC774\uB984 \uB610\uB294 \uC774\uBA54\uC77C, \uC5EC\uB7EC \uBA85 \uAC00\uB2A5)").option("--cc-group <code>", "\uCC38\uC870\uC790(cc) \uADF8\uB8F9 \uCD94\uAC00 (\uBC18\uBCF5 \uAC00\uB2A5, \uADF8\uB8F9 \uCF54\uB4DC \uBD80\uBD84\uC77C\uCE58)", (v, prev) => [...prev, v], []).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("--template <ref>", "\uD15C\uD50C\uB9BF \uC774\uB984 \uB610\uB294 ID \u2014 body/users/tags \uC790\uB3D9 \uCC44\uC6C0 (\uC0AC\uC6A9\uC790 \uC635\uC158 \uC6B0\uC120)").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) => {
|
|
3455
3451
|
const globalOpts = postCreateCommand.optsWithGlobals();
|
|
3456
3452
|
const config = await getConfigOrThrow();
|
|
3457
3453
|
const client = new DoorayApiClient(config.apiKey, config.baseUrl);
|
|
@@ -4034,7 +4030,36 @@ var commentEditCommand = new import_commander22.Command("edit").description("\uB
|
|
|
4034
4030
|
|
|
4035
4031
|
// src/commands/post/comment/delete.ts
|
|
4036
4032
|
var import_commander23 = require("commander");
|
|
4037
|
-
|
|
4033
|
+
|
|
4034
|
+
// src/utils/delete-confirmation.ts
|
|
4035
|
+
async function authorizeDeletion(skipConfirmation, isTTY, confirmDeletion) {
|
|
4036
|
+
if (skipConfirmation) {
|
|
4037
|
+
return true;
|
|
4038
|
+
}
|
|
4039
|
+
if (!isTTY) {
|
|
4040
|
+
throw new DoorayCliError(
|
|
4041
|
+
"non-TTY \uD658\uACBD\uC5D0\uC11C\uB294 \uC0AD\uC81C \uD655\uC778\uC744 \uC9C4\uD589\uD560 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4. --yes(-y) \uD50C\uB798\uADF8\uB85C \uB2E4\uC2DC \uC2E4\uD589\uD558\uC138\uC694.",
|
|
4042
|
+
EXIT_PARAM_ERROR
|
|
4043
|
+
);
|
|
4044
|
+
}
|
|
4045
|
+
return confirmDeletion();
|
|
4046
|
+
}
|
|
4047
|
+
async function promptDeletion(message) {
|
|
4048
|
+
const { confirm: confirm2 } = await import("@inquirer/prompts");
|
|
4049
|
+
return confirm2({ message, default: false });
|
|
4050
|
+
}
|
|
4051
|
+
|
|
4052
|
+
// src/commands/post/comment/delete.ts
|
|
4053
|
+
var commentDeleteCommand = new import_commander23.Command("delete").description("\uB313\uAE00 \uC0AD\uC81C").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("-y, --yes", "\uD655\uC778 \uC5C6\uC774 \uC0AD\uC81C (\uC790\uB3D9\uD654\uC6A9)").action(async (arg1, arg2, arg3, opts) => {
|
|
4054
|
+
const confirmed = await authorizeDeletion(
|
|
4055
|
+
!!opts.yes,
|
|
4056
|
+
!!process.stdin.isTTY,
|
|
4057
|
+
() => promptDeletion("\uC5C5\uBB34 \uB313\uAE00\uC744 \uC601\uAD6C \uC0AD\uC81C\uD560\uAE4C\uC694?")
|
|
4058
|
+
);
|
|
4059
|
+
if (!confirmed) {
|
|
4060
|
+
process.stderr.write("\uCDE8\uC18C\uB418\uC5C8\uC2B5\uB2C8\uB2E4.\n");
|
|
4061
|
+
return;
|
|
4062
|
+
}
|
|
4038
4063
|
const config = await getConfigOrThrow();
|
|
4039
4064
|
const client = new DoorayApiClient(config.apiKey, config.baseUrl);
|
|
4040
4065
|
let projectArg;
|
|
@@ -4315,9 +4340,11 @@ var import_commander26 = require("commander");
|
|
|
4315
4340
|
var import_node_path7 = require("path");
|
|
4316
4341
|
|
|
4317
4342
|
// src/utils/comment-files.ts
|
|
4343
|
+
var IMAGE_FILE_EXTENSION_RE = /\.(png|jpe?g|gif|webp|bmp|svg|avif|heic)$/i;
|
|
4318
4344
|
function appendFileReference(body, fileName, fileId) {
|
|
4319
4345
|
const safeName = fileName.replace(/[\[\]]/g, "");
|
|
4320
|
-
const
|
|
4346
|
+
const prefix = IMAGE_FILE_EXTENSION_RE.test(safeName) ? "!" : "";
|
|
4347
|
+
const ref = `${prefix}[${safeName}](/files/${fileId})`;
|
|
4321
4348
|
if (body.length === 0) return ref;
|
|
4322
4349
|
const trailing = body.endsWith("\n") ? "" : "\n";
|
|
4323
4350
|
return `${body}${trailing}
|
|
@@ -4325,14 +4352,14 @@ ${ref}`;
|
|
|
4325
4352
|
}
|
|
4326
4353
|
function removeFileReference(body, fileId) {
|
|
4327
4354
|
const escaped = fileId.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
4328
|
-
const refSource =
|
|
4355
|
+
const refSource = `!?\\[[^\\]]*\\]\\(/files/${escaped}\\)`;
|
|
4329
4356
|
const lineRe = new RegExp(`^[ \\t]*${refSource}[ \\t]*$\\n?`, "gm");
|
|
4330
4357
|
const inlineRe = new RegExp(refSource, "g");
|
|
4331
4358
|
return body.replace(lineRe, "").replace(inlineRe, "");
|
|
4332
4359
|
}
|
|
4333
4360
|
|
|
4334
4361
|
// src/commands/post/comment/file/upload.ts
|
|
4335
|
-
var uploadCommentFileCommand = new import_commander26.Command("upload").description("\uB313\uAE00\uC5D0 \uD30C\uC77C \uC5C5\uB85C\uB4DC (
|
|
4362
|
+
var uploadCommentFileCommand = new import_commander26.Command("upload").description("\uB313\uAE00\uC5D0 \uD30C\uC77C \uC5C5\uB85C\uB4DC (\uBCF8\uBB38\uC5D0 reference \uC790\uB3D9 \uCD94\uAC00)").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) => {
|
|
4336
4363
|
const globalOpts = uploadCommentFileCommand.optsWithGlobals();
|
|
4337
4364
|
const config = await getConfigOrThrow();
|
|
4338
4365
|
const client = new DoorayApiClient(config.apiKey, config.baseUrl);
|
|
@@ -4413,7 +4440,18 @@ var downloadCommentFileCommand = new import_commander27.Command("download").desc
|
|
|
4413
4440
|
|
|
4414
4441
|
// src/commands/post/comment/file/delete.ts
|
|
4415
4442
|
var import_commander28 = require("commander");
|
|
4416
|
-
var deleteCommentFileCommand = new import_commander28.Command("delete").description("\uB313\uAE00 \uCCA8\uBD80 \uD30C\uC77C \uC0AD\uC81C (\
|
|
4443
|
+
var deleteCommentFileCommand = new import_commander28.Command("delete").description("\uB313\uAE00 \uCCA8\uBD80 \uD30C\uC77C \uC0AD\uC81C (\uBCF8\uBB38 reference \uC81C\uAC70\uC640 \uD30C\uC77C \uC0AD\uC81C\uB97C \uD568\uAED8 \uC218\uD589)").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("-y, --yes", "\uD655\uC778 \uC5C6\uC774 \uC0AD\uC81C (\uC790\uB3D9\uD654\uC6A9)").action(async (arg1, arg2, arg3, arg4, opts) => {
|
|
4444
|
+
const confirmed = await authorizeDeletion(
|
|
4445
|
+
!!opts.yes,
|
|
4446
|
+
!!process.stdin.isTTY,
|
|
4447
|
+
() => promptDeletion(
|
|
4448
|
+
"\uB313\uAE00 \uBCF8\uBB38\uC5D0\uC11C \uD30C\uC77C reference\uB97C \uC81C\uAC70\uD558\uACE0 \uCCA8\uBD80 \uD30C\uC77C\uC744 \uC0AD\uC81C\uD569\uB2C8\uB2E4. \uAC19\uC740 \uC5C5\uBB34\uC758 \uB2E4\uB978 \uB313\uAE00\uC774 \uAC19\uC740 \uD30C\uC77C ID\uB97C \uCC38\uC870\uD558\uBA74 \uB9C1\uD06C\uAC00 \uAE68\uC9C8 \uC218 \uC788\uC2B5\uB2C8\uB2E4. \uACC4\uC18D\uD558\uC2DC\uACA0\uC2B5\uB2C8\uAE4C?"
|
|
4449
|
+
)
|
|
4450
|
+
);
|
|
4451
|
+
if (!confirmed) {
|
|
4452
|
+
process.stderr.write("\uCDE8\uC18C\uB418\uC5C8\uC2B5\uB2C8\uB2E4.\n");
|
|
4453
|
+
return;
|
|
4454
|
+
}
|
|
4417
4455
|
const config = await getConfigOrThrow();
|
|
4418
4456
|
const client = new DoorayApiClient(config.apiKey, config.baseUrl);
|
|
4419
4457
|
const { projectId, postId, commentId, secondary: fileId } = await resolveCommentFileInput(client, {
|
|
@@ -4428,16 +4466,6 @@ var deleteCommentFileCommand = new import_commander28.Command("delete").descript
|
|
|
4428
4466
|
requireSecondary: true,
|
|
4429
4467
|
secondaryLabel: FILE_ID_SECONDARY_LABEL
|
|
4430
4468
|
});
|
|
4431
|
-
if (!opts.yes) {
|
|
4432
|
-
const { confirm: confirm2 } = await import("@inquirer/prompts");
|
|
4433
|
-
const ok = await confirm2({
|
|
4434
|
-
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?`
|
|
4435
|
-
});
|
|
4436
|
-
if (!ok) {
|
|
4437
|
-
process.stdout.write("\uCDE8\uC18C\uB418\uC5C8\uC2B5\uB2C8\uB2E4.\n");
|
|
4438
|
-
return;
|
|
4439
|
-
}
|
|
4440
|
-
}
|
|
4441
4469
|
startSpinner("\uB313\uAE00 \uBCF8\uBB38 reference \uC81C\uAC70 \uC911...");
|
|
4442
4470
|
try {
|
|
4443
4471
|
const commentRes = await client.getPostComment(projectId, postId, commentId);
|
|
@@ -4470,7 +4498,7 @@ var deleteCommentFileCommand = new import_commander28.Command("delete").descript
|
|
|
4470
4498
|
});
|
|
4471
4499
|
|
|
4472
4500
|
// src/commands/post/comment/file/index.ts
|
|
4473
|
-
var commentFileCommand = new import_commander29.Command("file").description("\uB313\uAE00 \uCCA8\uBD80 \uD30C\uC77C \uAD00\uB9AC
|
|
4501
|
+
var commentFileCommand = new import_commander29.Command("file").description("\uB313\uAE00 \uCCA8\uBD80 \uD30C\uC77C \uAD00\uB9AC").addCommand(listCommentFileCommand).addCommand(uploadCommentFileCommand).addCommand(downloadCommentFileCommand).addCommand(deleteCommentFileCommand);
|
|
4474
4502
|
|
|
4475
4503
|
// src/commands/post/file/list.ts
|
|
4476
4504
|
var import_commander30 = require("commander");
|
|
@@ -4725,7 +4753,16 @@ var fileUploadCommand = new import_commander33.Command("upload").description("\u
|
|
|
4725
4753
|
|
|
4726
4754
|
// src/commands/post/file/delete.ts
|
|
4727
4755
|
var import_commander34 = require("commander");
|
|
4728
|
-
var fileDeleteCommand = new import_commander34.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) => {
|
|
4756
|
+
var fileDeleteCommand = new import_commander34.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)").option("-y, --yes", "\uD655\uC778 \uC5C6\uC774 \uC0AD\uC81C (\uC790\uB3D9\uD654\uC6A9)").action(async (arg1, arg2, arg3, opts) => {
|
|
4757
|
+
const confirmed = await authorizeDeletion(
|
|
4758
|
+
!!opts.yes,
|
|
4759
|
+
!!process.stdin.isTTY,
|
|
4760
|
+
() => promptDeletion("\uC5C5\uBB34\uC758 \uCCA8\uBD80 \uD30C\uC77C\uC744 \uC601\uAD6C \uC0AD\uC81C\uD560\uAE4C\uC694?")
|
|
4761
|
+
);
|
|
4762
|
+
if (!confirmed) {
|
|
4763
|
+
process.stderr.write("\uCDE8\uC18C\uB418\uC5C8\uC2B5\uB2C8\uB2E4.\n");
|
|
4764
|
+
return;
|
|
4765
|
+
}
|
|
4729
4766
|
const globalOpts = fileDeleteCommand.optsWithGlobals();
|
|
4730
4767
|
const config = await getConfigOrThrow();
|
|
4731
4768
|
const client = new DoorayApiClient(config.apiKey, config.baseUrl);
|
|
@@ -5057,7 +5094,7 @@ var wikiPageEditCommand = new import_commander40.Command("edit").description("\u
|
|
|
5057
5094
|
var import_commander41 = require("commander");
|
|
5058
5095
|
|
|
5059
5096
|
// src/resolvers/wiki-page-input.ts
|
|
5060
|
-
var INPUT_HELP2 = "\uC704\uD0A4 \uD398\uC774\uC9C0\uB97C \uC2DD\uBCC4\uD560 \uC815\uBCF4\uAC00 \uBD80\uC871\uD569\uB2C8\uB2E4. \uB2E4\uC74C \uC911 \uD558\uB098\uB97C \uC785\uB825\uD558\uC138\uC694:\n - <project> <page-id> \uC608: my-project
|
|
5097
|
+
var INPUT_HELP2 = "\uC704\uD0A4 \uD398\uC774\uC9C0\uB97C \uC2DD\uBCC4\uD560 \uC815\uBCF4\uAC00 \uBD80\uC871\uD569\uB2C8\uB2E4. \uB2E4\uC74C \uC911 \uD558\uB098\uB97C \uC785\uB825\uD558\uC138\uC694:\n - <project> <page-id> \uC608: my-project 9876543210987654321\n - --id <page-id> --project <project> (\uB610\uB294 --url)\n - <Dooray URL> \uC608: https://x.dooray.com/wiki/<wikiId>/<pageId>";
|
|
5061
5098
|
async function resolveWikiPageInput(client, args) {
|
|
5062
5099
|
const { projectArg, pageIdArg, idOpt, urlOpt, project } = args;
|
|
5063
5100
|
const hasPositional = !!projectArg || !!pageIdArg;
|
|
@@ -5112,6 +5149,17 @@ async function resolveWikiPageInput(client, args) {
|
|
|
5112
5149
|
|
|
5113
5150
|
// src/commands/wiki/page-delete.ts
|
|
5114
5151
|
var wikiPageDeleteCommand = new import_commander41.Command("delete").description("\uC704\uD0A4 \uD398\uC774\uC9C0 \uC0AD\uC81C (\uBE44\uACF5\uC2DD endpoint)").argument("[arg1]", "\uD504\uB85C\uC81D\uD2B8 \uCF54\uB4DC, Dooray Wiki URL, \uB610\uB294 (`--id`/`--url` \uBAA8\uB4DC\uC77C \uB54C) \uBBF8\uC0AC\uC6A9").argument("[arg2]", "page-id (positional 2\uAC1C \uBAA8\uB4DC)").option("--id <pageId>", "\uC704\uD0A4 \uD398\uC774\uC9C0 ID").option("--url <url>", "Dooray Wiki URL").option("--project <code>", "\uD504\uB85C\uC81D\uD2B8 \uCF54\uB4DC (--id \uBAA8\uB4DC\uC5D0\uC11C wikiId \uD574\uC11D\uC6A9)").option("-y, --yes", "\uD655\uC778 \uC5C6\uC774 \uC0AD\uC81C (\uC790\uB3D9\uD654\uC6A9)").action(async (arg1, arg2, opts) => {
|
|
5152
|
+
const confirmed = await authorizeDeletion(
|
|
5153
|
+
!!opts.yes,
|
|
5154
|
+
!!process.stdin.isTTY,
|
|
5155
|
+
() => promptDeletion(
|
|
5156
|
+
"\uC704\uD0A4 \uD398\uC774\uC9C0\uB97C \uC0AD\uC81C\uD560\uAE4C\uC694? \uD558\uC704 \uD398\uC774\uC9C0\uAC00 \uC788\uC73C\uBA74 \uC0AD\uC81C\uD55C \uD398\uC774\uC9C0\uC758 \uBD80\uBAA8 \uC544\uB798\uB85C \uC7AC\uBD80\uCC29\uB429\uB2C8\uB2E4."
|
|
5157
|
+
)
|
|
5158
|
+
);
|
|
5159
|
+
if (!confirmed) {
|
|
5160
|
+
process.stderr.write("\uCDE8\uC18C\uB418\uC5C8\uC2B5\uB2C8\uB2E4.\n");
|
|
5161
|
+
return;
|
|
5162
|
+
}
|
|
5115
5163
|
const globalOpts = wikiPageDeleteCommand.optsWithGlobals();
|
|
5116
5164
|
const config = await getConfigOrThrow();
|
|
5117
5165
|
const client = new DoorayApiClient(config.apiKey, config.baseUrl);
|
|
@@ -5122,25 +5170,6 @@ var wikiPageDeleteCommand = new import_commander41.Command("delete").description
|
|
|
5122
5170
|
urlOpt: opts.url,
|
|
5123
5171
|
project: opts.project
|
|
5124
5172
|
});
|
|
5125
|
-
if (!opts.yes) {
|
|
5126
|
-
if (!process.stdin.isTTY) {
|
|
5127
|
-
throw new DoorayCliError(
|
|
5128
|
-
"non-TTY \uD658\uACBD\uC5D0\uC11C\uB294 \uD655\uC778 \uC5C6\uC774 \uC0AD\uC81C\uD560 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4. --yes(-y) \uD50C\uB798\uADF8\uB85C \uB2E4\uC2DC \uC2E4\uD589\uD558\uC138\uC694.",
|
|
5129
|
-
EXIT_PARAM_ERROR
|
|
5130
|
-
);
|
|
5131
|
-
}
|
|
5132
|
-
const { confirm: confirm2 } = await import("@inquirer/prompts");
|
|
5133
|
-
const ok = await confirm2({
|
|
5134
|
-
message: `\uD398\uC774\uC9C0(${pageId})\uB97C \uC0AD\uC81C\uD560\uAE4C\uC694? \uD558\uC704 \uD398\uC774\uC9C0\uAC00 \uC788\uC73C\uBA74 \uC0C1\uC704 \uD398\uC774\uC9C0\uB85C \uC7AC\uBD80\uCC29\uB429\uB2C8\uB2E4.`,
|
|
5135
|
-
default: false
|
|
5136
|
-
});
|
|
5137
|
-
if (!ok) {
|
|
5138
|
-
if (!globalOpts.json && !globalOpts.quiet) {
|
|
5139
|
-
process.stdout.write("\uCDE8\uC18C\uB418\uC5C8\uC2B5\uB2C8\uB2E4.\n");
|
|
5140
|
-
}
|
|
5141
|
-
return;
|
|
5142
|
-
}
|
|
5143
|
-
}
|
|
5144
5173
|
startSpinner("\uD398\uC774\uC9C0 \uC0AD\uC81C \uC911...");
|
|
5145
5174
|
try {
|
|
5146
5175
|
await client.deleteWikiPage(wikiId, pageId);
|
|
@@ -5205,7 +5234,7 @@ function wikiInlineImageSnippet(wikiId, attachFileId, name) {
|
|
|
5205
5234
|
}
|
|
5206
5235
|
|
|
5207
5236
|
// src/commands/wiki/page-file/upload.ts
|
|
5208
|
-
var wikiPageFileUploadCommand = new import_commander43.Command("upload").description("\uC704\uD0A4 \uD398\uC774\uC9C0 \uCCA8\uBD80\uD30C\uC77C \uC5C5\uB85C\uB4DC
|
|
5237
|
+
var wikiPageFileUploadCommand = new import_commander43.Command("upload").description("\uC704\uD0A4 \uD398\uC774\uC9C0 \uCCA8\uBD80\uD30C\uC77C \uC5C5\uB85C\uB4DC").argument("[arg1]", "\uD504\uB85C\uC81D\uD2B8 \uCF54\uB4DC, Dooray Wiki URL, \uB610\uB294 (`--id`/`--url` \uBAA8\uB4DC\uC77C \uB54C) \uD30C\uC77C \uACBD\uB85C").argument("[arg2]", "page-id \uB610\uB294 (`--id`/`--url` \uBAA8\uB4DC\uC77C \uB54C) \uD30C\uC77C \uACBD\uB85C").argument("[arg3]", "\uD30C\uC77C \uACBD\uB85C (positional 3\uAC1C \uBAA8\uB4DC)").option("--id <pageId>", "\uC704\uD0A4 \uD398\uC774\uC9C0 ID").option("--url <url>", "Dooray Wiki URL").option("--project <code>", "\uD504\uB85C\uC81D\uD2B8 \uCF54\uB4DC (--id \uBAA8\uB4DC\uC5D0\uC11C wikiId \uD574\uC11D\uC6A9)").option("--file <path>", "\uC5C5\uB85C\uB4DC\uD560 \uD30C\uC77C \uACBD\uB85C (positional \uB300\uCCB4)").option("--type <type>", "\uD30C\uC77C \uD0C0\uC785: general | inline_image (\uAE30\uBCF8 general)", "general").action(async (arg1, arg2, arg3, opts) => {
|
|
5209
5238
|
const globalOpts = wikiPageFileUploadCommand.optsWithGlobals();
|
|
5210
5239
|
const config = await getConfigOrThrow();
|
|
5211
5240
|
const client = new DoorayApiClient(config.apiKey, config.baseUrl);
|
|
@@ -5426,7 +5455,16 @@ var wikiPageFileDownloadAllCommand = new import_commander45.Command("download-al
|
|
|
5426
5455
|
|
|
5427
5456
|
// src/commands/wiki/page-file/delete.ts
|
|
5428
5457
|
var import_commander46 = require("commander");
|
|
5429
|
-
var wikiPageFileDeleteCommand = new import_commander46.Command("delete").description("\uC704\uD0A4 \uD398\uC774\uC9C0 \uCCA8\uBD80\uD30C\uC77C \uC0AD\uC81C").argument("[arg1]", "\uD504\uB85C\uC81D\uD2B8 \uCF54\uB4DC, Dooray Wiki URL, \uB610\uB294 (`--id`/`--url` \uBAA8\uB4DC\uC77C \uB54C) \uD30C\uC77C ID").argument("[arg2]", "page-id \uB610\uB294 (`--id`/`--url` \uBAA8\uB4DC\uC77C \uB54C) \uD30C\uC77C ID").argument("[arg3]", "\uD30C\uC77C ID (positional 3\uAC1C \uBAA8\uB4DC)").option("--id <pageId>", "\uC704\uD0A4 \uD398\uC774\uC9C0 ID").option("--url <url>", "Dooray Wiki URL").option("--project <code>", "\uD504\uB85C\uC81D\uD2B8 \uCF54\uB4DC (--id \uBAA8\uB4DC\uC5D0\uC11C wikiId \uD574\uC11D\uC6A9)").option("--file-id <fileId>", "\uD30C\uC77C ID (positional \uB300\uCCB4)").action(async (arg1, arg2, arg3, opts) => {
|
|
5458
|
+
var wikiPageFileDeleteCommand = new import_commander46.Command("delete").description("\uC704\uD0A4 \uD398\uC774\uC9C0 \uCCA8\uBD80\uD30C\uC77C \uC0AD\uC81C").argument("[arg1]", "\uD504\uB85C\uC81D\uD2B8 \uCF54\uB4DC, Dooray Wiki URL, \uB610\uB294 (`--id`/`--url` \uBAA8\uB4DC\uC77C \uB54C) \uD30C\uC77C ID").argument("[arg2]", "page-id \uB610\uB294 (`--id`/`--url` \uBAA8\uB4DC\uC77C \uB54C) \uD30C\uC77C ID").argument("[arg3]", "\uD30C\uC77C ID (positional 3\uAC1C \uBAA8\uB4DC)").option("--id <pageId>", "\uC704\uD0A4 \uD398\uC774\uC9C0 ID").option("--url <url>", "Dooray Wiki URL").option("--project <code>", "\uD504\uB85C\uC81D\uD2B8 \uCF54\uB4DC (--id \uBAA8\uB4DC\uC5D0\uC11C wikiId \uD574\uC11D\uC6A9)").option("--file-id <fileId>", "\uD30C\uC77C ID (positional \uB300\uCCB4)").option("-y, --yes", "\uD655\uC778 \uC5C6\uC774 \uC0AD\uC81C (\uC790\uB3D9\uD654\uC6A9)").action(async (arg1, arg2, arg3, opts) => {
|
|
5459
|
+
const confirmed = await authorizeDeletion(
|
|
5460
|
+
!!opts.yes,
|
|
5461
|
+
!!process.stdin.isTTY,
|
|
5462
|
+
() => promptDeletion("\uC704\uD0A4 \uD398\uC774\uC9C0\uC758 \uCCA8\uBD80 \uD30C\uC77C\uC744 \uC601\uAD6C \uC0AD\uC81C\uD560\uAE4C\uC694?")
|
|
5463
|
+
);
|
|
5464
|
+
if (!confirmed) {
|
|
5465
|
+
process.stderr.write("\uCDE8\uC18C\uB418\uC5C8\uC2B5\uB2C8\uB2E4.\n");
|
|
5466
|
+
return;
|
|
5467
|
+
}
|
|
5430
5468
|
const globalOpts = wikiPageFileDeleteCommand.optsWithGlobals();
|
|
5431
5469
|
const config = await getConfigOrThrow();
|
|
5432
5470
|
const client = new DoorayApiClient(config.apiKey, config.baseUrl);
|
|
@@ -5485,7 +5523,7 @@ var wikiPageFileDeleteCommand = new import_commander46.Command("delete").descrip
|
|
|
5485
5523
|
});
|
|
5486
5524
|
|
|
5487
5525
|
// src/commands/wiki/page-file/index.ts
|
|
5488
|
-
var wikiPageFileCommand = new import_commander47.Command("file").description("\uC704\uD0A4 \uD398\uC774\uC9C0 \uCCA8\uBD80\uD30C\uC77C \uAD00\uB828 \uBA85\uB839
|
|
5526
|
+
var wikiPageFileCommand = new import_commander47.Command("file").description("\uC704\uD0A4 \uD398\uC774\uC9C0 \uCCA8\uBD80\uD30C\uC77C \uAD00\uB828 \uBA85\uB839");
|
|
5489
5527
|
wikiPageFileCommand.addCommand(wikiPageFileListCommand);
|
|
5490
5528
|
wikiPageFileCommand.addCommand(wikiPageFileUploadCommand);
|
|
5491
5529
|
wikiPageFileCommand.addCommand(wikiPageFileDownloadCommand);
|
|
@@ -5766,7 +5804,16 @@ var wikiPageCommentEditCommand = new import_commander52.Command("edit").descript
|
|
|
5766
5804
|
|
|
5767
5805
|
// src/commands/wiki/page-comment/delete.ts
|
|
5768
5806
|
var import_commander53 = require("commander");
|
|
5769
|
-
var wikiPageCommentDeleteCommand = new import_commander53.Command("delete").description("\uC704\uD0A4 \uD398\uC774\uC9C0 \uB313\uAE00 \uC0AD\uC81C
|
|
5807
|
+
var wikiPageCommentDeleteCommand = new import_commander53.Command("delete").description("\uC704\uD0A4 \uD398\uC774\uC9C0 \uB313\uAE00 \uC0AD\uC81C").argument("[arg1]", "\uD504\uB85C\uC81D\uD2B8 \uCF54\uB4DC / Dooray Wiki URL (\uBAA8\uB4DC\uBCC4)").argument("[arg2]", "\uC704\uD0A4 \uD398\uC774\uC9C0 ID (\uBAA8\uB4DC\uBCC4)").argument("[arg3]", "\uB313\uAE00 ID (positional 3\uAC1C \uBAA8\uB4DC)").option("--id <pageId>", "\uC704\uD0A4 \uD398\uC774\uC9C0 ID (positional \uB300\uC2E0)").option("--url <url>", "Dooray Wiki URL (positional \uB300\uC2E0)").option("--project <code>", "\uD504\uB85C\uC81D\uD2B8 \uCF54\uB4DC (--id \uBAA8\uB4DC\uC6A9)").option("--comment-id <commentId>", "\uB313\uAE00 ID (positional \uB300\uCCB4)").option("-y, --yes", "\uD655\uC778 \uC5C6\uC774 \uC0AD\uC81C (\uC790\uB3D9\uD654\uC6A9)").action(async (arg1, arg2, arg3, opts) => {
|
|
5808
|
+
const confirmed = await authorizeDeletion(
|
|
5809
|
+
!!opts.yes,
|
|
5810
|
+
!!process.stdin.isTTY,
|
|
5811
|
+
() => promptDeletion("\uC704\uD0A4 \uD398\uC774\uC9C0\uC758 \uB313\uAE00\uC744 \uC601\uAD6C \uC0AD\uC81C\uD560\uAE4C\uC694?")
|
|
5812
|
+
);
|
|
5813
|
+
if (!confirmed) {
|
|
5814
|
+
process.stderr.write("\uCDE8\uC18C\uB418\uC5C8\uC2B5\uB2C8\uB2E4.\n");
|
|
5815
|
+
return;
|
|
5816
|
+
}
|
|
5770
5817
|
const parsed = parseWikiCommentArgs(arg1, arg2, arg3, opts);
|
|
5771
5818
|
const config = await getConfigOrThrow();
|
|
5772
5819
|
const client = new DoorayApiClient(config.apiKey, config.baseUrl);
|
package/package.json
CHANGED
|
@@ -5,50 +5,207 @@ description: Dooray 업무 관리 CLI. 프로젝트/업무/댓글/위키 조회
|
|
|
5
5
|
|
|
6
6
|
# dooray-cli
|
|
7
7
|
|
|
8
|
-
NHN Dooray REST API를 래핑한 CLI
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
|
15
|
-
|
|
16
|
-
|
|
|
17
|
-
|
|
|
18
|
-
|
|
|
19
|
-
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
-
|
|
27
|
-
-
|
|
28
|
-
-
|
|
29
|
-
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
8
|
+
NHN Dooray REST API 를 래핑한 CLI 다. 이 파일은 라우터이므로, 작업 영역에 맞는 reference 를 먼저 읽는다.
|
|
9
|
+
|
|
10
|
+
## 어느 reference 를 읽을지
|
|
11
|
+
|
|
12
|
+
| 하려는 일 | reference |
|
|
13
|
+
| --- | --- |
|
|
14
|
+
| 설치·초기 설정, 출력 모드, API 제약, 에러 처리, 캐시, 피드백 등록 | [common.md](references/common.md) |
|
|
15
|
+
| 업무 식별·생성·수정·삭제, 참조자·담당자 변경, 첨부 보호, 부모 지정, 태그 | [post.md](references/post.md) |
|
|
16
|
+
| 업무 댓글 추가·필터·조회 | [comment.md](references/comment.md) |
|
|
17
|
+
| 위키 페이지 조회·트리·삭제, 첨부와 인라인 이미지, 위키 댓글 | [wiki.md](references/wiki.md) |
|
|
18
|
+
| 그룹 멘션·cc 판단, 멘션·링크 자동 삽입, Dooray 마크다운 링크 | [mention-link.md](references/mention-link.md) |
|
|
19
|
+
| 워크플로우 판단 기준, 정형 task 자동화, 명령 체이닝 | [workflow.md](references/workflow.md) |
|
|
20
|
+
|
|
21
|
+
## 대상 지정 방법
|
|
22
|
+
|
|
23
|
+
`post get`/`edit`/`done`/`workflow`, `post comment` 전체, `post file` 전체, `post comment file` 전체,
|
|
24
|
+
`wiki page file` 과 `wiki page comment` 전체, 그리고 `wiki page delete` 가 네 가지 형태를 모두 받는다.
|
|
25
|
+
|
|
26
|
+
- `<project> <number>` — 업무는 번호, 위키는 `<project> <page-id>`
|
|
27
|
+
- `--id <postId>` / `--id <pageId>` — 위키는 `--project` 를 함께 줘야 한다 (API 가 page 단독 조회를 지원하지 않는다)
|
|
28
|
+
- `--url <url>`
|
|
29
|
+
- 첫 인자에 Dooray URL 을 직접
|
|
30
|
+
|
|
31
|
+
받아들이는 URL 형식은 셋이다.
|
|
32
|
+
|
|
33
|
+
- `https://*.dooray.com/task/to/<postId>`
|
|
34
|
+
- `https://*.dooray.com/task/<projectId>/<postId>` — 브라우저 주소창 복사본
|
|
35
|
+
- `https://*.dooray.com/project/tasks/<postId>` — 업무 목록에서 업무를 열었을 때
|
|
36
|
+
|
|
37
|
+
## 실행 규칙
|
|
38
|
+
|
|
39
|
+
- 사용자가 Dooray URL 을 줬으면 그대로 첫 인자로 넘긴다 — resolve 단계를 건너뛰어 가장 빠르다
|
|
40
|
+
- 구조화 결과가 필요하면 `--json`, 다음 명령에 ID 만 넘길 때는 `--quiet` 를 쓴다
|
|
41
|
+
- 조회는 `--json` 으로 먼저 실행해 응답 구조를 확인한 뒤 쓰기 명령으로 넘어간다
|
|
42
|
+
- 쓰기 명령은 대상 ID 를 명시하고, 지원하면 `--dry-run` 으로 먼저 확인한다
|
|
43
|
+
- 이름 기반 조회(멤버·그룹·워크플로우·태그)는 부분일치를 지원한다. 모호하면 에러와 후보 목록이 나오므로 임의로 고르지 말고 사용자에게 확인한다
|
|
44
|
+
- 실패하면 [common.md](references/common.md) 의 에러 처리 표와 대조한다
|
|
45
|
+
|
|
46
|
+
## 파일 명령의 `--json` 스키마
|
|
47
|
+
|
|
48
|
+
`post file` 과 `wiki page file` 이 같은 스키마를 쓴다. 한쪽 파싱 코드를 다른 쪽에 그대로 쓸 수 있다.
|
|
49
|
+
|
|
50
|
+
| 명령 | `--json` | `--quiet` |
|
|
51
|
+
| --- | --- | --- |
|
|
52
|
+
| `upload` | API 응답의 `result` 원형 | `id` |
|
|
53
|
+
| `download` | `{outputPath, fileName, size}` | `outputPath` |
|
|
54
|
+
| `download-all` | `{count, succeeded: [{path, fileName}], failed: [{fileId, error}]}` | — |
|
|
55
|
+
| `delete` | `{fileId, status: "deleted"}` | `fileId` |
|
|
56
|
+
|
|
57
|
+
`download-all` 은 일부만 실패해도 나머지를 계속 내려받고 **종료 코드 1** 을 반환한다.
|
|
58
|
+
성공과 실패를 갈라 처리해야 하므로 종료 코드만 보고 전체 실패로 판단하지 않는다.
|
|
59
|
+
|
|
60
|
+
`wiki page file upload --type inline_image` 는 `--json` 에 `markdownSnippet` 이 더 붙는다.
|
|
61
|
+
본문에 그대로 넣을 수 있는 markdown 이며, `general` 타입과 `--quiet` 에는 없다.
|
|
62
|
+
|
|
63
|
+
## 삭제 명령의 확인 동작
|
|
64
|
+
|
|
65
|
+
여섯 삭제 명령은 같은 안전 확인 정책을 따른다.
|
|
66
|
+
|
|
67
|
+
| 명령 | 확인 | 자동화 |
|
|
68
|
+
| --- | --- | --- |
|
|
69
|
+
| `wiki page delete` | 있음 | `-y`, `--yes` |
|
|
70
|
+
| `post comment file delete` | 있음 | `-y`, `--yes` |
|
|
71
|
+
| `post file delete` | 있음 | `-y`, `--yes` |
|
|
72
|
+
| `wiki page file delete` | 있음 | `-y`, `--yes` |
|
|
73
|
+
| `post comment delete` | 있음 | `-y`, `--yes` |
|
|
74
|
+
| `wiki page comment delete` | 있음 | `-y`, `--yes` |
|
|
75
|
+
|
|
76
|
+
- TTY 확인은 기본값이 아니오다.
|
|
77
|
+
- non-TTY에서 플래그가 없으면 설정 조회나 삭제 API 호출 전에 종료 코드 3으로 중단한다.
|
|
78
|
+
- 자동화에서는 `-y` 또는 `--yes`를 반드시 붙인다.
|
|
79
|
+
|
|
80
|
+
# 의도별 커맨드
|
|
81
|
+
|
|
82
|
+
자연어 요청을 커맨드로 옮길 때 해당 영역의 절만 본다.
|
|
83
|
+
|
|
84
|
+
## 설정
|
|
85
|
+
|
|
86
|
+
| 의도 | 커맨드 |
|
|
87
|
+
| --- | --- |
|
|
88
|
+
| 초기 설정 (대화형) | `dooray setup` |
|
|
89
|
+
|
|
90
|
+
## 프로젝트와 멤버
|
|
91
|
+
|
|
92
|
+
| 의도 | 커맨드 |
|
|
93
|
+
| --- | --- |
|
|
94
|
+
| 프로젝트 찾기 | `dooray project list --search <keyword>` |
|
|
95
|
+
| 개인 프로젝트 목록 | `dooray project list --type private` |
|
|
96
|
+
| 프로젝트 멤버 보기 | `dooray project members <project>` 또는 `dooray member list <project>` |
|
|
97
|
+
| 프로젝트 멤버 그룹 목록 | `dooray project groups <project>` |
|
|
98
|
+
| 프로젝트 태그 목록 | `dooray project tags <project>` |
|
|
99
|
+
| 프로젝트 템플릿 목록 | `dooray project templates <project>` |
|
|
100
|
+
| 멤버 상세 | `dooray member get <organizationMemberId>` (캐시 우회) |
|
|
101
|
+
| organization 전체 멤버 검색 | `dooray member search <keyword>` — 옵션은 [common.md](references/common.md) |
|
|
102
|
+
|
|
103
|
+
## 업무 조회와 생성
|
|
104
|
+
|
|
105
|
+
| 의도 | 커맨드 |
|
|
106
|
+
| --- | --- |
|
|
107
|
+
| 업무 목록 | `dooray post list <project>` |
|
|
108
|
+
| 업무 검색 | `dooray post search <project> "<keyword>"` — projectId(15자리 이상 numeric) 를 넣으면 캐시를 우회한다 |
|
|
109
|
+
| 업무 상세 | `dooray post get <project> <number>` 또는 `dooray post get --id <postId>` |
|
|
110
|
+
| 업무 생성 | `dooray post create <project> --title "..." [--body "..." \| --body-file <path>]` — 담당자는 `--to <name\|email>`, 참조자는 `--cc`, 둘 다 여러 명 가능 |
|
|
111
|
+
| 템플릿으로 생성 | `dooray post create <project> --template <name\|id>` — 본문·담당자·태그가 채워지고 사용자 옵션이 우선한다 |
|
|
112
|
+
| 제목·본문 수정 | `dooray post edit <project> <number> --title "..." --body "..."` |
|
|
113
|
+
| 완료 처리 | `dooray post done <project> <number>` |
|
|
114
|
+
| 워크플로우 변경 | `dooray post workflow <project> <number> <workflow>` |
|
|
115
|
+
|
|
116
|
+
## 업무 메타 변경
|
|
117
|
+
|
|
118
|
+
자세한 동작은 [post.md](references/post.md) 를 읽는다.
|
|
119
|
+
|
|
120
|
+
| 의도 | 커맨드 |
|
|
121
|
+
| --- | --- |
|
|
122
|
+
| 참조자에 그룹 추가 | `dooray post edit <project> <number> --cc-group <code>` — 기존 참조자를 유지하고 추가한다 |
|
|
123
|
+
| 참조자 전체 교체 | `dooray post edit <project> <number> --cc-clear --cc <name>` |
|
|
124
|
+
| 생성 시 그룹 참조자 | `dooray post create <project> --title "..." --cc-group <code>` |
|
|
125
|
+
| 상위 업무 지정·변경 | `dooray post edit <project> <number> --title "<원제목>" --parent <ref>` — `--title` 이 필수이고 해제는 지원하지 않는다 |
|
|
126
|
+
| 태그 추가 | `dooray post edit --id <postId> --tag <name>` (반복 가능, 중복 제거) |
|
|
127
|
+
| 태그 전체 교체 | `dooray post edit --id <postId> --tag-clear --tag <name>` |
|
|
128
|
+
| 태그 제거 | `dooray post edit --id <postId> --tag-remove <name>` |
|
|
129
|
+
|
|
130
|
+
참조자·담당자 옵션만 지정하면 `$EDITOR`를 열지 않고 기존 제목·본문·태그를 보존한 채 참여자만 바꾼다.
|
|
131
|
+
|
|
132
|
+
그룹 지정(`--cc-group`, `--mention-group`)은 15자리 이상 numeric 이면 ID 로, 그 외에는 code 부분일치로 찾는다.
|
|
133
|
+
|
|
134
|
+
## 업무 댓글
|
|
135
|
+
|
|
136
|
+
| 의도 | 커맨드 |
|
|
137
|
+
| --- | --- |
|
|
138
|
+
| 댓글 조회 | `dooray post comment list <project> <number>` — 필터는 [comment.md](references/comment.md) |
|
|
139
|
+
| 최신 댓글 | `dooray post comment latest <project> <number>` (`-n <N>` 으로 개수 지정) |
|
|
140
|
+
| 단일 댓글 | `dooray post comment get <project> <number> <comment-id>` |
|
|
141
|
+
| 댓글 추가 | `dooray post comment add <project> <number> --body "..."` |
|
|
142
|
+
| 댓글 수정 | `dooray post comment edit <project> <number> <comment-id> --body "..."` |
|
|
143
|
+
| 댓글 삭제 | `dooray post comment delete <project> <number> <comment-id>` — 확인 있음, `-y`/`--yes`로 생략 |
|
|
144
|
+
|
|
145
|
+
## 업무 첨부
|
|
146
|
+
|
|
147
|
+
`--json` 출력 스키마는 [post.md](references/post.md) 를 읽는다.
|
|
148
|
+
|
|
149
|
+
| 의도 | 커맨드 |
|
|
150
|
+
| --- | --- |
|
|
151
|
+
| 첨부 목록 | `dooray post file list <project> <number>` |
|
|
152
|
+
| 첨부 다운로드 | `dooray post file download <project> <number> <file-id>` |
|
|
153
|
+
| 첨부 일괄 다운로드 | `dooray post file download-all <project> <number>` |
|
|
154
|
+
| 첨부 업로드 | `dooray post file upload <project> <number> <file-path>` |
|
|
155
|
+
| 첨부 삭제 | `dooray post file delete <project> <number> <file-id>` — 확인 있음, `-y`/`--yes`로 생략 |
|
|
156
|
+
| 댓글 첨부 목록 | `dooray post comment file list <project> <number> <comment-id>` |
|
|
157
|
+
| 댓글 첨부 업로드 | `dooray post comment file upload <project> <number> <comment-id> <path>` |
|
|
158
|
+
| 댓글 첨부 다운로드 | `dooray post comment file download <project> <number> <comment-id> <file-id>` |
|
|
159
|
+
| 댓글 첨부 삭제 | `dooray post comment file delete <project> <number> <comment-id> <file-id>` — 확인 있음, `-y`/`--yes`로 생략 |
|
|
160
|
+
|
|
161
|
+
- 댓글 파일 업로드는 이미지 확장자면 이미지 마크다운을, 그 외에는 일반 링크를 만든다.
|
|
162
|
+
- `comment file list`가 비어도 웹 UI 첨부가 없다고 단정하지 말고 `post file list`로 확인한다.
|
|
163
|
+
|
|
164
|
+
## 위키
|
|
165
|
+
|
|
166
|
+
| 의도 | 커맨드 |
|
|
167
|
+
| --- | --- |
|
|
168
|
+
| 위키 목록 | `dooray wiki list` |
|
|
169
|
+
| 페이지 목록 | `dooray wiki pages <project>` |
|
|
170
|
+
| 페이지 트리 | `dooray wiki tree <project>` (`--depth N` 으로 상한, `--json` 은 flat) |
|
|
171
|
+
| 페이지 상세 | `dooray wiki page get <project> <page-id>` |
|
|
172
|
+
| 페이지 생성 | `dooray wiki page create <project> --title "..." [--parent <page-id>] [--body "..."]` — `--parent` 를 생략하면 위키 home 아래에 만든다 |
|
|
173
|
+
| 페이지 제목 수정 | `dooray wiki page edit <project> <page-id> --title "..."` |
|
|
174
|
+
| 페이지 본문 수정 | `dooray wiki page edit <project> <page-id> --body "..."` 또는 `--body-file ./new.md` |
|
|
175
|
+
| 페이지 에디터로 수정 | `dooray wiki page edit <project> <page-id>` — 플래그가 없으면 `$EDITOR` 가 열린다 |
|
|
176
|
+
| 페이지 삭제 | `dooray wiki page delete <project> <page-id>` — 확인 있음, `-y`/`--yes`로 생략. 하위 페이지는 삭제한 페이지의 부모 아래로 재부착되어 orphan 이 생기지 않는다 |
|
|
177
|
+
| 첨부 목록 | `dooray wiki page file list <project> <page-id>` — general 과 inline 을 합쳐 보여준다 |
|
|
178
|
+
| 첨부 업로드 | `dooray wiki page file upload <project> <page-id> --file <path> [--type inline_image]` |
|
|
179
|
+
| 첨부 다운로드 | `dooray wiki page file download <project> <page-id> --file-id <id> -o <dir>` |
|
|
180
|
+
| 첨부 일괄 다운로드 | `dooray wiki page file download-all <project> <page-id> -o <dir>` |
|
|
181
|
+
| 첨부 삭제 | `dooray wiki page file delete <project> <page-id> --file-id <id>` — 확인 있음, `-y`/`--yes`로 생략 |
|
|
182
|
+
| 댓글 목록 | `dooray wiki page comment list <project> <page-id> [--latest N]` (최신순) |
|
|
183
|
+
| 최신 댓글 | `dooray wiki page comment latest <project> <page-id>` |
|
|
184
|
+
| 단일 댓글 | `dooray wiki page comment get <project> <page-id> <comment-id>` |
|
|
185
|
+
| 댓글 추가 | `dooray wiki page comment add <project> <page-id> --body "..."` (`$EDITOR` fallback) |
|
|
186
|
+
| 댓글 수정 | `dooray wiki page comment edit <project> <page-id> <comment-id> --body "..."` |
|
|
187
|
+
| 댓글 삭제 | `dooray wiki page comment delete <project> <page-id> <comment-id>` — 확인 있음, `-y`/`--yes`로 생략 |
|
|
188
|
+
|
|
189
|
+
## 메일
|
|
190
|
+
|
|
191
|
+
| 의도 | 커맨드 |
|
|
192
|
+
| --- | --- |
|
|
193
|
+
| 메일 목록 | `dooray mail list` |
|
|
194
|
+
| 안 읽은 메일 | `dooray mail list --unread` |
|
|
195
|
+
| 제목 검색 | `dooray mail list --search "<keyword>"` |
|
|
196
|
+
| 메일 상세 | `dooray mail get <uid>` |
|
|
197
|
+
| 메일 발송 | `dooray mail send --to "..." --subject "..." --body "..."` |
|
|
198
|
+
| 메일 답장 | `dooray mail reply <uid> --body "..."` |
|
|
199
|
+
| 저장된 인증정보 제거 | `dooray mail logout` (비대화형 환경은 `--yes`) |
|
|
200
|
+
|
|
201
|
+
## 메신저
|
|
202
|
+
|
|
203
|
+
| 의도 | 커맨드 |
|
|
204
|
+
| --- | --- |
|
|
205
|
+
| 1:1 다이렉트 메시지 | `dooray messenger send --to "<id\|email>" --body "..."` — `--to` 는 ID 나 이메일만 받고 이름은 지원하지 않는다 |
|
|
206
|
+
| 대화방 메시지 | `dooray messenger channel-send --channel "<channelId\|이름>" --body "..."` — 이름으로는 자신이 속한 방만 찾는다 |
|
|
207
|
+
|
|
208
|
+
## 옵션 이름
|
|
209
|
+
|
|
210
|
+
`post` 와 `wiki page` 모두 제목은 `--title` 이다.
|
|
211
|
+
`post` 의 `--subject` 는 deprecated alias 로 아직 동작하지만 경고가 나온다.
|