feishu-docs-cli 0.1.0-beta.10

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 (120) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +403 -0
  3. package/README.zh.md +402 -0
  4. package/bin/feishu-docs.js +8 -0
  5. package/dist/auth.d.ts +76 -0
  6. package/dist/auth.js +512 -0
  7. package/dist/auth.js.map +1 -0
  8. package/dist/cli.d.ts +5 -0
  9. package/dist/cli.js +197 -0
  10. package/dist/cli.js.map +1 -0
  11. package/dist/client.d.ts +28 -0
  12. package/dist/client.js +256 -0
  13. package/dist/client.js.map +1 -0
  14. package/dist/commands/authorize.d.ts +12 -0
  15. package/dist/commands/authorize.js +73 -0
  16. package/dist/commands/authorize.js.map +1 -0
  17. package/dist/commands/cat.d.ts +6 -0
  18. package/dist/commands/cat.js +159 -0
  19. package/dist/commands/cat.js.map +1 -0
  20. package/dist/commands/cp.d.ts +9 -0
  21. package/dist/commands/cp.js +70 -0
  22. package/dist/commands/cp.js.map +1 -0
  23. package/dist/commands/create.d.ts +6 -0
  24. package/dist/commands/create.js +120 -0
  25. package/dist/commands/create.js.map +1 -0
  26. package/dist/commands/delete.d.ts +6 -0
  27. package/dist/commands/delete.js +91 -0
  28. package/dist/commands/delete.js.map +1 -0
  29. package/dist/commands/info.d.ts +6 -0
  30. package/dist/commands/info.js +69 -0
  31. package/dist/commands/info.js.map +1 -0
  32. package/dist/commands/install-skill.d.ts +5 -0
  33. package/dist/commands/install-skill.js +28 -0
  34. package/dist/commands/install-skill.js.map +1 -0
  35. package/dist/commands/login.d.ts +10 -0
  36. package/dist/commands/login.js +93 -0
  37. package/dist/commands/login.js.map +1 -0
  38. package/dist/commands/ls.d.ts +6 -0
  39. package/dist/commands/ls.js +79 -0
  40. package/dist/commands/ls.js.map +1 -0
  41. package/dist/commands/mkdir.d.ts +6 -0
  42. package/dist/commands/mkdir.js +49 -0
  43. package/dist/commands/mkdir.js.map +1 -0
  44. package/dist/commands/mv.d.ts +9 -0
  45. package/dist/commands/mv.js +72 -0
  46. package/dist/commands/mv.js.map +1 -0
  47. package/dist/commands/read.d.ts +6 -0
  48. package/dist/commands/read.js +439 -0
  49. package/dist/commands/read.js.map +1 -0
  50. package/dist/commands/search.d.ts +7 -0
  51. package/dist/commands/search.js +92 -0
  52. package/dist/commands/search.js.map +1 -0
  53. package/dist/commands/share.d.ts +13 -0
  54. package/dist/commands/share.js +266 -0
  55. package/dist/commands/share.js.map +1 -0
  56. package/dist/commands/spaces.d.ts +6 -0
  57. package/dist/commands/spaces.js +43 -0
  58. package/dist/commands/spaces.js.map +1 -0
  59. package/dist/commands/tree.d.ts +6 -0
  60. package/dist/commands/tree.js +101 -0
  61. package/dist/commands/tree.js.map +1 -0
  62. package/dist/commands/update.d.ts +9 -0
  63. package/dist/commands/update.js +217 -0
  64. package/dist/commands/update.js.map +1 -0
  65. package/dist/commands/wiki.d.ts +6 -0
  66. package/dist/commands/wiki.js +286 -0
  67. package/dist/commands/wiki.js.map +1 -0
  68. package/dist/parser/block-types.d.ts +141 -0
  69. package/dist/parser/block-types.js +167 -0
  70. package/dist/parser/block-types.js.map +1 -0
  71. package/dist/parser/blocks-to-md.d.ts +26 -0
  72. package/dist/parser/blocks-to-md.js +666 -0
  73. package/dist/parser/blocks-to-md.js.map +1 -0
  74. package/dist/parser/text-elements.d.ts +13 -0
  75. package/dist/parser/text-elements.js +91 -0
  76. package/dist/parser/text-elements.js.map +1 -0
  77. package/dist/scopes.d.ts +21 -0
  78. package/dist/scopes.js +48 -0
  79. package/dist/scopes.js.map +1 -0
  80. package/dist/services/block-writer.d.ts +29 -0
  81. package/dist/services/block-writer.js +131 -0
  82. package/dist/services/block-writer.js.map +1 -0
  83. package/dist/services/doc-blocks.d.ts +8 -0
  84. package/dist/services/doc-blocks.js +26 -0
  85. package/dist/services/doc-blocks.js.map +1 -0
  86. package/dist/services/markdown-convert.d.ts +68 -0
  87. package/dist/services/markdown-convert.js +217 -0
  88. package/dist/services/markdown-convert.js.map +1 -0
  89. package/dist/services/wiki-nodes.d.ts +20 -0
  90. package/dist/services/wiki-nodes.js +46 -0
  91. package/dist/services/wiki-nodes.js.map +1 -0
  92. package/dist/types/index.d.ts +236 -0
  93. package/dist/types/index.js +5 -0
  94. package/dist/types/index.js.map +1 -0
  95. package/dist/utils/document-resolver.d.ts +26 -0
  96. package/dist/utils/document-resolver.js +46 -0
  97. package/dist/utils/document-resolver.js.map +1 -0
  98. package/dist/utils/drive-types.d.ts +4 -0
  99. package/dist/utils/drive-types.js +16 -0
  100. package/dist/utils/drive-types.js.map +1 -0
  101. package/dist/utils/errors.d.ts +23 -0
  102. package/dist/utils/errors.js +114 -0
  103. package/dist/utils/errors.js.map +1 -0
  104. package/dist/utils/member.d.ts +11 -0
  105. package/dist/utils/member.js +30 -0
  106. package/dist/utils/member.js.map +1 -0
  107. package/dist/utils/scope-prompt.d.ts +39 -0
  108. package/dist/utils/scope-prompt.js +134 -0
  109. package/dist/utils/scope-prompt.js.map +1 -0
  110. package/dist/utils/url-parser.d.ts +5 -0
  111. package/dist/utils/url-parser.js +55 -0
  112. package/dist/utils/url-parser.js.map +1 -0
  113. package/dist/utils/validate.d.ts +8 -0
  114. package/dist/utils/validate.js +15 -0
  115. package/dist/utils/validate.js.map +1 -0
  116. package/dist/utils/version.d.ts +12 -0
  117. package/dist/utils/version.js +128 -0
  118. package/dist/utils/version.js.map +1 -0
  119. package/package.json +53 -0
  120. package/skills/feishu-docs/SKILL.md +194 -0
@@ -0,0 +1,93 @@
1
+ /**
2
+ * login / logout / whoami commands.
3
+ */
4
+ import { oauthLogin, clearTokens, resolveAuth } from "../auth.js";
5
+ import { CliError } from "../utils/errors.js";
6
+ import { BASE_SCOPES } from "../scopes.js";
7
+ export const loginMeta = {
8
+ options: {
9
+ scope: { type: "string" },
10
+ port: { type: "string" },
11
+ "redirect-uri": { type: "string" },
12
+ },
13
+ positionals: false,
14
+ handler: login,
15
+ };
16
+ export const logoutMeta = {
17
+ options: {},
18
+ positionals: false,
19
+ handler: logout,
20
+ };
21
+ export const whoamiMeta = {
22
+ options: {},
23
+ positionals: false,
24
+ handler: whoami,
25
+ };
26
+ export async function login(args, globalOpts) {
27
+ const appId = process.env.FEISHU_APP_ID;
28
+ const appSecret = process.env.FEISHU_APP_SECRET;
29
+ if (!appId || !appSecret) {
30
+ throw new CliError("AUTH_REQUIRED", "请先设置 FEISHU_APP_ID 和 FEISHU_APP_SECRET 环境变量");
31
+ }
32
+ const scope = args.scope || BASE_SCOPES.join(" ");
33
+ const tokens = await oauthLogin(appId, {
34
+ scope,
35
+ appSecret,
36
+ port: args.port,
37
+ redirectUri: args.redirectUri,
38
+ useLark: globalOpts.lark,
39
+ });
40
+ process.stderr.write("feishu-docs: 登录成功!token 已加密保存。\n" +
41
+ "提示: login 仅申请基础权限。如需 ls、share 等功能,请运行:\n" +
42
+ " feishu-docs authorize --feature drive # 云空间文件管理\n" +
43
+ " feishu-docs authorize --feature contact # 联系人查询\n");
44
+ if (globalOpts.json) {
45
+ process.stdout.write(JSON.stringify({ success: true, expires_at: tokens.expires_at }) + "\n");
46
+ }
47
+ }
48
+ export async function logout(_args, globalOpts) {
49
+ await clearTokens();
50
+ process.stderr.write("feishu-docs: 已清除保存的凭证。\n");
51
+ if (globalOpts.json) {
52
+ process.stdout.write(JSON.stringify({ success: true }) + "\n");
53
+ }
54
+ }
55
+ export async function whoami(_args, globalOpts) {
56
+ try {
57
+ const authInfo = await resolveAuth(globalOpts.auth || "auto");
58
+ if (globalOpts.json) {
59
+ process.stdout.write(JSON.stringify({
60
+ success: true,
61
+ mode: authInfo.mode,
62
+ app_id: authInfo.appId,
63
+ has_user_token: !!authInfo.userToken,
64
+ }) + "\n");
65
+ }
66
+ else {
67
+ process.stdout.write(`认证模式: ${authInfo.mode}\n`);
68
+ if (authInfo.appId) {
69
+ process.stdout.write(`App ID: ${authInfo.appId}\n`);
70
+ }
71
+ if (authInfo.userToken) {
72
+ process.stdout.write(`User Token: ${authInfo.userToken.slice(0, 10)}...\n`);
73
+ if (authInfo.expiresAt) {
74
+ const expires = new Date(authInfo.expiresAt).toLocaleString();
75
+ const expired = Date.now() >= authInfo.expiresAt;
76
+ process.stdout.write(`过期时间: ${expires}${expired ? " (已过期)" : ""}\n`);
77
+ }
78
+ }
79
+ }
80
+ }
81
+ catch (err) {
82
+ if (globalOpts.json) {
83
+ process.stdout.write(JSON.stringify({
84
+ success: false,
85
+ error: err.message,
86
+ }) + "\n");
87
+ }
88
+ else {
89
+ process.stdout.write(`未认证: ${err.message}\n`);
90
+ }
91
+ }
92
+ }
93
+ //# sourceMappingURL=login.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"login.js","sourceRoot":"","sources":["../../src/commands/login.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * ls command: List files in a drive folder.
3
+ */
4
+ import { CommandMeta, CommandArgs, GlobalOpts } from "../types/index.js";
5
+ export declare const meta: CommandMeta;
6
+ export declare function ls(args: CommandArgs, globalOpts: GlobalOpts): Promise<void>;
@@ -0,0 +1,79 @@
1
+ /**
2
+ * ls command: List files in a drive folder.
3
+ */
4
+ import { createClient, fetchWithAuth } from "../client.js";
5
+ import { CliError } from "../utils/errors.js";
6
+ import { validateToken } from "../utils/validate.js";
7
+ import { withScopeRecovery } from "../utils/scope-prompt.js";
8
+ export const meta = {
9
+ options: {
10
+ type: { type: "string" },
11
+ limit: { type: "string" },
12
+ },
13
+ positionals: true,
14
+ handler: ls,
15
+ };
16
+ const TYPE_LABELS = {
17
+ doc: "文档",
18
+ docx: "新文档",
19
+ sheet: "表格",
20
+ bitable: "多维表格",
21
+ mindnote: "思维导图",
22
+ file: "文件",
23
+ folder: "文件夹",
24
+ slides: "幻灯片",
25
+ };
26
+ export async function ls(args, globalOpts) {
27
+ const folderToken = args.positionals[0] || undefined;
28
+ if (folderToken)
29
+ validateToken(folderToken, "folder_token");
30
+ const limit = args.limit ? Number(args.limit) : 50;
31
+ if (!Number.isInteger(limit) || limit < 1 || limit > 1000) {
32
+ throw new CliError("INVALID_ARGS", "--limit 必须是 1-1000 之间的整数");
33
+ }
34
+ if (args.type) {
35
+ const ALLOWED_TYPES = new Set(Object.keys(TYPE_LABELS));
36
+ if (!ALLOWED_TYPES.has(args.type)) {
37
+ throw new CliError("INVALID_ARGS", `无效的文件类型: ${args.type}。可选值: ${[...ALLOWED_TYPES].join(", ")}`);
38
+ }
39
+ }
40
+ return withScopeRecovery(async () => {
41
+ const { authInfo } = await createClient(globalOpts);
42
+ const typeStr = args.type;
43
+ const params = {
44
+ page_size: Math.min(limit, 50),
45
+ ...(folderToken && { folder_token: folderToken }),
46
+ ...(typeStr && { type: typeStr }),
47
+ };
48
+ const items = [];
49
+ let pageToken;
50
+ do {
51
+ if (pageToken)
52
+ params.page_token = pageToken;
53
+ const res = await fetchWithAuth(authInfo, "/open-apis/drive/v1/files", {
54
+ params,
55
+ });
56
+ const data = res?.data;
57
+ if (data?.files) {
58
+ items.push(...data.files);
59
+ }
60
+ pageToken = data?.has_more ? data.next_page_token : undefined;
61
+ } while (pageToken && items.length < limit);
62
+ const trimmed = items.slice(0, limit);
63
+ if (globalOpts.json) {
64
+ process.stdout.write(JSON.stringify({ success: true, count: trimmed.length, files: trimmed }, null, 2) + "\n");
65
+ return;
66
+ }
67
+ if (trimmed.length === 0) {
68
+ process.stdout.write("文件夹为空\n");
69
+ return;
70
+ }
71
+ for (const f of trimmed) {
72
+ const name = f.name || "(未命名)";
73
+ const type = TYPE_LABELS[f.type] || f.type || "unknown";
74
+ const token = f.token || "";
75
+ process.stdout.write(` ${name} [${type}] ${token}\n`);
76
+ }
77
+ }, globalOpts);
78
+ }
79
+ //# sourceMappingURL=ls.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ls.js","sourceRoot":"","sources":["../../src/commands/ls.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * mkdir command: Create a folder in cloud drive.
3
+ */
4
+ import { CommandMeta, CommandArgs, GlobalOpts } from "../types/index.js";
5
+ export declare const meta: CommandMeta;
6
+ export declare function mkdir(args: CommandArgs, globalOpts: GlobalOpts): Promise<void>;
@@ -0,0 +1,49 @@
1
+ /**
2
+ * mkdir command: Create a folder in cloud drive.
3
+ */
4
+ import { createClient, fetchWithAuth } from "../client.js";
5
+ import { CliError } from "../utils/errors.js";
6
+ import { withScopeRecovery } from "../utils/scope-prompt.js";
7
+ import { validateToken } from "../utils/validate.js";
8
+ export const meta = {
9
+ options: {
10
+ parent: { type: "string" },
11
+ },
12
+ positionals: true,
13
+ handler: mkdir,
14
+ };
15
+ export async function mkdir(args, globalOpts) {
16
+ const name = args.positionals[0];
17
+ if (!name) {
18
+ throw new CliError("INVALID_ARGS", "用法: feishu-docs mkdir <name> [--parent <folder_token>]");
19
+ }
20
+ const parentToken = args.parent;
21
+ if (parentToken) {
22
+ validateToken(parentToken, "parent_folder_token");
23
+ }
24
+ return withScopeRecovery(async () => {
25
+ const { authInfo } = await createClient(globalOpts);
26
+ const res = await fetchWithAuth(authInfo, "/open-apis/drive/v1/files/create_folder", {
27
+ method: "POST",
28
+ body: {
29
+ name,
30
+ folder_token: parentToken || "",
31
+ },
32
+ });
33
+ const resData = res?.data;
34
+ const token = resData?.token || "";
35
+ const url = resData?.url || "";
36
+ if (globalOpts.json) {
37
+ process.stdout.write(JSON.stringify({
38
+ success: true,
39
+ token,
40
+ name,
41
+ url,
42
+ }) + "\n");
43
+ }
44
+ else {
45
+ process.stdout.write(`已创建文件夹 "${name}" (${token})\n`);
46
+ }
47
+ }, globalOpts);
48
+ }
49
+ //# sourceMappingURL=mkdir.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mkdir.js","sourceRoot":"","sources":["../../src/commands/mkdir.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,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAC7D,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAGrD,MAAM,CAAC,MAAM,IAAI,GAAgB;IAC/B,OAAO,EAAE;QACP,MAAM,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;KAC3B;IACD,WAAW,EAAE,IAAI;IACjB,OAAO,EAAE,KAAK;CACf,CAAC;AAEF,MAAM,CAAC,KAAK,UAAU,KAAK,CACzB,IAAiB,EACjB,UAAsB;IAEtB,MAAM,IAAI,GAAG,IAAI,CAAC,WAAY,CAAC,CAAC,CAAC,CAAC;IAClC,IAAI,CAAC,IAAI,EAAE,CAAC;QACV,MAAM,IAAI,QAAQ,CAChB,cAAc,EACd,wDAAwD,CACzD,CAAC;IACJ,CAAC;IAED,MAAM,WAAW,GAAG,IAAI,CAAC,MAA4B,CAAC;IACtD,IAAI,WAAW,EAAE,CAAC;QAChB,aAAa,CAAC,WAAW,EAAE,qBAAqB,CAAC,CAAC;IACpD,CAAC;IAED,OAAO,iBAAiB,CAAC,KAAK,IAAI,EAAE;QAClC,MAAM,EAAE,QAAQ,EAAE,GAAG,MAAM,YAAY,CAAC,UAAU,CAAC,CAAC;QAEpD,MAAM,GAAG,GAAG,MAAM,aAAa,CAC7B,QAAQ,EACR,yCAAyC,EACzC;YACE,MAAM,EAAE,MAAM;YACd,IAAI,EAAE;gBACJ,IAAI;gBACJ,YAAY,EAAE,WAAW,IAAI,EAAE;aAChC;SACF,CACF,CAAC;QAEF,MAAM,OAAO,GAAG,GAAG,EAAE,IAA2C,CAAC;QACjE,MAAM,KAAK,GAAI,OAAO,EAAE,KAAgB,IAAI,EAAE,CAAC;QAC/C,MAAM,GAAG,GAAI,OAAO,EAAE,GAAc,IAAI,EAAE,CAAC;QAE3C,IAAI,UAAU,CAAC,IAAI,EAAE,CAAC;YACpB,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,IAAI,CAAC,SAAS,CAAC;gBACb,OAAO,EAAE,IAAI;gBACb,KAAK;gBACL,IAAI;gBACJ,GAAG;aACJ,CAAC,GAAG,IAAI,CACV,CAAC;QACJ,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,WAAW,IAAI,MAAM,KAAK,KAAK,CAAC,CAAC;QACxD,CAAC;IACH,CAAC,EAAE,UAAU,CAAC,CAAC;AACjB,CAAC"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * mv command: Move a file to a different folder in cloud drive.
3
+ *
4
+ * The move API may complete synchronously (empty data, code 0) or
5
+ * return a task_id for async polling. Both cases are handled.
6
+ */
7
+ import { CommandMeta, CommandArgs, GlobalOpts } from "../types/index.js";
8
+ export declare const meta: CommandMeta;
9
+ export declare function mv(args: CommandArgs, globalOpts: GlobalOpts): Promise<void>;
@@ -0,0 +1,72 @@
1
+ /**
2
+ * mv command: Move a file to a different folder in cloud drive.
3
+ *
4
+ * The move API may complete synchronously (empty data, code 0) or
5
+ * return a task_id for async polling. Both cases are handled.
6
+ */
7
+ import { createClient, fetchWithAuth } from "../client.js";
8
+ import { CliError } from "../utils/errors.js";
9
+ import { withScopeRecovery } from "../utils/scope-prompt.js";
10
+ import { resolveDocument } from "../utils/document-resolver.js";
11
+ import { validateToken } from "../utils/validate.js";
12
+ const POLL_INTERVAL_MS = 1000;
13
+ const POLL_TIMEOUT_MS = 30_000;
14
+ export const meta = {
15
+ options: {},
16
+ positionals: true,
17
+ handler: mv,
18
+ };
19
+ function outputSuccess(fileToken, targetFolder, json) {
20
+ if (json) {
21
+ process.stdout.write(JSON.stringify({
22
+ success: true,
23
+ file_token: fileToken,
24
+ folder_token: targetFolder,
25
+ }) + "\n");
26
+ }
27
+ else {
28
+ process.stdout.write(`已移动 ${fileToken} 到文件夹 ${targetFolder}\n`);
29
+ }
30
+ }
31
+ export async function mv(args, globalOpts) {
32
+ const input = args.positionals[0];
33
+ const targetFolder = args.positionals[1];
34
+ if (!input || !targetFolder) {
35
+ throw new CliError("INVALID_ARGS", "用法: feishu-docs mv <url|token> <target_folder_token>");
36
+ }
37
+ validateToken(targetFolder, "target_folder_token");
38
+ return withScopeRecovery(async () => {
39
+ const { authInfo } = await createClient(globalOpts);
40
+ const doc = await resolveDocument(authInfo, input);
41
+ const fileToken = doc.objToken;
42
+ const type = doc.objType;
43
+ const moveRes = await fetchWithAuth(authInfo, `/open-apis/drive/v1/files/${encodeURIComponent(fileToken)}/move`, {
44
+ method: "POST",
45
+ body: { type, folder_token: targetFolder },
46
+ });
47
+ const resData = moveRes?.data;
48
+ const taskId = resData?.task_id;
49
+ // Sync completion: API returns code 0 with no task_id
50
+ if (!taskId) {
51
+ outputSuccess(fileToken, targetFolder, globalOpts.json);
52
+ return;
53
+ }
54
+ // Async: poll task_check until complete
55
+ const deadline = Date.now() + POLL_TIMEOUT_MS;
56
+ while (Date.now() < deadline) {
57
+ await new Promise((r) => setTimeout(r, POLL_INTERVAL_MS));
58
+ const checkRes = await fetchWithAuth(authInfo, `/open-apis/drive/v1/files/task_check`, { params: { task_id: taskId } });
59
+ const status = checkRes?.data
60
+ ?.status;
61
+ if (status === "success") {
62
+ outputSuccess(fileToken, targetFolder, globalOpts.json);
63
+ return;
64
+ }
65
+ if (status === "fail") {
66
+ throw new CliError("API_ERROR", "移动操作失败");
67
+ }
68
+ }
69
+ throw new CliError("API_ERROR", `移动操作超时(${POLL_TIMEOUT_MS / 1000}秒),task_id: ${taskId}`, { retryable: true });
70
+ }, globalOpts);
71
+ }
72
+ //# sourceMappingURL=mv.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mv.js","sourceRoot":"","sources":["../../src/commands/mv.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * read command: Read a Feishu document and output as Markdown.
3
+ */
4
+ import { CommandMeta, CommandArgs, GlobalOpts } from "../types/index.js";
5
+ export declare const meta: CommandMeta;
6
+ export declare function read(args: CommandArgs, globalOpts: GlobalOpts): Promise<void>;