@cloudglab/confluence-cli 0.0.1
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/AGENTS.md +34 -0
- package/CHANGELOG.md +26 -0
- package/README.md +147 -0
- package/assets/readme/confluence-cli-hero.png +0 -0
- package/assets/readme/confluence-cli-hero.svg +7 -0
- package/assets/readme/prompts/01-cover-confluence-cli.md +61 -0
- package/dist/api/endpoints.d.ts +404 -0
- package/dist/api/endpoints.js +85 -0
- package/dist/api/index.d.ts +148 -0
- package/dist/api/index.js +143 -0
- package/dist/bin/confluence-reader.d.ts +2 -0
- package/dist/bin/confluence-reader.js +8 -0
- package/dist/bin/confluence-writer.d.ts +2 -0
- package/dist/bin/confluence-writer.js +8 -0
- package/dist/bin/confluence.d.ts +2 -0
- package/dist/bin/confluence.js +11 -0
- package/dist/cli.d.ts +1 -0
- package/dist/cli.js +154 -0
- package/dist/core/api-provider.d.ts +3 -0
- package/dist/core/api-provider.js +13 -0
- package/dist/core/changelog.d.ts +7 -0
- package/dist/core/changelog.js +42 -0
- package/dist/core/cli-output.d.ts +16 -0
- package/dist/core/cli-output.js +318 -0
- package/dist/core/cli-registry.d.ts +20 -0
- package/dist/core/cli-registry.js +148 -0
- package/dist/core/command-groups.generated.d.ts +2 -0
- package/dist/core/command-groups.generated.js +88 -0
- package/dist/core/config.d.ts +5 -0
- package/dist/core/config.js +108 -0
- package/dist/core/http-error.d.ts +2 -0
- package/dist/core/http-error.js +4 -0
- package/dist/core/http.d.ts +28 -0
- package/dist/core/http.js +124 -0
- package/dist/core/inline-comment.d.ts +23 -0
- package/dist/core/inline-comment.js +27 -0
- package/dist/core/list-result.d.ts +14 -0
- package/dist/core/list-result.js +81 -0
- package/dist/core/manifest.d.ts +11 -0
- package/dist/core/manifest.js +42 -0
- package/dist/core/pagination.d.ts +26 -0
- package/dist/core/pagination.js +45 -0
- package/dist/core/roles.d.ts +4 -0
- package/dist/core/roles.js +12 -0
- package/dist/core/tool-registry.d.ts +9 -0
- package/dist/core/tool-registry.js +60 -0
- package/dist/core/validation.d.ts +2 -0
- package/dist/core/validation.js +10 -0
- package/dist/core/value.d.ts +2 -0
- package/dist/core/value.js +19 -0
- package/dist/core/write-guard.d.ts +25 -0
- package/dist/core/write-guard.js +49 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +3 -0
- package/dist/install.d.ts +3 -0
- package/dist/install.js +407 -0
- package/dist/manifest.json +122 -0
- package/dist/tools/attachments.d.ts +2 -0
- package/dist/tools/attachments.js +46 -0
- package/dist/tools/content.d.ts +2 -0
- package/dist/tools/content.js +45 -0
- package/dist/tools/convert.d.ts +2 -0
- package/dist/tools/convert.js +63 -0
- package/dist/tools/init.d.ts +2 -0
- package/dist/tools/init.js +24 -0
- package/dist/tools/install.d.ts +2 -0
- package/dist/tools/install.js +52 -0
- package/dist/tools/labels.d.ts +2 -0
- package/dist/tools/labels.js +22 -0
- package/dist/tools/metadata.d.ts +2 -0
- package/dist/tools/metadata.js +26 -0
- package/dist/tools/rest.d.ts +2 -0
- package/dist/tools/rest.js +52 -0
- package/dist/tools/spaces.d.ts +2 -0
- package/dist/tools/spaces.js +18 -0
- package/dist/tools/transfer.d.ts +2 -0
- package/dist/tools/transfer.js +407 -0
- package/dist/types/common.d.ts +17 -0
- package/dist/types/common.js +2 -0
- package/dist/update-probe.d.ts +2 -0
- package/dist/update-probe.js +142 -0
- package/dist/utils/mark-metadata.d.ts +9 -0
- package/dist/utils/mark-metadata.js +16 -0
- package/dist/utils/markdown.d.ts +9 -0
- package/dist/utils/markdown.js +220 -0
- package/dist/utils/result.d.ts +3 -0
- package/dist/utils/result.js +7 -0
- package/dist/version.d.ts +1 -0
- package/dist/version.js +2 -0
- package/docs/confluence-7.13.7-api.md +183 -0
- package/docs/index.html +608 -0
- package/docs/release.md +41 -0
- package/package.json +63 -0
- package/skills/confluence-cli/SKILL.md +63 -0
- package/skills/confluence-cli/reference/cli.md +36 -0
- package/skills/confluence-cli/reference/commands.md +41 -0
- package/skills/confluence-cli/reference/content.md +23 -0
- package/skills/confluence-cli/reference/overview.md +23 -0
- package/skills/confluence-cli/reference/rest.md +19 -0
- package/skills/confluence-cli/reference/transfer.md +27 -0
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { Role } from "../types/common.js";
|
|
2
|
+
import type { InMemoryCliRegistry } from "./cli-registry.js";
|
|
3
|
+
export declare const BUILTIN_COMMAND_NAMES: string[];
|
|
4
|
+
export declare const BUILTIN_COMMAND_ALIASES: string[];
|
|
5
|
+
export declare function printHelp(role: Role, commandNames: string[]): void;
|
|
6
|
+
export declare function printCommandList(role: Role, commandNames: string[], builtinCommandNames?: string[]): void;
|
|
7
|
+
export declare function getBuiltinCommandHelp(commandName: string): string | undefined;
|
|
8
|
+
export declare function printCommandHelp(registry: InMemoryCliRegistry, name: string): void;
|
|
9
|
+
export declare function renderCommandHelp(registry: InMemoryCliRegistry, name: string): string;
|
|
10
|
+
export interface ChangelogOptions {
|
|
11
|
+
limit: number | "all";
|
|
12
|
+
version?: string;
|
|
13
|
+
since?: string;
|
|
14
|
+
raw: boolean;
|
|
15
|
+
}
|
|
16
|
+
export declare function renderChangelog(options: ChangelogOptions): Promise<string>;
|
|
@@ -0,0 +1,318 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { VERSION } from "../version.js";
|
|
3
|
+
import { loadChangelogRaw, loadChangelogSections } from "./changelog.js";
|
|
4
|
+
const BUILTIN_DESCRIPTIONS = {
|
|
5
|
+
help: "查看总帮助或指定命令参数",
|
|
6
|
+
list: "按场景列出可用命令",
|
|
7
|
+
version: "查看 CLI 版本",
|
|
8
|
+
changelog: "查看版本更新记录",
|
|
9
|
+
install: "安装 CLI 和 Confluence skill",
|
|
10
|
+
update: "更新 CLI 和 Confluence skill",
|
|
11
|
+
upgrade: "update 的别名",
|
|
12
|
+
uninstall: "卸载 CLI / skill / 配置",
|
|
13
|
+
remove: "uninstall 的别名",
|
|
14
|
+
};
|
|
15
|
+
const COMMAND_DESCRIPTIONS = {
|
|
16
|
+
initConfluence: "初始化或校验 Confluence 连接配置",
|
|
17
|
+
install: "安装 CLI 和 Confluence skill",
|
|
18
|
+
update: "更新 CLI 和 Confluence skill",
|
|
19
|
+
convertMarkdownToWiki: "将 Markdown 转换为 Confluence Wiki 标记",
|
|
20
|
+
convertMermaidToDrawio: "将 Mermaid 图转换为 draw.io XML",
|
|
21
|
+
generateMarkMetadata: "生成 Markdown 页面元数据",
|
|
22
|
+
request: "发送原始 Confluence REST 请求",
|
|
23
|
+
searchSpace: "搜索 Confluence 空间",
|
|
24
|
+
listSpaces: "列出 Confluence 空间",
|
|
25
|
+
getSpace: "获取空间详情",
|
|
26
|
+
searchContent: "使用 CQL 搜索内容",
|
|
27
|
+
getContent: "获取页面或博客内容",
|
|
28
|
+
createContent: "创建 Confluence 内容",
|
|
29
|
+
updateContent: "更新 Confluence 内容",
|
|
30
|
+
deleteContent: "删除 Confluence 内容",
|
|
31
|
+
addLabels: "添加内容标签",
|
|
32
|
+
removeLabel: "移除内容标签",
|
|
33
|
+
listLabels: "列出内容标签",
|
|
34
|
+
listAttachments: "列出页面附件",
|
|
35
|
+
uploadAttachment: "上传页面附件",
|
|
36
|
+
downloadAttachment: "下载页面附件",
|
|
37
|
+
uploadMarkdown: "上传 Markdown 为 Confluence 页面",
|
|
38
|
+
downloadPage: "下载页面为本地内容",
|
|
39
|
+
};
|
|
40
|
+
export const BUILTIN_COMMAND_NAMES = ["changelog", "help", "list", "version"];
|
|
41
|
+
export const BUILTIN_COMMAND_ALIASES = ["install", "update", "upgrade", "uninstall", "remove"];
|
|
42
|
+
export function printHelp(role, commandNames) {
|
|
43
|
+
const recommended = getRecommendedCommands(commandNames);
|
|
44
|
+
process.stdout.write([
|
|
45
|
+
`confluence CLI ${VERSION}`,
|
|
46
|
+
"",
|
|
47
|
+
`当前 role: ${role}`,
|
|
48
|
+
"适配版本:Confluence Data Center / Server REST API。",
|
|
49
|
+
"运行要求:Node.js >= 18",
|
|
50
|
+
"",
|
|
51
|
+
"用法:",
|
|
52
|
+
" confluence [--role full|reader|writer] <command> [--key value]",
|
|
53
|
+
" confluence help <command>",
|
|
54
|
+
" confluence <command> --help",
|
|
55
|
+
"",
|
|
56
|
+
"快速开始:",
|
|
57
|
+
" confluence list 查看全部可用命令(推荐)",
|
|
58
|
+
" confluence help <command> 查看命令参数",
|
|
59
|
+
" confluence initConfluence 初始化或校验连接配置",
|
|
60
|
+
" confluence version 查看版本",
|
|
61
|
+
" confluence changelog 查看最近更新",
|
|
62
|
+
"",
|
|
63
|
+
"安装/更新:",
|
|
64
|
+
" confluence install 一键安装 CLI + Skill",
|
|
65
|
+
" confluence update 更新到最新版本",
|
|
66
|
+
" npx -y @cloudglab/confluence-cli@latest install",
|
|
67
|
+
"",
|
|
68
|
+
"常用命令:",
|
|
69
|
+
...recommended.map((item) => ` - ${item.name.padEnd(28)} ${item.description}`),
|
|
70
|
+
"",
|
|
71
|
+
"写操作保护:",
|
|
72
|
+
" 真实写操作必须显式传 --confirm true",
|
|
73
|
+
" CONFLUENCE_DISABLE_WRITE=true 可强制禁用真实写入",
|
|
74
|
+
"",
|
|
75
|
+
"查看更多:",
|
|
76
|
+
" confluence list 按场景查看命令说明",
|
|
77
|
+
" confluence list --raw 仅输出命令名,适合脚本处理",
|
|
78
|
+
" confluence help <command> 查看某个命令的参数",
|
|
79
|
+
"",
|
|
80
|
+
].join("\n"));
|
|
81
|
+
}
|
|
82
|
+
export function printCommandList(role, commandNames, builtinCommandNames = BUILTIN_COMMAND_NAMES) {
|
|
83
|
+
const allCommandNames = [...new Set([...builtinCommandNames, ...commandNames])]
|
|
84
|
+
.sort((left, right) => left.localeCompare(right));
|
|
85
|
+
const groups = buildCommandGroups(allCommandNames);
|
|
86
|
+
const lines = [
|
|
87
|
+
"confluence 可用命令",
|
|
88
|
+
"",
|
|
89
|
+
`当前 role: ${role}`,
|
|
90
|
+
`命令数量:${allCommandNames.length}`,
|
|
91
|
+
"",
|
|
92
|
+
];
|
|
93
|
+
for (const group of groups) {
|
|
94
|
+
if (group.commands.length === 0)
|
|
95
|
+
continue;
|
|
96
|
+
lines.push(`${group.title}:`);
|
|
97
|
+
for (const commandName of group.commands) {
|
|
98
|
+
lines.push(` - ${commandName.padEnd(28)} ${describeCommand(commandName)}`);
|
|
99
|
+
}
|
|
100
|
+
lines.push("");
|
|
101
|
+
}
|
|
102
|
+
lines.push("下一步:", " - 查看参数:confluence help <command>,例如 confluence help searchContent", " - 初始化配置:confluence initConfluence", " - 查看脚本友好命令名:confluence list --raw", " - 切换角色命令集:confluence --role reader list 或 confluence --role writer list", "");
|
|
103
|
+
process.stdout.write(lines.join("\n"));
|
|
104
|
+
}
|
|
105
|
+
export function getBuiltinCommandHelp(commandName) {
|
|
106
|
+
const normalizedCommand = commandName === "upgrade"
|
|
107
|
+
? "update"
|
|
108
|
+
: commandName === "remove"
|
|
109
|
+
? "uninstall"
|
|
110
|
+
: commandName;
|
|
111
|
+
const help = {
|
|
112
|
+
help: [
|
|
113
|
+
"confluence help [command]",
|
|
114
|
+
"",
|
|
115
|
+
"查看总帮助或指定命令参数。",
|
|
116
|
+
].join("\n"),
|
|
117
|
+
list: [
|
|
118
|
+
"confluence list [--raw]",
|
|
119
|
+
"",
|
|
120
|
+
"按场景列出可用命令。",
|
|
121
|
+
"",
|
|
122
|
+
"参数:",
|
|
123
|
+
" --raw 仅输出命令名,每行一个,适合脚本处理",
|
|
124
|
+
].join("\n"),
|
|
125
|
+
install: [
|
|
126
|
+
"confluence install",
|
|
127
|
+
"",
|
|
128
|
+
"用法:",
|
|
129
|
+
" confluence install [--skill-source local|git|npm] [--skill-local-path <path>] [--skip-config-check] [--cli-only] [--skill-only]",
|
|
130
|
+
" npx -y @cloudglab/confluence-cli@latest install",
|
|
131
|
+
"",
|
|
132
|
+
"说明:",
|
|
133
|
+
" 安装或更新 CLI,并按来源安装 Confluence skill。",
|
|
134
|
+
"",
|
|
135
|
+
"参数:",
|
|
136
|
+
" --skill-source <local|git|npm> (可选):skill 安装来源,默认 local。",
|
|
137
|
+
" --skill-local-path <string> (可选):直接从本地目录安装 skill。",
|
|
138
|
+
" --skip-config-check (可选):安装后跳过 Confluence 配置校验。",
|
|
139
|
+
" --cli-only (可选):只安装 CLI,不安装 skill。",
|
|
140
|
+
" --skill-only (可选):只安装 skill,不安装 CLI。",
|
|
141
|
+
].join("\n"),
|
|
142
|
+
update: [
|
|
143
|
+
"confluence update",
|
|
144
|
+
"",
|
|
145
|
+
"用法:",
|
|
146
|
+
" confluence update [--skill-source local|git|npm] [--skill-local-path <path>] [--skip-config-check] [--cli-only] [--skill-only]",
|
|
147
|
+
" npx -y @cloudglab/confluence-cli@latest update",
|
|
148
|
+
"",
|
|
149
|
+
"说明:",
|
|
150
|
+
" 更新或重新安装 CLI,并按来源更新 Confluence skill。",
|
|
151
|
+
"",
|
|
152
|
+
"参数:",
|
|
153
|
+
" --skill-source <local|git|npm> (可选):skill 更新来源,默认 local。",
|
|
154
|
+
" --skill-local-path <string> (可选):直接从本地目录更新 skill。",
|
|
155
|
+
" --skip-config-check (可选):更新后跳过 Confluence 配置校验。",
|
|
156
|
+
" --cli-only (可选):只更新 CLI,不更新 skill。",
|
|
157
|
+
" --skill-only (可选):只更新 skill,不更新 CLI。",
|
|
158
|
+
].join("\n"),
|
|
159
|
+
uninstall: [
|
|
160
|
+
"confluence uninstall",
|
|
161
|
+
"",
|
|
162
|
+
"用法:",
|
|
163
|
+
" confluence uninstall [--confirm true] [--keep-config true] [--cli-only] [--skill-only]",
|
|
164
|
+
" npx -y @cloudglab/confluence-cli@latest uninstall --confirm true",
|
|
165
|
+
"",
|
|
166
|
+
"说明:",
|
|
167
|
+
" 卸载 CLI、Confluence skill,以及可选的本地配置文件。",
|
|
168
|
+
"",
|
|
169
|
+
"参数:",
|
|
170
|
+
" --confirm (可选):显式确认后才真实执行卸载。",
|
|
171
|
+
" --keep-config (可选):保留 ~/.confluence/config.json。",
|
|
172
|
+
" --cli-only (可选):只卸载 CLI,不卸载 skill。",
|
|
173
|
+
" --skill-only (可选):只卸载 skill,不卸载 CLI。",
|
|
174
|
+
].join("\n"),
|
|
175
|
+
version: [
|
|
176
|
+
"confluence version",
|
|
177
|
+
"",
|
|
178
|
+
"输出当前 CLI 版本。",
|
|
179
|
+
].join("\n"),
|
|
180
|
+
changelog: [
|
|
181
|
+
"confluence changelog [--limit N|all] [--version VERSION] [--since VERSION] [--raw]",
|
|
182
|
+
"",
|
|
183
|
+
"查看 CHANGELOG.md 中的版本更新记录。",
|
|
184
|
+
"",
|
|
185
|
+
"参数:",
|
|
186
|
+
" --limit N|all 输出最近 N 个版本,默认 5;all 输出全部",
|
|
187
|
+
" --version VERSION 只输出指定版本",
|
|
188
|
+
" --since VERSION 输出从最新版到指定版本的记录",
|
|
189
|
+
" --raw 输出完整 CHANGELOG.md 原文",
|
|
190
|
+
].join("\n"),
|
|
191
|
+
};
|
|
192
|
+
return help[normalizedCommand];
|
|
193
|
+
}
|
|
194
|
+
export function printCommandHelp(registry, name) {
|
|
195
|
+
process.stdout.write(`${renderCommandHelp(registry, name)}\n`);
|
|
196
|
+
}
|
|
197
|
+
export function renderCommandHelp(registry, name) {
|
|
198
|
+
const selected = registry.get(name);
|
|
199
|
+
if (!selected)
|
|
200
|
+
throw new Error(`Unknown command: ${name}`);
|
|
201
|
+
const lines = [`confluence ${name} [--key value]`];
|
|
202
|
+
if (selected.description)
|
|
203
|
+
lines.push("", selected.description);
|
|
204
|
+
const params = describeParams(selected.schema);
|
|
205
|
+
if (params.length > 0)
|
|
206
|
+
lines.push("", "Parameters:", ...params.map((param) => ` ${param}`));
|
|
207
|
+
return lines.join("\n");
|
|
208
|
+
}
|
|
209
|
+
function buildCommandGroups(commandNames) {
|
|
210
|
+
const groups = [
|
|
211
|
+
{ title: "开始使用", match: (name) => ["changelog", "help", "list", "version", "install", "update", "upgrade", "uninstall", "remove", "initConfluence"].includes(name), commands: [] },
|
|
212
|
+
{ title: "内容检索 / 页面", match: (name) => /Content|Page|searchContent|getContent/.test(name), commands: [] },
|
|
213
|
+
{ title: "上传 / 下载 / 附件", match: (name) => /Upload|Download|Attachment|upload|download/.test(name), commands: [] },
|
|
214
|
+
{ title: "空间 / 标签", match: (name) => /Space|Label/.test(name), commands: [] },
|
|
215
|
+
{ title: "转换 / 元数据", match: (name) => /convert|generate|Metadata|Markdown|Mermaid|Drawio/.test(name), commands: [] },
|
|
216
|
+
{ title: "底层 REST", match: (name) => ["request"].includes(name), commands: [] },
|
|
217
|
+
{ title: "其他", match: () => true, commands: [] },
|
|
218
|
+
];
|
|
219
|
+
for (const commandName of commandNames) {
|
|
220
|
+
const group = groups.find((item) => item.match(commandName));
|
|
221
|
+
group?.commands.push(commandName);
|
|
222
|
+
}
|
|
223
|
+
return groups;
|
|
224
|
+
}
|
|
225
|
+
function getRecommendedCommands(commandNames) {
|
|
226
|
+
const candidates = [
|
|
227
|
+
{ name: "initConfluence", description: "初始化或校验连接配置" },
|
|
228
|
+
{ name: "searchContent", description: "使用 CQL 搜索页面/博客" },
|
|
229
|
+
{ name: "getContent", description: "读取 Confluence 内容" },
|
|
230
|
+
{ name: "uploadMarkdown", description: "上传 Markdown 页面(需确认)" },
|
|
231
|
+
{ name: "downloadPage", description: "下载页面到本地" },
|
|
232
|
+
{ name: "convertMarkdownToWiki", description: "本地转换 Markdown" },
|
|
233
|
+
];
|
|
234
|
+
return candidates.filter((item) => commandNames.includes(item.name));
|
|
235
|
+
}
|
|
236
|
+
function describeCommand(commandName) {
|
|
237
|
+
return BUILTIN_DESCRIPTIONS[commandName]
|
|
238
|
+
?? COMMAND_DESCRIPTIONS[commandName]
|
|
239
|
+
?? `查看参数:confluence help ${commandName}`;
|
|
240
|
+
}
|
|
241
|
+
export async function renderChangelog(options) {
|
|
242
|
+
if (options.raw)
|
|
243
|
+
return loadChangelogRaw();
|
|
244
|
+
const sections = await loadChangelogSections();
|
|
245
|
+
if (sections.length === 0)
|
|
246
|
+
throw new Error("CHANGELOG.md 中没有版本记录");
|
|
247
|
+
let selected = sections;
|
|
248
|
+
if (options.version) {
|
|
249
|
+
selected = sections.filter((section) => section.version === options.version);
|
|
250
|
+
if (selected.length === 0)
|
|
251
|
+
throw new Error(`未找到版本 ${options.version} 的更新记录`);
|
|
252
|
+
}
|
|
253
|
+
else if (options.since) {
|
|
254
|
+
const sinceIndex = sections.findIndex((section) => section.version === options.since);
|
|
255
|
+
if (sinceIndex === -1)
|
|
256
|
+
throw new Error(`未找到起始版本 ${options.since}`);
|
|
257
|
+
selected = sections.slice(0, sinceIndex + 1);
|
|
258
|
+
}
|
|
259
|
+
else if (options.limit !== "all") {
|
|
260
|
+
selected = sections.slice(0, options.limit);
|
|
261
|
+
}
|
|
262
|
+
const header = options.version
|
|
263
|
+
? `confluence CLI ${options.version} 更新内容`
|
|
264
|
+
: `confluence CLI 最近更新(共 ${sections.length} 个版本)`;
|
|
265
|
+
return [header, "", ...selected.map((section) => section.content)].join("\n").trimEnd() + "\n";
|
|
266
|
+
}
|
|
267
|
+
function describeParams(schema) {
|
|
268
|
+
const unwrapped = unwrapSchema(schema);
|
|
269
|
+
if (!(unwrapped instanceof z.ZodObject))
|
|
270
|
+
return [];
|
|
271
|
+
return Object.entries(unwrapped.shape).map(([key, field]) => describeParam(key, field));
|
|
272
|
+
}
|
|
273
|
+
function describeParam(name, schema) {
|
|
274
|
+
const isOptional = schema instanceof z.ZodOptional || schema instanceof z.ZodDefault;
|
|
275
|
+
const defaultValue = schema instanceof z.ZodDefault ? formatDefaultValue(schema._def.defaultValue()) : undefined;
|
|
276
|
+
const description = schema.description;
|
|
277
|
+
const parts = [`--${name} ${describeZodType(schema)}`, isOptional ? "optional" : "required"];
|
|
278
|
+
if (defaultValue !== undefined)
|
|
279
|
+
parts.push(`default=${defaultValue}`);
|
|
280
|
+
if (description)
|
|
281
|
+
parts.push(description);
|
|
282
|
+
return parts.join(" | ");
|
|
283
|
+
}
|
|
284
|
+
function unwrapSchema(schema) {
|
|
285
|
+
if (schema instanceof z.ZodOptional || schema instanceof z.ZodNullable)
|
|
286
|
+
return unwrapSchema(schema.unwrap());
|
|
287
|
+
if (schema instanceof z.ZodDefault)
|
|
288
|
+
return unwrapSchema(schema._def.innerType);
|
|
289
|
+
if (schema instanceof z.ZodEffects)
|
|
290
|
+
return unwrapSchema(schema.innerType());
|
|
291
|
+
return schema;
|
|
292
|
+
}
|
|
293
|
+
function describeZodType(schema) {
|
|
294
|
+
const unwrapped = unwrapSchema(schema);
|
|
295
|
+
if (unwrapped instanceof z.ZodString)
|
|
296
|
+
return "string";
|
|
297
|
+
if (unwrapped instanceof z.ZodNumber)
|
|
298
|
+
return "number";
|
|
299
|
+
if (unwrapped instanceof z.ZodBoolean)
|
|
300
|
+
return "boolean";
|
|
301
|
+
if (unwrapped instanceof z.ZodArray)
|
|
302
|
+
return "array";
|
|
303
|
+
if (unwrapped instanceof z.ZodEnum)
|
|
304
|
+
return unwrapped.options.join("|");
|
|
305
|
+
if (unwrapped instanceof z.ZodObject)
|
|
306
|
+
return "json-object";
|
|
307
|
+
return "value";
|
|
308
|
+
}
|
|
309
|
+
function formatDefaultValue(value) {
|
|
310
|
+
if (typeof value === "string")
|
|
311
|
+
return JSON.stringify(value);
|
|
312
|
+
if (typeof value === "number" || typeof value === "boolean")
|
|
313
|
+
return String(value);
|
|
314
|
+
if (Array.isArray(value) || (typeof value === "object" && value !== null))
|
|
315
|
+
return JSON.stringify(value);
|
|
316
|
+
return String(value);
|
|
317
|
+
}
|
|
318
|
+
//# sourceMappingURL=cli-output.js.map
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import type { ToolHandler } from "../types/common.js";
|
|
3
|
+
export interface RegisteredTool<TInput = unknown> {
|
|
4
|
+
name: string;
|
|
5
|
+
description?: string;
|
|
6
|
+
schema: z.ZodType<TInput>;
|
|
7
|
+
handler: ToolHandler<TInput>;
|
|
8
|
+
}
|
|
9
|
+
export interface CliRegistry {
|
|
10
|
+
tool<TInput>(name: string, schema: z.ZodType<TInput>, handler: ToolHandler<TInput>, description?: string): void;
|
|
11
|
+
get(name: string): RegisteredTool | undefined;
|
|
12
|
+
list(): RegisteredTool[];
|
|
13
|
+
}
|
|
14
|
+
export declare class InMemoryCliRegistry implements CliRegistry {
|
|
15
|
+
private readonly tools;
|
|
16
|
+
tool<TInput>(name: string, schema: z.ZodType<TInput>, handler: ToolHandler<TInput>, description?: string): void;
|
|
17
|
+
get(name: string): RegisteredTool | undefined;
|
|
18
|
+
list(): RegisteredTool[];
|
|
19
|
+
}
|
|
20
|
+
export declare function parseCommandInput(schema: z.ZodType, args: string[]): unknown;
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export class InMemoryCliRegistry {
|
|
3
|
+
tools = new Map();
|
|
4
|
+
tool(name, schema, handler, description) {
|
|
5
|
+
this.tools.set(name, { name, schema, handler: handler, description });
|
|
6
|
+
}
|
|
7
|
+
get(name) {
|
|
8
|
+
return this.tools.get(name);
|
|
9
|
+
}
|
|
10
|
+
list() {
|
|
11
|
+
return [...this.tools.values()].sort((left, right) => left.name.localeCompare(right.name));
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
export function parseCommandInput(schema, args) {
|
|
15
|
+
const raw = {};
|
|
16
|
+
for (let index = 0; index < args.length; index += 1) {
|
|
17
|
+
const token = args[index];
|
|
18
|
+
if (!token.startsWith("--")) {
|
|
19
|
+
throw new Error(`无法识别的位置参数: ${token}`);
|
|
20
|
+
}
|
|
21
|
+
const equalsIndex = token.indexOf("=");
|
|
22
|
+
const key = equalsIndex >= 0 ? token.slice(2, equalsIndex) : token.slice(2);
|
|
23
|
+
if (!key)
|
|
24
|
+
throw new Error("检测到空参数名。");
|
|
25
|
+
const next = args[index + 1];
|
|
26
|
+
const hasInlineValue = equalsIndex >= 0;
|
|
27
|
+
const hasExplicitValue = !hasInlineValue && typeof next === "string" && !next.startsWith("--");
|
|
28
|
+
const value = hasInlineValue ? token.slice(equalsIndex + 1) : hasExplicitValue ? next : true;
|
|
29
|
+
if (hasExplicitValue)
|
|
30
|
+
index += 1;
|
|
31
|
+
appendArg(raw, key, value);
|
|
32
|
+
}
|
|
33
|
+
const objectSchema = unwrapObjectSchema(schema);
|
|
34
|
+
if (!objectSchema)
|
|
35
|
+
return schema.parse(raw);
|
|
36
|
+
const shape = objectSchema.shape;
|
|
37
|
+
const unknownKeys = Object.keys(raw).filter((key) => !(key in shape));
|
|
38
|
+
if (unknownKeys.length > 0) {
|
|
39
|
+
throw new Error(`未知参数: ${unknownKeys.map((key) => `--${key}`).join(", ")}`);
|
|
40
|
+
}
|
|
41
|
+
const converted = {};
|
|
42
|
+
for (const [key, fieldSchema] of Object.entries(shape)) {
|
|
43
|
+
if (!(key in raw))
|
|
44
|
+
continue;
|
|
45
|
+
converted[key] = coerceValue(selectValueForSchema(raw[key], fieldSchema), fieldSchema);
|
|
46
|
+
}
|
|
47
|
+
return schema.parse(converted);
|
|
48
|
+
}
|
|
49
|
+
function appendArg(target, key, value) {
|
|
50
|
+
const current = target[key];
|
|
51
|
+
if (current === undefined) {
|
|
52
|
+
target[key] = value;
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
if (Array.isArray(current)) {
|
|
56
|
+
current.push(value);
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
target[key] = [current, value];
|
|
60
|
+
}
|
|
61
|
+
function selectValueForSchema(value, schema) {
|
|
62
|
+
if (!Array.isArray(value))
|
|
63
|
+
return value;
|
|
64
|
+
const unwrapped = unwrapSchema(schema);
|
|
65
|
+
return unwrapped instanceof z.ZodArray ? value : value[value.length - 1];
|
|
66
|
+
}
|
|
67
|
+
function coerceValue(value, schema) {
|
|
68
|
+
const unwrapped = unwrapSchema(schema);
|
|
69
|
+
if (unwrapped instanceof z.ZodBoolean)
|
|
70
|
+
return toBoolean(value);
|
|
71
|
+
if (unwrapped instanceof z.ZodNumber)
|
|
72
|
+
return toNumber(value);
|
|
73
|
+
if (unwrapped instanceof z.ZodString)
|
|
74
|
+
return typeof value === "string" ? value : String(value);
|
|
75
|
+
if (unwrapped instanceof z.ZodArray) {
|
|
76
|
+
const items = Array.isArray(value)
|
|
77
|
+
? value
|
|
78
|
+
: typeof value === "string" && value.trim().startsWith("[")
|
|
79
|
+
? parseJsonValue(value, "数组参数")
|
|
80
|
+
: typeof value === "string"
|
|
81
|
+
? value.split(",").map((item) => item.trim()).filter(Boolean)
|
|
82
|
+
: [value];
|
|
83
|
+
return items.map((item) => coerceValue(item, unwrapped.element));
|
|
84
|
+
}
|
|
85
|
+
if (unwrapped instanceof z.ZodObject) {
|
|
86
|
+
if (typeof value !== "string")
|
|
87
|
+
return value;
|
|
88
|
+
return parseJsonValue(value, "对象参数");
|
|
89
|
+
}
|
|
90
|
+
if (unwrapped instanceof z.ZodUnion) {
|
|
91
|
+
for (const option of unwrapped._def.options) {
|
|
92
|
+
try {
|
|
93
|
+
return coerceValue(value, option);
|
|
94
|
+
}
|
|
95
|
+
catch {
|
|
96
|
+
// try next option
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
return value;
|
|
101
|
+
}
|
|
102
|
+
function parseJsonValue(value, label) {
|
|
103
|
+
try {
|
|
104
|
+
return JSON.parse(value);
|
|
105
|
+
}
|
|
106
|
+
catch (error) {
|
|
107
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
108
|
+
throw new Error(`无法解析${label}: ${value}(${message})`);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
function unwrapObjectSchema(schema) {
|
|
112
|
+
const unwrapped = unwrapSchema(schema);
|
|
113
|
+
return unwrapped instanceof z.ZodObject ? unwrapped : undefined;
|
|
114
|
+
}
|
|
115
|
+
function unwrapSchema(schema) {
|
|
116
|
+
if (schema instanceof z.ZodOptional || schema instanceof z.ZodNullable)
|
|
117
|
+
return unwrapSchema(schema.unwrap());
|
|
118
|
+
if (schema instanceof z.ZodDefault)
|
|
119
|
+
return unwrapSchema(schema._def.innerType);
|
|
120
|
+
if (schema instanceof z.ZodEffects)
|
|
121
|
+
return unwrapSchema(schema.innerType());
|
|
122
|
+
if (schema instanceof z.ZodPipeline)
|
|
123
|
+
return unwrapSchema(schema._def.out);
|
|
124
|
+
return schema;
|
|
125
|
+
}
|
|
126
|
+
function toBoolean(value) {
|
|
127
|
+
if (typeof value === "boolean")
|
|
128
|
+
return value;
|
|
129
|
+
if (typeof value === "string") {
|
|
130
|
+
const normalized = value.trim().toLowerCase();
|
|
131
|
+
if (["true", "1", "yes", "y", "on"].includes(normalized))
|
|
132
|
+
return true;
|
|
133
|
+
if (["false", "0", "no", "n", "off"].includes(normalized))
|
|
134
|
+
return false;
|
|
135
|
+
}
|
|
136
|
+
throw new Error(`无法解析布尔值: ${String(value)}`);
|
|
137
|
+
}
|
|
138
|
+
function toNumber(value) {
|
|
139
|
+
if (typeof value === "number" && Number.isFinite(value))
|
|
140
|
+
return value;
|
|
141
|
+
if (typeof value === "string" && value.trim() !== "") {
|
|
142
|
+
const parsed = Number(value);
|
|
143
|
+
if (Number.isFinite(parsed))
|
|
144
|
+
return parsed;
|
|
145
|
+
}
|
|
146
|
+
throw new Error(`无法解析数字: ${String(value)}`);
|
|
147
|
+
}
|
|
148
|
+
//# sourceMappingURL=cli-registry.js.map
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
// 由 scripts/generate-manifest.ts 在 build 时自动生成,请勿手动编辑。
|
|
2
|
+
export const commandToGroup = {
|
|
3
|
+
"initConfluence": "init",
|
|
4
|
+
"install": "install",
|
|
5
|
+
"remove": "install",
|
|
6
|
+
"uninstall": "install",
|
|
7
|
+
"update": "install",
|
|
8
|
+
"convertMarkdownToWiki": "convert",
|
|
9
|
+
"convertMermaidToDrawio": "convert",
|
|
10
|
+
"generateMarkMetadata": "metadata",
|
|
11
|
+
"callRestApi": "rest",
|
|
12
|
+
"listRestApis": "rest",
|
|
13
|
+
"convertContentBody": "space",
|
|
14
|
+
"getCurrentUser": "space",
|
|
15
|
+
"getSpace": "space",
|
|
16
|
+
"listSpaces": "space",
|
|
17
|
+
"addComment": "content",
|
|
18
|
+
"deleteContent": "content",
|
|
19
|
+
"findContent": "content",
|
|
20
|
+
"getComments": "content",
|
|
21
|
+
"getContent": "content",
|
|
22
|
+
"getPageChildren": "content",
|
|
23
|
+
"searchContent": "content",
|
|
24
|
+
"addLabels": "labels",
|
|
25
|
+
"deleteLabel": "labels",
|
|
26
|
+
"getLabels": "labels",
|
|
27
|
+
"downloadAttachment": "attachments",
|
|
28
|
+
"listAttachments": "attachments",
|
|
29
|
+
"updateAttachment": "attachments",
|
|
30
|
+
"uploadAttachment": "attachments",
|
|
31
|
+
"downloadPage": "transfer",
|
|
32
|
+
"uploadHtml": "transfer",
|
|
33
|
+
"uploadMarkdown": "transfer"
|
|
34
|
+
};
|
|
35
|
+
export const groupCommands = {
|
|
36
|
+
"init": [
|
|
37
|
+
"initConfluence"
|
|
38
|
+
],
|
|
39
|
+
"install": [
|
|
40
|
+
"install",
|
|
41
|
+
"remove",
|
|
42
|
+
"uninstall",
|
|
43
|
+
"update"
|
|
44
|
+
],
|
|
45
|
+
"convert": [
|
|
46
|
+
"convertMarkdownToWiki",
|
|
47
|
+
"convertMermaidToDrawio"
|
|
48
|
+
],
|
|
49
|
+
"metadata": [
|
|
50
|
+
"generateMarkMetadata"
|
|
51
|
+
],
|
|
52
|
+
"rest": [
|
|
53
|
+
"callRestApi",
|
|
54
|
+
"listRestApis"
|
|
55
|
+
],
|
|
56
|
+
"space": [
|
|
57
|
+
"convertContentBody",
|
|
58
|
+
"getCurrentUser",
|
|
59
|
+
"getSpace",
|
|
60
|
+
"listSpaces"
|
|
61
|
+
],
|
|
62
|
+
"content": [
|
|
63
|
+
"addComment",
|
|
64
|
+
"deleteContent",
|
|
65
|
+
"findContent",
|
|
66
|
+
"getComments",
|
|
67
|
+
"getContent",
|
|
68
|
+
"getPageChildren",
|
|
69
|
+
"searchContent"
|
|
70
|
+
],
|
|
71
|
+
"labels": [
|
|
72
|
+
"addLabels",
|
|
73
|
+
"deleteLabel",
|
|
74
|
+
"getLabels"
|
|
75
|
+
],
|
|
76
|
+
"attachments": [
|
|
77
|
+
"downloadAttachment",
|
|
78
|
+
"listAttachments",
|
|
79
|
+
"updateAttachment",
|
|
80
|
+
"uploadAttachment"
|
|
81
|
+
],
|
|
82
|
+
"transfer": [
|
|
83
|
+
"downloadPage",
|
|
84
|
+
"uploadHtml",
|
|
85
|
+
"uploadMarkdown"
|
|
86
|
+
]
|
|
87
|
+
};
|
|
88
|
+
//# sourceMappingURL=command-groups.generated.js.map
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { ConfluenceConfig } from "../types/common.js";
|
|
2
|
+
export declare function normalizeConfig(raw: Partial<ConfluenceConfig>): ConfluenceConfig;
|
|
3
|
+
export declare function loadConfluenceConfig(): ConfluenceConfig;
|
|
4
|
+
export declare function saveConfig(config: Partial<ConfluenceConfig>): void;
|
|
5
|
+
export declare function maskConfig(config: ConfluenceConfig): ConfluenceConfig;
|