hm-doc-tool 0.3.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.
Files changed (40) hide show
  1. package/README.md +230 -0
  2. package/dist/api-client.d.ts +44 -0
  3. package/dist/api-client.js +137 -0
  4. package/dist/common/config.d.ts +11 -0
  5. package/dist/common/config.js +70 -0
  6. package/dist/common/path-generator.d.ts +39 -0
  7. package/dist/common/path-generator.js +192 -0
  8. package/dist/common/tree-formatter.d.ts +19 -0
  9. package/dist/common/tree-formatter.js +129 -0
  10. package/dist/common/tree-processor.d.ts +35 -0
  11. package/dist/common/tree-processor.js +145 -0
  12. package/dist/common/types.d.ts +38 -0
  13. package/dist/common/types.js +5 -0
  14. package/dist/download/downloader.d.ts +46 -0
  15. package/dist/download/downloader.js +251 -0
  16. package/dist/download/index.d.ts +16 -0
  17. package/dist/download/index.js +168 -0
  18. package/dist/download/link-localizer.d.ts +13 -0
  19. package/dist/download/link-localizer.js +116 -0
  20. package/dist/download/markdown-converter.d.ts +1 -0
  21. package/dist/download/markdown-converter.js +96 -0
  22. package/dist/download/summary-generator.d.ts +46 -0
  23. package/dist/download/summary-generator.js +188 -0
  24. package/dist/download/turndown-rules.d.ts +2 -0
  25. package/dist/download/turndown-rules.js +394 -0
  26. package/dist/index.d.ts +2 -0
  27. package/dist/index.js +65 -0
  28. package/dist/tree/index.d.ts +11 -0
  29. package/dist/tree/index.js +91 -0
  30. package/dist/wiki/index.d.ts +7 -0
  31. package/dist/wiki/index.js +22 -0
  32. package/dist/wiki/wiki-generator.d.ts +3 -0
  33. package/dist/wiki/wiki-generator.js +357 -0
  34. package/dist/wiki/wiki-types.d.ts +61 -0
  35. package/dist/wiki/wiki-types.js +3 -0
  36. package/dist/wiki/wiki-utils.d.ts +33 -0
  37. package/dist/wiki/wiki-utils.js +180 -0
  38. package/docs_catalog.json +28 -0
  39. package/package.json +29 -0
  40. package/wiki_config.json +198 -0
package/README.md ADDED
@@ -0,0 +1,230 @@
1
+ # HarmonyOS Documentation Downloader
2
+
3
+ 将华为 HarmonyOS 官方文档下载并转换为本地 Markdown 文件的 CLI 工具。
4
+
5
+ ## 功能特性
6
+
7
+ - **目录结构同步** - 下载的文档目录层级与华为开发者官网完全一致
8
+ - **链接本地化** - 将文档中的远程链接替换为本地相对路径,支持跨 catalog 和锚点保留
9
+ - **元数据导出** - 支持导出目录树 JSON 和节点平铺列表
10
+ - **文档概要生成** - 自动提取摘要,生成 summary JSON 索引
11
+ - **Wiki 生成** - 从下载的文档生成 Wiki 文件
12
+ - 多 catalog 支持(指南、API 参考、最佳实践、FAQ 等)
13
+ - HTML 转 Markdown,保留代码块、表格、链接等格式
14
+ - 并发下载,可配置并发数
15
+
16
+ ## 安装
17
+
18
+ ```bash
19
+ # 克隆项目
20
+ git clone <repository-url>
21
+ cd hm-doc-new
22
+
23
+ # 安装依赖
24
+ npm install
25
+
26
+ # 编译 TypeScript
27
+ npm run build
28
+
29
+ # 全局链接
30
+ npm link
31
+ ```
32
+
33
+ ## 使用方法
34
+
35
+ ### 快速使用
36
+
37
+ ```bash
38
+ # 批量查看所有文档结构,并输出树结构文件
39
+ hm-doc tree
40
+
41
+ # 批量下载所有文档,并输出概要文件
42
+ hm-doc download
43
+
44
+ # 使用默认配置生成 Wiki(必须先执行前两条命令)
45
+ hm-doc wiki
46
+ ```
47
+
48
+ ### 下载文档
49
+
50
+ ```bash
51
+ # 批量下载(从 docs_catalog.json 配置读取所有 catalog)
52
+ hm-doc download
53
+
54
+ # 下载指定 catalog
55
+ hm-doc download -c harmonyos-guides
56
+
57
+ # 下载多个 catalog
58
+ hm-doc download -c harmonyos-guides -c harmonyos-references
59
+
60
+ # 下载指定节点
61
+ hm-doc download -c harmonyos-guides -n "快速入门"
62
+
63
+ # 通过 URL 下载单篇文档
64
+ hm-doc download -u "https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/start-overview"
65
+
66
+ # 预览目录树(不下载)
67
+ hm-doc download -c harmonyos-guides --dry-run
68
+
69
+ # 排除 C++ 相关文档
70
+ hm-doc download -c harmonyos-guides --no-cpp
71
+
72
+ # 只下载叶子节点
73
+ hm-doc download -c harmonyos-guides --leaf-only
74
+
75
+ # 下载并生成 summary JSON
76
+ hm-doc download -c harmonyos-guides -s
77
+
78
+ # 下载并本地化链接(将远程链接替换为本地相对路径)
79
+ hm-doc download -c harmonyos-guides -l
80
+
81
+ # 批量下载 + summary + 链接本地化
82
+ hm-doc download -s -l
83
+
84
+ # 设置并发数
85
+ hm-doc download -c harmonyos-guides --concurrency 10
86
+
87
+ # 指定输出目录
88
+ hm-doc download -o ./my-docs
89
+ ```
90
+
91
+ ### 查看目录树
92
+
93
+ ```bash
94
+ # 批量查看所有 catalog(从 docs_catalog.json 配置读取)
95
+ hm-doc tree
96
+
97
+ # 查看指定 catalog
98
+ hm-doc tree -c harmonyos-guides
99
+
100
+ # 查看指定节点的子树
101
+ hm-doc tree -c harmonyos-guides -n "快速入门"
102
+
103
+ # 限制显示深度
104
+ hm-doc tree -c harmonyos-guides -d 2
105
+
106
+ # 导出 JSON 文件
107
+ hm-doc tree -c harmonyos-guides -o ./raw
108
+ ```
109
+
110
+ ### 生成 Wiki
111
+
112
+ ```bash
113
+ # 使用默认配置生成 Wiki
114
+ hm-doc wiki
115
+
116
+ # 指定配置文件
117
+ hm-doc wiki -c ./my-wiki-config.json
118
+
119
+ # 指定文档目录
120
+ hm-doc wiki -d ./my-docs
121
+ ```
122
+
123
+ ## 命令参数
124
+
125
+ ### download 命令
126
+
127
+ | 参数 | 说明 | 默认值 |
128
+ |------|------|--------|
129
+ | `-c, --catalog <name...>` | catalog 名称,可指定多个 | 批量模式(所有 catalog) |
130
+ | `-n, --node-name <name>` | 目标节点名称 | - |
131
+ | `-i, --node-id <id>` | 目标节点 ID | - |
132
+ | `-u, --url <url>` | 通过 URL 下载单篇文档 | - |
133
+ | `-o, --output <dir>` | 输出目录 | `./docs` |
134
+ | `--leaf-only` | 只下载叶子节点 | `false` |
135
+ | `--no-cpp` | 排除 C++ 相关文档 | - |
136
+ | `--concurrency <n>` | 下载并发数 | `5` |
137
+ | `--dry-run` | 预览目录树,不下载 | `false` |
138
+ | `-s, --summary` | 生成 summary JSON 文件 | `true`(可用 `--no-summary` 禁用) |
139
+ | `-l, --localize` | 将文档中的远程链接替换为本地相对路径 | `false` |
140
+
141
+ ### tree 命令
142
+
143
+ | 参数 | 说明 | 默认值 |
144
+ |------|------|--------|
145
+ | `-c, --catalog <name>` | catalog 名称 | 批量模式(所有 catalog) |
146
+ | `-n, --node-name <name>` | 目标节点名称 | - |
147
+ | `-i, --node-id <id>` | 目标节点 ID | - |
148
+ | `-d, --depth <n>` | 显示深度限制 | - |
149
+ | `-o, --output <dir>` | JSON 输出目录 | `./docs` |
150
+ | `--no-cpp` | 排除 C++ 相关节点 | - |
151
+
152
+ ### wiki 命令
153
+
154
+ | 参数 | 说明 | 默认值 |
155
+ |------|------|--------|
156
+ | `-c, --config <path>` | 配置文件路径 | 包内 `wiki_config.json` |
157
+ | `-d, --docs <dir>` | 文档目录路径 | `./docs` |
158
+
159
+ ## 配置文件
160
+
161
+ ### wiki_config.json
162
+
163
+ Wiki 生成配置,定义 Kit 分类和主题分类。位于项目根目录,打包时会包含在 npm 包内。
164
+
165
+ ```json
166
+ {
167
+ "kitCategories": {
168
+ "Network_Kit": {
169
+ "zh": "网络服务",
170
+ "desc": "HTTP、WebSocket、Socket、网络管理等"
171
+ }
172
+ },
173
+ "topicCategories": {
174
+ "network": {
175
+ "zh": "网络与通信",
176
+ "desc": "HTTP、Socket、WebSocket、网络管理",
177
+ "patterns": ["网络", "HTTP", "Socket", "WebSocket"]
178
+ }
179
+ }
180
+ }
181
+ ```
182
+
183
+ - `kitCategories`: Kit 分类定义
184
+ - key: Kit 名称(如 `Network_Kit`)
185
+ - `zh`: 中文显示名
186
+ - `desc`: 描述
187
+ - `topicCategories`: 主题分类定义
188
+ - key: 主题名称(如 `network`)
189
+ - `zh`: 中文显示名
190
+ - `desc`: 描述
191
+ - `patterns`: 匹配模式(用于自动分类文档)
192
+
193
+ ## 开发
194
+
195
+ ```bash
196
+ npm run build # 编译
197
+ npm run start # 运行
198
+ ```
199
+
200
+ ## 项目结构
201
+
202
+ ```
203
+ src/
204
+ ├── index.ts # CLI 入口
205
+ ├── api-client.ts # API 请求封装
206
+ ├── common/
207
+ │ ├── types.ts # 共享类型定义
208
+ │ ├── config.ts # 配置文件加载
209
+ │ ├── tree-processor.ts # 树结构处理
210
+ │ ├── path-generator.ts # 路径和任务生成
211
+ │ └── tree-formatter.ts # 树形文本格式化
212
+ ├── download/
213
+ │ ├── index.ts # Download 命令入口
214
+ │ ├── downloader.ts # 下载调度
215
+ │ ├── summary-generator.ts # Summary 生成
216
+ │ ├── link-localizer.ts # 链接本地化
217
+ │ ├── markdown-converter.ts # HTML 转 Markdown
218
+ │ └── turndown-rules.ts # Turndown 规则
219
+ ├── tree/
220
+ │ └── index.ts # Tree 命令入口
221
+ └── wiki/
222
+ ├── index.ts # Wiki 命令入口
223
+ ├── wiki-generator.ts # Wiki 生成器
224
+ ├── wiki-types.ts # Wiki 类型
225
+ └── wiki-utils.ts # Wiki 工具函数
226
+ ```
227
+
228
+ ## License
229
+
230
+ Private
@@ -0,0 +1,44 @@
1
+ /** 文档内容数据结构 */
2
+ export interface DocumentContent {
3
+ title: string;
4
+ html: string;
5
+ objectId: string;
6
+ catalogName: string;
7
+ displayUpdateTime: string;
8
+ }
9
+ /**
10
+ * 从 URL 中提取 objectId
11
+ * 策略依次为:查询参数 objectId/id → 路径末尾段 → 倒数第二段
12
+ * @returns objectId 或 null
13
+ */
14
+ export declare function objectIdFromUrl(url: string): string | null;
15
+ /**
16
+ * 从 URL 路径中提取 catalogName(匹配 /doc/<catalogName>/ 模式)
17
+ * @returns catalogName 或 null
18
+ */
19
+ export declare function catalogNameFromUrl(url: string): string | null;
20
+ /**
21
+ * 根据 objectId 获取文档 HTML 内容和元信息
22
+ * @param objectId - 文档唯一标识
23
+ * @param language - 语言代码,默认 "cn"
24
+ * @returns 文档内容(title, html, catalogName, displayUpdateTime)
25
+ */
26
+ export declare function fetchDocument(objectId: string, language?: string): Promise<DocumentContent>;
27
+ /** 目录树节点(嵌套结构) */
28
+ export interface CatalogNode {
29
+ nodeId: string;
30
+ nodeName: string;
31
+ parent: string | null;
32
+ relateDocument: string | null;
33
+ children?: CatalogNode[];
34
+ isLeaf?: boolean;
35
+ }
36
+ /**
37
+ * 获取指定 catalog 的目录树(嵌套结构)
38
+ * @param catalogName - 目录分类名
39
+ * @param objectId - 可选,指定则返回该节点所在子树
40
+ * @returns 根节点数组
41
+ */
42
+ export declare function getCatalogTree(catalogName: string, objectId?: string): Promise<CatalogNode[]>;
43
+ /** 将 UTC 时间字符串转为北京时间 "YYYY-MM-DD HH:mm",输入为空则返回空串 */
44
+ export declare function formatUpdateTime(utcTimeStr: string): string;
@@ -0,0 +1,137 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.objectIdFromUrl = objectIdFromUrl;
4
+ exports.catalogNameFromUrl = catalogNameFromUrl;
5
+ exports.fetchDocument = fetchDocument;
6
+ exports.getCatalogTree = getCatalogTree;
7
+ exports.formatUpdateTime = formatUpdateTime;
8
+ const BASE_URL = "https://svc-drcn.developer.huawei.com/community/servlet";
9
+ const HEADERS = {
10
+ "Content-Type": "application/json",
11
+ Referer: "https://developer.huawei.com/consumer/cn/doc/",
12
+ "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36",
13
+ };
14
+ const REQUEST_TIMEOUT_MS = 15_000;
15
+ /**
16
+ * 向华为文档 API 发送 POST 请求,自动处理超时和错误码校验
17
+ * @param path - API 路径(不含 BASE_URL)
18
+ * @param body - 请求体
19
+ * @returns 响应数据
20
+ * @throws HTTP 非 2xx 或 API 返回错误码时抛出
21
+ */
22
+ async function post(path, body) {
23
+ const controller = new AbortController();
24
+ const timer = setTimeout(() => controller.abort(), REQUEST_TIMEOUT_MS);
25
+ try {
26
+ const res = await fetch(BASE_URL + path, {
27
+ method: "POST",
28
+ headers: HEADERS,
29
+ body: JSON.stringify(body),
30
+ signal: controller.signal,
31
+ });
32
+ if (!res.ok) {
33
+ throw new Error(`API request failed: ${res.status} ${res.statusText} for ${path}`);
34
+ }
35
+ const data = (await res.json());
36
+ if (data.code && data.code !== 0 && data.code !== "0") {
37
+ throw new Error(`API error [${data.code}]: ${data.message} for ${path}`);
38
+ }
39
+ return data;
40
+ }
41
+ finally {
42
+ clearTimeout(timer);
43
+ }
44
+ }
45
+ /**
46
+ * 从 URL 中提取 objectId
47
+ * 策略依次为:查询参数 objectId/id → 路径末尾段 → 倒数第二段
48
+ * @returns objectId 或 null
49
+ */
50
+ function objectIdFromUrl(url) {
51
+ try {
52
+ const parsed = new URL(url);
53
+ const pathname = parsed.pathname.replace(/\/$/, "");
54
+ const queryId = parsed.searchParams.get("objectId") || parsed.searchParams.get("id");
55
+ if (queryId)
56
+ return queryId;
57
+ const parts = pathname.split("/");
58
+ const lastSegment = parts[parts.length - 1];
59
+ if (lastSegment && lastSegment.length > 2)
60
+ return lastSegment;
61
+ if (parts.length >= 2) {
62
+ const secondLast = parts[parts.length - 2];
63
+ if (secondLast && secondLast.length > 2)
64
+ return secondLast;
65
+ }
66
+ return null;
67
+ }
68
+ catch {
69
+ return null;
70
+ }
71
+ }
72
+ /**
73
+ * 从 URL 路径中提取 catalogName(匹配 /doc/<catalogName>/ 模式)
74
+ * @returns catalogName 或 null
75
+ */
76
+ function catalogNameFromUrl(url) {
77
+ try {
78
+ const parsed = new URL(url);
79
+ const match = parsed.pathname.match(/\/doc\/([^/]+)/);
80
+ return match ? match[1] : null;
81
+ }
82
+ catch {
83
+ return null;
84
+ }
85
+ }
86
+ /**
87
+ * 根据 objectId 获取文档 HTML 内容和元信息
88
+ * @param objectId - 文档唯一标识
89
+ * @param language - 语言代码,默认 "cn"
90
+ * @returns 文档内容(title, html, catalogName, displayUpdateTime)
91
+ */
92
+ async function fetchDocument(objectId, language = "cn") {
93
+ const data = await post("/consumer/cn/documentPortal/getDocumentById", {
94
+ language,
95
+ objectId,
96
+ });
97
+ const v = data.value;
98
+ if (!v) {
99
+ throw new Error(`Empty response for objectId: ${objectId}`);
100
+ }
101
+ return {
102
+ title: v.title ?? "",
103
+ html: v.content?.content ?? "",
104
+ objectId,
105
+ catalogName: v.catalogName ?? "",
106
+ displayUpdateTime: v.displayUpdateTime ?? "",
107
+ };
108
+ }
109
+ /**
110
+ * 获取指定 catalog 的目录树(嵌套结构)
111
+ * @param catalogName - 目录分类名
112
+ * @param objectId - 可选,指定则返回该节点所在子树
113
+ * @returns 根节点数组
114
+ */
115
+ async function getCatalogTree(catalogName, objectId) {
116
+ const body = { language: "cn", catalogName };
117
+ if (objectId)
118
+ body.objectId = objectId;
119
+ const data = await post("/consumer/cn/documentPortal/getCatalogTree", body);
120
+ return data.value?.catalogTreeList ?? [];
121
+ }
122
+ // --- 时间格式化 ---
123
+ /** 将 UTC 时间字符串转为北京时间 "YYYY-MM-DD HH:mm",输入为空则返回空串 */
124
+ function formatUpdateTime(utcTimeStr) {
125
+ if (!utcTimeStr)
126
+ return "";
127
+ const dt = new Date(utcTimeStr.replace(" ", "T") + "Z");
128
+ if (isNaN(dt.getTime()))
129
+ return utcTimeStr;
130
+ const bj = new Date(dt.getTime() + 8 * 60 * 60 * 1000);
131
+ const y = bj.getUTCFullYear();
132
+ const m = String(bj.getUTCMonth() + 1).padStart(2, "0");
133
+ const d = String(bj.getUTCDate()).padStart(2, "0");
134
+ const h = String(bj.getUTCHours()).padStart(2, "0");
135
+ const min = String(bj.getUTCMinutes()).padStart(2, "0");
136
+ return `${y}-${m}-${d} ${h}:${min}`;
137
+ }
@@ -0,0 +1,11 @@
1
+ import type { TopLevelCatalog, CatalogWithTopLevel } from "./types.js";
2
+ /** 加载 docs_catalog.json 配置文件 */
3
+ export declare function loadDocsCatalogConfig(): TopLevelCatalog[];
4
+ /** 根据 catalogName 查找对应的 top_level */
5
+ export declare function findTopLevelForCatalog(catalogName: string): string | undefined;
6
+ /** 根据 catalogName 查找对应的中文名称(name 字段) */
7
+ export declare function findCatalogName(catalogName: string): string | undefined;
8
+ /** 获取配置中所有 catalog 信息(包含 top_level) */
9
+ export declare function getAllCatalogsWithTopLevel(): CatalogWithTopLevel[];
10
+ /** 获取所有已知的 catalog ID 列表 */
11
+ export declare function getAllCatalogIds(): string[];
@@ -0,0 +1,70 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.loadDocsCatalogConfig = loadDocsCatalogConfig;
4
+ exports.findTopLevelForCatalog = findTopLevelForCatalog;
5
+ exports.findCatalogName = findCatalogName;
6
+ exports.getAllCatalogsWithTopLevel = getAllCatalogsWithTopLevel;
7
+ exports.getAllCatalogIds = getAllCatalogIds;
8
+ /**
9
+ * 配置文件加载模块
10
+ *
11
+ * 职责:
12
+ * 1. 加载 docs_catalog.json 配置文件
13
+ * 2. 根据 catalogName 查找对应的 top_level
14
+ * 3. 获取所有 catalog 信息(包含 top_level)
15
+ * 4. 获取 catalog 的中文名称
16
+ */
17
+ const node_fs_1 = require("node:fs");
18
+ const node_path_1 = require("node:path");
19
+ /** 加载 docs_catalog.json 配置文件 */
20
+ function loadDocsCatalogConfig() {
21
+ const configPath = (0, node_path_1.join)(__dirname, "..", "..", "docs_catalog.json");
22
+ const content = (0, node_fs_1.readFileSync)(configPath, "utf-8");
23
+ return JSON.parse(content);
24
+ }
25
+ /** 根据 catalogName 查找对应的 top_level */
26
+ function findTopLevelForCatalog(catalogName) {
27
+ const config = loadDocsCatalogConfig();
28
+ for (const topLevel of config) {
29
+ for (const catalog of topLevel.catalogs) {
30
+ if (catalog.id === catalogName) {
31
+ return topLevel.top_level;
32
+ }
33
+ }
34
+ }
35
+ return undefined;
36
+ }
37
+ /** 根据 catalogName 查找对应的中文名称(name 字段) */
38
+ function findCatalogName(catalogName) {
39
+ const config = loadDocsCatalogConfig();
40
+ for (const topLevel of config) {
41
+ for (const catalog of topLevel.catalogs) {
42
+ if (catalog.id === catalogName) {
43
+ return catalog.name;
44
+ }
45
+ }
46
+ }
47
+ return undefined;
48
+ }
49
+ /** 获取配置中所有 catalog 信息(包含 top_level) */
50
+ function getAllCatalogsWithTopLevel() {
51
+ const config = loadDocsCatalogConfig();
52
+ const result = [];
53
+ for (const topLevel of config) {
54
+ for (const catalog of topLevel.catalogs) {
55
+ result.push({ topLevel: topLevel.top_level, catalog });
56
+ }
57
+ }
58
+ return result;
59
+ }
60
+ /** 获取所有已知的 catalog ID 列表 */
61
+ function getAllCatalogIds() {
62
+ const config = loadDocsCatalogConfig();
63
+ const result = [];
64
+ for (const topLevel of config) {
65
+ for (const catalog of topLevel.catalogs) {
66
+ result.push(catalog.id);
67
+ }
68
+ }
69
+ return result;
70
+ }
@@ -0,0 +1,39 @@
1
+ import type { FlatNode, OutputTask } from "./types.js";
2
+ /** 将文件/目录名中的非法字符及空格替换为下划线 */
3
+ export declare function safeFileName(name: string): string;
4
+ /**
5
+ * 计算输出路径并生成下载任务列表
6
+ *
7
+ * @param nodes - 全量平铺节点(用于路径计算)
8
+ * @param rootId - 指定子树根节点 ID,undefined 表示整个 catalog
9
+ * @param catalogName - catalog 名称
10
+ * @param outputBase - 输出根目录
11
+ * @param taskNodes - 需要生成任务的节点子集(如经过 --no-cpp 过滤后的)
12
+ * @returns 下载任务列表
13
+ */
14
+ export declare function buildOutputPaths(nodes: FlatNode[], rootId: string | undefined, catalogName: string, outputBase: string, taskNodes?: FlatNode[]): OutputTask[];
15
+ /**
16
+ * 收集输出所需的全部目录路径(去重、按深度排序)
17
+ *
18
+ * @param nodes - 全量平铺节点
19
+ * @param rootId - 指定子树根节点 ID
20
+ * @param catalogName - catalog 名称
21
+ * @param outputBase - 输出根目录
22
+ * @param taskNodes - 需要创建目录的节点子集
23
+ * @returns 目录路径数组,按深度从浅到深排序
24
+ */
25
+ export declare function collectDirectories(nodes: FlatNode[], rootId: string | undefined, catalogName: string, outputBase: string, taskNodes?: FlatNode[]): string[];
26
+ /**
27
+ * 保存目录树 JSON 文件(参考 fetch_catalog.py)
28
+ * 输出两个文件:{catalog}_tree.json(原始树结构)和 {catalog}_nodes.json(平铺节点)
29
+ *
30
+ * @param catalogName - catalog 名称
31
+ * @param outputDir - 输出目录路径
32
+ * @returns 保存的文件路径
33
+ */
34
+ export declare function saveCatalogJson(catalogName: string, outputDir: string): Promise<{
35
+ treePath: string;
36
+ flatPath: string;
37
+ treeCount: number;
38
+ flatCount: number;
39
+ }>;