feishu-docs-cli 0.1.0-beta.9 → 1.0.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 +25 -9
- package/README.zh.md +8 -9
- package/dist/auth.js +31 -17
- package/dist/auth.js.map +1 -1
- package/dist/cli.js +5 -4
- package/dist/cli.js.map +1 -1
- package/dist/client.d.ts +4 -2
- package/dist/client.js +177 -61
- package/dist/client.js.map +1 -1
- package/dist/commands/authorize.d.ts +3 -0
- package/dist/commands/authorize.js +16 -34
- package/dist/commands/authorize.js.map +1 -1
- package/dist/commands/cp.js +44 -30
- package/dist/commands/cp.js.map +1 -1
- package/dist/commands/create.js +21 -7
- package/dist/commands/create.js.map +1 -1
- package/dist/commands/delete.js +53 -54
- package/dist/commands/delete.js.map +1 -1
- package/dist/commands/login.js +6 -2
- package/dist/commands/login.js.map +1 -1
- package/dist/commands/ls.js +38 -38
- package/dist/commands/ls.js.map +1 -1
- package/dist/commands/mkdir.js +25 -25
- package/dist/commands/mkdir.js.map +1 -1
- package/dist/commands/mv.d.ts +2 -2
- package/dist/commands/mv.js +45 -40
- package/dist/commands/mv.js.map +1 -1
- package/dist/commands/read.d.ts +1 -1
- package/dist/commands/read.js +17 -354
- package/dist/commands/read.js.map +1 -1
- package/dist/commands/search.js +57 -55
- package/dist/commands/search.js.map +1 -1
- package/dist/commands/share.js +135 -133
- package/dist/commands/share.js.map +1 -1
- package/dist/commands/update.js +43 -60
- package/dist/commands/update.js.map +1 -1
- package/dist/commands/wiki.js +8 -20
- package/dist/commands/wiki.js.map +1 -1
- package/dist/parser/block-types.d.ts +0 -1
- package/dist/parser/block-types.js +0 -22
- package/dist/parser/block-types.js.map +1 -1
- package/dist/parser/blocks-to-md.d.ts +10 -18
- package/dist/parser/blocks-to-md.js +341 -450
- package/dist/parser/blocks-to-md.js.map +1 -1
- package/dist/scopes.d.ts +5 -47
- package/dist/scopes.js +9 -54
- package/dist/scopes.js.map +1 -1
- package/dist/services/block-writer.d.ts +3 -2
- package/dist/services/block-writer.js +29 -13
- package/dist/services/block-writer.js.map +1 -1
- package/dist/services/doc-blocks.d.ts +1 -1
- package/dist/services/doc-blocks.js +1 -1
- package/dist/services/doc-blocks.js.map +1 -1
- package/dist/services/doc-enrichment.d.ts +64 -0
- package/dist/services/doc-enrichment.js +397 -0
- package/dist/services/doc-enrichment.js.map +1 -0
- package/dist/services/image-download.d.ts +31 -0
- package/dist/services/image-download.js +127 -0
- package/dist/services/image-download.js.map +1 -0
- package/dist/services/markdown-convert.d.ts +20 -0
- package/dist/services/markdown-convert.js +55 -1
- package/dist/services/markdown-convert.js.map +1 -1
- package/dist/services/wiki-nodes.d.ts +1 -1
- package/dist/services/wiki-nodes.js +2 -3
- package/dist/services/wiki-nodes.js.map +1 -1
- package/dist/types/api-responses.d.ts +34 -0
- package/dist/types/api-responses.js +8 -0
- package/dist/types/api-responses.js.map +1 -0
- package/dist/types/index.d.ts +9 -17
- package/dist/utils/concurrency.d.ts +12 -0
- package/dist/utils/concurrency.js +37 -0
- package/dist/utils/concurrency.js.map +1 -0
- package/dist/utils/errors.d.ts +3 -1
- package/dist/utils/errors.js +11 -7
- package/dist/utils/errors.js.map +1 -1
- package/dist/utils/retry.d.ts +49 -0
- package/dist/utils/retry.js +70 -0
- package/dist/utils/retry.js.map +1 -0
- package/dist/utils/scope-prompt.d.ts +23 -18
- package/dist/utils/scope-prompt.js +62 -51
- package/dist/utils/scope-prompt.js.map +1 -1
- package/package.json +3 -1
- package/skills/feishu-docs/SKILL.md +22 -2
package/dist/commands/share.js
CHANGED
|
@@ -3,8 +3,7 @@
|
|
|
3
3
|
*/
|
|
4
4
|
import { createClient, fetchWithAuth } from "../client.js";
|
|
5
5
|
import { CliError } from "../utils/errors.js";
|
|
6
|
-
import {
|
|
7
|
-
import { ensureScopes } from "../utils/scope-prompt.js";
|
|
6
|
+
import { withScopeRecovery } from "../utils/scope-prompt.js";
|
|
8
7
|
import { resolveDocument } from "../utils/document-resolver.js";
|
|
9
8
|
import { validateMemberId, detectMemberType } from "../utils/member.js";
|
|
10
9
|
import { mapToDriveType } from "../utils/drive-types.js";
|
|
@@ -80,43 +79,42 @@ export function mapPublicMode(mode, role = "view") {
|
|
|
80
79
|
throw new CliError("INVALID_ARGS", `无效的公开模式: ${mode}。可选值: closed, tenant, open`);
|
|
81
80
|
}
|
|
82
81
|
/**
|
|
83
|
-
*
|
|
82
|
+
* Resolve document and determine share context.
|
|
83
|
+
* No pre-flight scope checks — scope errors are handled reactively by withScopeRecovery.
|
|
84
84
|
*/
|
|
85
|
-
async function
|
|
86
|
-
return ensureScopes(authInfo, FEATURE_SCOPE_GROUPS.drive.scopes, globalOpts);
|
|
87
|
-
}
|
|
88
|
-
async function resolveDocForShare(authInfo, input) {
|
|
85
|
+
async function resolveShareContext(authInfo, input) {
|
|
89
86
|
const doc = await resolveDocument(authInfo, input);
|
|
90
|
-
|
|
91
|
-
const token =
|
|
92
|
-
const type =
|
|
93
|
-
return { token, type, doc };
|
|
87
|
+
const isWiki = Boolean(doc.spaceId);
|
|
88
|
+
const token = isWiki ? doc.parsed.token : doc.objToken;
|
|
89
|
+
const type = isWiki ? "wiki" : mapToDriveType(doc.objType);
|
|
90
|
+
return { token, type, authInfo, doc };
|
|
94
91
|
}
|
|
95
92
|
async function list(args, globalOpts) {
|
|
96
93
|
const input = args.positionals[0];
|
|
97
94
|
if (!input) {
|
|
98
95
|
throw new CliError("INVALID_ARGS", "缺少文档 URL 或 token。用法: feishu-docs share list <url>");
|
|
99
96
|
}
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
97
|
+
return withScopeRecovery(async () => {
|
|
98
|
+
const { authInfo: rawAuthInfo } = await createClient(globalOpts);
|
|
99
|
+
const { token, type, authInfo } = await resolveShareContext(rawAuthInfo, input);
|
|
100
|
+
const res = await fetchWithAuth(authInfo, `/open-apis/drive/v1/permissions/${encodeURIComponent(token)}/members`, { params: { type } });
|
|
101
|
+
const shareResData = res?.data;
|
|
102
|
+
const members = (shareResData?.members || []);
|
|
103
|
+
if (globalOpts.json) {
|
|
104
|
+
process.stdout.write(JSON.stringify({ success: true, members }, null, 2) + "\n");
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
if (members.length === 0) {
|
|
108
|
+
process.stdout.write("没有协作者\n");
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
for (const m of members) {
|
|
112
|
+
const name = m.member_name || m.member_id || "(未知)";
|
|
113
|
+
const perm = m.perm || "unknown";
|
|
114
|
+
const memberType = m.member_type || "";
|
|
115
|
+
process.stdout.write(` ${name} [${perm}] (${memberType}: ${m.member_id})\n`);
|
|
116
|
+
}
|
|
117
|
+
}, globalOpts);
|
|
120
118
|
}
|
|
121
119
|
async function add(args, globalOpts) {
|
|
122
120
|
const input = args.positionals[0];
|
|
@@ -125,44 +123,45 @@ async function add(args, globalOpts) {
|
|
|
125
123
|
throw new CliError("INVALID_ARGS", "用法: feishu-docs share add <url> <member> --role <role>");
|
|
126
124
|
}
|
|
127
125
|
validateMemberId(memberId);
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
params: { type },
|
|
137
|
-
body: { member_type: memberType, member_id: memberId, perm },
|
|
138
|
-
});
|
|
139
|
-
}
|
|
140
|
-
catch (err) {
|
|
141
|
-
// Error 1201003: member already exists → fallback to update
|
|
142
|
-
const code = err?.apiCode ||
|
|
143
|
-
err?.code;
|
|
144
|
-
if (code === 1201003) {
|
|
145
|
-
await fetchWithAuth(authInfo, `/open-apis/drive/v1/permissions/${encodeURIComponent(token)}/members/${encodeURIComponent(memberId)}`, {
|
|
146
|
-
method: "PUT",
|
|
126
|
+
return withScopeRecovery(async () => {
|
|
127
|
+
const { authInfo: rawAuthInfo } = await createClient(globalOpts);
|
|
128
|
+
const { token, type, authInfo } = await resolveShareContext(rawAuthInfo, input);
|
|
129
|
+
const memberType = detectMemberType(memberId);
|
|
130
|
+
const perm = mapRole(args.role || "view");
|
|
131
|
+
try {
|
|
132
|
+
await fetchWithAuth(authInfo, `/open-apis/drive/v1/permissions/${encodeURIComponent(token)}/members`, {
|
|
133
|
+
method: "POST",
|
|
147
134
|
params: { type },
|
|
148
|
-
body: { member_type: memberType, perm },
|
|
135
|
+
body: { member_type: memberType, member_id: memberId, perm },
|
|
149
136
|
});
|
|
150
137
|
}
|
|
138
|
+
catch (err) {
|
|
139
|
+
// Error 1201003: member already exists → fallback to update
|
|
140
|
+
const code = err?.apiCode ||
|
|
141
|
+
err?.code;
|
|
142
|
+
if (code === 1201003) {
|
|
143
|
+
await fetchWithAuth(authInfo, `/open-apis/drive/v1/permissions/${encodeURIComponent(token)}/members/${encodeURIComponent(memberId)}`, {
|
|
144
|
+
method: "PUT",
|
|
145
|
+
params: { type },
|
|
146
|
+
body: { member_type: memberType, perm },
|
|
147
|
+
});
|
|
148
|
+
}
|
|
149
|
+
else {
|
|
150
|
+
throw err;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
if (globalOpts.json) {
|
|
154
|
+
process.stdout.write(JSON.stringify({
|
|
155
|
+
success: true,
|
|
156
|
+
member_id: memberId,
|
|
157
|
+
member_type: memberType,
|
|
158
|
+
perm,
|
|
159
|
+
}) + "\n");
|
|
160
|
+
}
|
|
151
161
|
else {
|
|
152
|
-
|
|
162
|
+
process.stdout.write(`已添加协作者 ${memberId} (${perm})\n`);
|
|
153
163
|
}
|
|
154
|
-
}
|
|
155
|
-
if (globalOpts.json) {
|
|
156
|
-
process.stdout.write(JSON.stringify({
|
|
157
|
-
success: true,
|
|
158
|
-
member_id: memberId,
|
|
159
|
-
member_type: memberType,
|
|
160
|
-
perm,
|
|
161
|
-
}) + "\n");
|
|
162
|
-
}
|
|
163
|
-
else {
|
|
164
|
-
process.stdout.write(`已添加协作者 ${memberId} (${perm})\n`);
|
|
165
|
-
}
|
|
164
|
+
}, globalOpts);
|
|
166
165
|
}
|
|
167
166
|
async function remove(args, globalOpts) {
|
|
168
167
|
const input = args.positionals[0];
|
|
@@ -171,25 +170,26 @@ async function remove(args, globalOpts) {
|
|
|
171
170
|
throw new CliError("INVALID_ARGS", "用法: feishu-docs share remove <url> <member>");
|
|
172
171
|
}
|
|
173
172
|
validateMemberId(memberId);
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
173
|
+
return withScopeRecovery(async () => {
|
|
174
|
+
const { authInfo: rawAuthInfo } = await createClient(globalOpts);
|
|
175
|
+
const { token, type, authInfo } = await resolveShareContext(rawAuthInfo, input);
|
|
176
|
+
const memberType = detectMemberType(memberId);
|
|
177
|
+
await fetchWithAuth(authInfo, `/open-apis/drive/v1/permissions/${encodeURIComponent(token)}/members/${encodeURIComponent(memberId)}`, {
|
|
178
|
+
method: "DELETE",
|
|
179
|
+
params: { type, member_type: memberType },
|
|
180
|
+
});
|
|
181
|
+
if (globalOpts.json) {
|
|
182
|
+
process.stdout.write(JSON.stringify({
|
|
183
|
+
success: true,
|
|
184
|
+
member_id: memberId,
|
|
185
|
+
member_type: memberType,
|
|
186
|
+
action: "removed",
|
|
187
|
+
}) + "\n");
|
|
188
|
+
}
|
|
189
|
+
else {
|
|
190
|
+
process.stdout.write(`已移除协作者 ${memberId}\n`);
|
|
191
|
+
}
|
|
192
|
+
}, globalOpts);
|
|
193
193
|
}
|
|
194
194
|
async function update(args, globalOpts) {
|
|
195
195
|
const input = args.positionals[0];
|
|
@@ -201,27 +201,28 @@ async function update(args, globalOpts) {
|
|
|
201
201
|
throw new CliError("INVALID_ARGS", "缺少 --role 参数。可选值: view, edit, manage");
|
|
202
202
|
}
|
|
203
203
|
validateMemberId(memberId);
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
204
|
+
return withScopeRecovery(async () => {
|
|
205
|
+
const { authInfo: rawAuthInfo } = await createClient(globalOpts);
|
|
206
|
+
const { token, type, authInfo } = await resolveShareContext(rawAuthInfo, input);
|
|
207
|
+
const memberType = detectMemberType(memberId);
|
|
208
|
+
const perm = mapRole(args.role);
|
|
209
|
+
await fetchWithAuth(authInfo, `/open-apis/drive/v1/permissions/${encodeURIComponent(token)}/members/${encodeURIComponent(memberId)}`, {
|
|
210
|
+
method: "PUT",
|
|
211
|
+
params: { type },
|
|
212
|
+
body: { member_type: memberType, perm },
|
|
213
|
+
});
|
|
214
|
+
if (globalOpts.json) {
|
|
215
|
+
process.stdout.write(JSON.stringify({
|
|
216
|
+
success: true,
|
|
217
|
+
member_id: memberId,
|
|
218
|
+
member_type: memberType,
|
|
219
|
+
perm,
|
|
220
|
+
}) + "\n");
|
|
221
|
+
}
|
|
222
|
+
else {
|
|
223
|
+
process.stdout.write(`已更新协作者 ${memberId} 权限为 ${perm}\n`);
|
|
224
|
+
}
|
|
225
|
+
}, globalOpts);
|
|
225
226
|
}
|
|
226
227
|
async function set(args, globalOpts) {
|
|
227
228
|
const input = args.positionals[0];
|
|
@@ -231,34 +232,35 @@ async function set(args, globalOpts) {
|
|
|
231
232
|
if (!args.public) {
|
|
232
233
|
throw new CliError("INVALID_ARGS", "缺少 --public 参数。可选值: closed, tenant, open");
|
|
233
234
|
}
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
235
|
+
return withScopeRecovery(async () => {
|
|
236
|
+
const { authInfo: rawAuthInfo } = await createClient(globalOpts);
|
|
237
|
+
const { token, type, authInfo } = await resolveShareContext(rawAuthInfo, input);
|
|
238
|
+
// Extract optional role from --public value like "tenant:edit"
|
|
239
|
+
let mode = args.public;
|
|
240
|
+
let shareRole = "view";
|
|
241
|
+
if (mode.includes(":")) {
|
|
242
|
+
const parts = mode.split(":");
|
|
243
|
+
mode = parts[0];
|
|
244
|
+
shareRole = parts[1] || "view";
|
|
245
|
+
}
|
|
246
|
+
if (shareRole !== "view" && shareRole !== "edit") {
|
|
247
|
+
throw new CliError("INVALID_ARGS", `无效的分享角色: ${shareRole}。可选值: view, edit(如 tenant:edit)`);
|
|
248
|
+
}
|
|
249
|
+
const linkShareEntity = mapPublicMode(mode, shareRole);
|
|
250
|
+
await fetchWithAuth(authInfo, `/open-apis/drive/v1/permissions/${encodeURIComponent(token)}/public`, {
|
|
251
|
+
method: "PATCH",
|
|
252
|
+
params: { type },
|
|
253
|
+
body: { link_share_entity: linkShareEntity },
|
|
254
|
+
});
|
|
255
|
+
if (globalOpts.json) {
|
|
256
|
+
process.stdout.write(JSON.stringify({
|
|
257
|
+
success: true,
|
|
258
|
+
link_share_entity: linkShareEntity,
|
|
259
|
+
}) + "\n");
|
|
260
|
+
}
|
|
261
|
+
else {
|
|
262
|
+
process.stdout.write(`已修改分享设置为 ${linkShareEntity}\n`);
|
|
263
|
+
}
|
|
264
|
+
}, globalOpts);
|
|
263
265
|
}
|
|
264
266
|
//# sourceMappingURL=share.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"share.js","sourceRoot":"","sources":["../../src/commands/share.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAC3D,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC9C,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"share.js","sourceRoot":"","sources":["../../src/commands/share.ts"],"names":[],"mappings":"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"}
|
package/dist/commands/update.js
CHANGED
|
@@ -4,15 +4,14 @@
|
|
|
4
4
|
* Uses Convert + Descendant API for writing new content.
|
|
5
5
|
* Restore uses the old children API (backup data is raw blocks, not markdown).
|
|
6
6
|
*/
|
|
7
|
-
import { readFile
|
|
7
|
+
import { readFile } from "node:fs/promises";
|
|
8
8
|
import { existsSync } from "node:fs";
|
|
9
9
|
import { resolve, normalize, sep } from "node:path";
|
|
10
|
-
import { randomUUID } from "node:crypto";
|
|
11
10
|
import { createClient, fetchWithAuth } from "../client.js";
|
|
12
11
|
import { CliError } from "../utils/errors.js";
|
|
13
|
-
import { convertAndWrite } from "../services/markdown-convert.js";
|
|
12
|
+
import { convertAndWrite, extractMarkdownTitle, sanitizeBlocks, writeDescendant, } from "../services/markdown-convert.js";
|
|
14
13
|
import { resolveDocument } from "../utils/document-resolver.js";
|
|
15
|
-
import { readBody, getDocumentInfo, clearDocument, backupDocument,
|
|
14
|
+
import { readBody, getDocumentInfo, clearDocument, backupDocument, getBackupsDir, } from "../services/block-writer.js";
|
|
16
15
|
export const meta = {
|
|
17
16
|
options: {
|
|
18
17
|
body: { type: "string" },
|
|
@@ -46,7 +45,7 @@ export async function update(args, globalOpts) {
|
|
|
46
45
|
if (args.append) {
|
|
47
46
|
return appendToDocument(authInfo, documentId, bodyContent, globalOpts);
|
|
48
47
|
}
|
|
49
|
-
return overwriteDocument(authInfo, documentId, bodyContent, globalOpts);
|
|
48
|
+
return overwriteDocument(authInfo, documentId, bodyContent, globalOpts, doc.spaceId, doc.nodeToken);
|
|
50
49
|
}
|
|
51
50
|
async function appendToDocument(authInfo, documentId, bodyContent, globalOpts) {
|
|
52
51
|
const docInfo = await getDocumentInfo(authInfo, documentId);
|
|
@@ -62,7 +61,10 @@ async function appendToDocument(authInfo, documentId, bodyContent, globalOpts) {
|
|
|
62
61
|
process.stdout.write(`已追加内容到文档 ${documentId}\n`);
|
|
63
62
|
}
|
|
64
63
|
}
|
|
65
|
-
async function overwriteDocument(authInfo, documentId, bodyContent, globalOpts) {
|
|
64
|
+
async function overwriteDocument(authInfo, documentId, bodyContent, globalOpts, spaceId, nodeToken) {
|
|
65
|
+
// Extract first H1 heading as document title, strip from body
|
|
66
|
+
const { title: extractedTitle, body: strippedBody } = extractMarkdownTitle(bodyContent);
|
|
67
|
+
const contentToWrite = strippedBody.trim() || undefined;
|
|
66
68
|
let backupPath;
|
|
67
69
|
try {
|
|
68
70
|
const backup = await backupDocument(authInfo, documentId);
|
|
@@ -82,7 +84,10 @@ async function overwriteDocument(authInfo, documentId, bodyContent, globalOpts)
|
|
|
82
84
|
throw err;
|
|
83
85
|
}
|
|
84
86
|
try {
|
|
85
|
-
|
|
87
|
+
// Write body content first (if any), then update title
|
|
88
|
+
if (contentToWrite) {
|
|
89
|
+
rev = await convertAndWrite(authInfo, documentId, contentToWrite, rev);
|
|
90
|
+
}
|
|
86
91
|
}
|
|
87
92
|
catch (err) {
|
|
88
93
|
process.stderr.write(`feishu-docs: error: 写入新内容失败,尝试从备份恢复...\n`);
|
|
@@ -97,13 +102,29 @@ async function overwriteDocument(authInfo, documentId, bodyContent, globalOpts)
|
|
|
97
102
|
}
|
|
98
103
|
throw err;
|
|
99
104
|
}
|
|
100
|
-
//
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
105
|
+
// Update document title after successful content write
|
|
106
|
+
if (extractedTitle) {
|
|
107
|
+
try {
|
|
108
|
+
if (spaceId && nodeToken) {
|
|
109
|
+
// Wiki documents use the wiki node rename API
|
|
110
|
+
await fetchWithAuth(authInfo, `/open-apis/wiki/v2/spaces/${encodeURIComponent(spaceId)}/nodes/${encodeURIComponent(nodeToken)}/update_title`, {
|
|
111
|
+
method: "POST",
|
|
112
|
+
body: { title: extractedTitle },
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
else {
|
|
116
|
+
// Drive documents use the docx PATCH API
|
|
117
|
+
await fetchWithAuth(authInfo, `/open-apis/docx/v1/documents/${encodeURIComponent(documentId)}`, {
|
|
118
|
+
method: "PATCH",
|
|
119
|
+
body: { title: extractedTitle },
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
catch {
|
|
124
|
+
process.stderr.write(`feishu-docs: warning: 更新文档标题失败,标题可能未同步\n`);
|
|
125
|
+
}
|
|
106
126
|
}
|
|
127
|
+
// Backup kept for undo — rotateBackups() in backupDocument handles cleanup
|
|
107
128
|
if (globalOpts.json) {
|
|
108
129
|
process.stdout.write(JSON.stringify({
|
|
109
130
|
success: true,
|
|
@@ -115,53 +136,9 @@ async function overwriteDocument(authInfo, documentId, bodyContent, globalOpts)
|
|
|
115
136
|
process.stdout.write(`已覆盖更新文档 ${documentId}\n`);
|
|
116
137
|
}
|
|
117
138
|
}
|
|
118
|
-
/**
|
|
119
|
-
* Recursively restore blocks and their descendants from a backup block map.
|
|
120
|
-
* Uses the old children API (backup data is raw blocks, not markdown).
|
|
121
|
-
*/
|
|
122
|
-
const MAX_RESTORE_DEPTH = 20;
|
|
123
|
-
async function restoreChildren(authInfo, documentId, parentBlockId, childIds, blockMap, revisionId, depth = 0) {
|
|
124
|
-
let rev = revisionId;
|
|
125
|
-
if (!childIds || childIds.length === 0)
|
|
126
|
-
return rev;
|
|
127
|
-
if (depth >= MAX_RESTORE_DEPTH) {
|
|
128
|
-
process.stderr.write(`feishu-docs: warning: 恢复深度超过 ${MAX_RESTORE_DEPTH} 层,跳过更深层级\n`);
|
|
129
|
-
return rev;
|
|
130
|
-
}
|
|
131
|
-
for (let i = 0; i < childIds.length; i += BATCH_SIZE) {
|
|
132
|
-
const batchIds = childIds.slice(i, i + BATCH_SIZE);
|
|
133
|
-
const batch = batchIds
|
|
134
|
-
.map((id) => blockMap.get(id))
|
|
135
|
-
.filter(Boolean)
|
|
136
|
-
.map((b) => {
|
|
137
|
-
const { block_id, parent_id, children, ...rest } = b;
|
|
138
|
-
return rest;
|
|
139
|
-
});
|
|
140
|
-
if (batch.length === 0)
|
|
141
|
-
continue;
|
|
142
|
-
if (i > 0)
|
|
143
|
-
await sleep(QPS_DELAY);
|
|
144
|
-
const res = await fetchWithAuth(authInfo, `/open-apis/docx/v1/documents/${encodeURIComponent(documentId)}/blocks/${encodeURIComponent(parentBlockId)}/children`, {
|
|
145
|
-
method: "POST",
|
|
146
|
-
body: { children: batch, index: i },
|
|
147
|
-
params: { document_revision_id: rev, client_token: randomUUID() },
|
|
148
|
-
});
|
|
149
|
-
const resData = res?.data;
|
|
150
|
-
rev = resData?.document_revision_id ?? rev;
|
|
151
|
-
const createdIds = (resData?.children ?? []).map((c) => c.block_id);
|
|
152
|
-
for (let j = 0; j < createdIds.length && j < batchIds.length; j++) {
|
|
153
|
-
const original = blockMap.get(batchIds[j]);
|
|
154
|
-
if (original?.children?.length && original.children.length > 0) {
|
|
155
|
-
await sleep(QPS_DELAY);
|
|
156
|
-
rev = await restoreChildren(authInfo, documentId, createdIds[j], original.children, blockMap, rev, depth + 1);
|
|
157
|
-
}
|
|
158
|
-
}
|
|
159
|
-
}
|
|
160
|
-
return rev;
|
|
161
|
-
}
|
|
162
139
|
async function restoreFromBackup(authInfo, documentId, backupPath, globalOpts) {
|
|
163
140
|
const resolvedPath = resolve(normalize(backupPath));
|
|
164
|
-
const resolvedBackups = resolve(
|
|
141
|
+
const resolvedBackups = resolve(getBackupsDir());
|
|
165
142
|
if (!resolvedPath.startsWith(resolvedBackups + sep)) {
|
|
166
143
|
throw new CliError("INVALID_ARGS", `备份文件必须位于 ${resolvedBackups} 目录下`, { recovery: `请使用 ${resolvedBackups} 下的备份文件路径` });
|
|
167
144
|
}
|
|
@@ -191,11 +168,17 @@ async function restoreFromBackup(authInfo, documentId, backupPath, globalOpts) {
|
|
|
191
168
|
process.stderr.write("feishu-docs: warning: 备份文件中没有可恢复的内容\n");
|
|
192
169
|
return;
|
|
193
170
|
}
|
|
194
|
-
|
|
171
|
+
// Build ConvertedBlocks for Descendant API (supports all block types)
|
|
172
|
+
const allBlocks = sanitizeBlocks(blocks.filter((b) => b.block_type !== 1));
|
|
173
|
+
const converted = {
|
|
174
|
+
blocks: allBlocks,
|
|
175
|
+
firstLevelBlockIds: topLevelIds,
|
|
176
|
+
blockIdToImageUrls: {},
|
|
177
|
+
};
|
|
195
178
|
const docInfo = await getDocumentInfo(authInfo, documentId);
|
|
196
179
|
let rev = await clearDocument(authInfo, documentId, docInfo.revisionId);
|
|
197
180
|
try {
|
|
198
|
-
rev = await
|
|
181
|
+
rev = await writeDescendant(authInfo, documentId, documentId, converted, rev);
|
|
199
182
|
}
|
|
200
183
|
catch (restoreErr) {
|
|
201
184
|
process.stderr.write(`feishu-docs: error: 恢复过程中出错: ${restoreErr.message}\n` +
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"update.js","sourceRoot":"","sources":["../../src/commands/update.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"update.js","sourceRoot":"","sources":["../../src/commands/update.ts"],"names":[],"mappings":"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"}
|