fantsec-docmost-cli 2.2.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 (48) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +137 -0
  3. package/build/__tests__/cli-utils.test.js +287 -0
  4. package/build/__tests__/client-pagination.test.js +103 -0
  5. package/build/__tests__/discovery.test.js +40 -0
  6. package/build/__tests__/envelope.test.js +91 -0
  7. package/build/__tests__/filters.test.js +235 -0
  8. package/build/__tests__/integration/comment.test.js +48 -0
  9. package/build/__tests__/integration/discovery.test.js +24 -0
  10. package/build/__tests__/integration/file.test.js +33 -0
  11. package/build/__tests__/integration/group.test.js +48 -0
  12. package/build/__tests__/integration/helpers/global-setup.js +80 -0
  13. package/build/__tests__/integration/helpers/run-cli.js +163 -0
  14. package/build/__tests__/integration/invite.test.js +34 -0
  15. package/build/__tests__/integration/page.test.js +69 -0
  16. package/build/__tests__/integration/search.test.js +45 -0
  17. package/build/__tests__/integration/share.test.js +49 -0
  18. package/build/__tests__/integration/space.test.js +56 -0
  19. package/build/__tests__/integration/user.test.js +15 -0
  20. package/build/__tests__/integration/workspace.test.js +42 -0
  21. package/build/__tests__/markdown-converter.test.js +445 -0
  22. package/build/__tests__/mcp-tooling.test.js +58 -0
  23. package/build/__tests__/page-mentions.test.js +65 -0
  24. package/build/__tests__/tiptap-extensions.test.js +135 -0
  25. package/build/client.js +715 -0
  26. package/build/commands/comment.js +54 -0
  27. package/build/commands/discovery.js +21 -0
  28. package/build/commands/file.js +36 -0
  29. package/build/commands/group.js +91 -0
  30. package/build/commands/invite.js +67 -0
  31. package/build/commands/page.js +227 -0
  32. package/build/commands/search.js +33 -0
  33. package/build/commands/share.js +65 -0
  34. package/build/commands/space.js +154 -0
  35. package/build/commands/user.js +38 -0
  36. package/build/commands/workspace.js +77 -0
  37. package/build/index.js +19 -0
  38. package/build/lib/auth-utils.js +53 -0
  39. package/build/lib/cli-utils.js +293 -0
  40. package/build/lib/collaboration.js +126 -0
  41. package/build/lib/filters.js +137 -0
  42. package/build/lib/markdown-converter.js +187 -0
  43. package/build/lib/mcp-tooling.js +295 -0
  44. package/build/lib/page-mentions.js +162 -0
  45. package/build/lib/tiptap-extensions.js +86 -0
  46. package/build/mcp.js +186 -0
  47. package/build/program.js +60 -0
  48. package/package.json +64 -0
@@ -0,0 +1,54 @@
1
+ import { ensureOutputSupported, printResult, resolveContentInput, withClient, } from "../lib/cli-utils.js";
2
+ export function register(program) {
3
+ program
4
+ .command("comment-list")
5
+ .description("List comments on a page")
6
+ .requiredOption("--page-id <id>", "Page ID")
7
+ .action((options) => withClient(program, async (client, opts) => {
8
+ ensureOutputSupported(opts, { allowTable: true });
9
+ const result = await client.getComments(options.pageId);
10
+ printResult(result.items, opts, { allowTable: true, hasMore: result.hasMore });
11
+ }));
12
+ program
13
+ .command("comment-info")
14
+ .description("Get comment by ID")
15
+ .requiredOption("--comment-id <id>", "Comment ID")
16
+ .action((options) => withClient(program, async (client, opts) => {
17
+ ensureOutputSupported(opts);
18
+ const result = await client.getCommentInfo(options.commentId);
19
+ printResult(result, opts);
20
+ }));
21
+ program
22
+ .command("comment-create")
23
+ .description("Create a comment on a page")
24
+ .requiredOption("--page-id <id>", "Page ID")
25
+ .requiredOption("--content <content>", "Content literal, @file, or - for stdin")
26
+ .option("--selection <text>", "Selected text the comment refers to")
27
+ .option("--parent-comment-id <id>", "Parent comment ID for replies")
28
+ .action((options) => withClient(program, async (client, opts) => {
29
+ ensureOutputSupported(opts);
30
+ const content = await resolveContentInput(options.content);
31
+ const result = await client.createComment(options.pageId, content, options.selection, options.parentCommentId);
32
+ printResult(result, opts);
33
+ }));
34
+ program
35
+ .command("comment-update")
36
+ .description("Update a comment")
37
+ .requiredOption("--comment-id <id>", "Comment ID")
38
+ .requiredOption("--content <content>", "Content literal, @file, or - for stdin")
39
+ .action((options) => withClient(program, async (client, opts) => {
40
+ ensureOutputSupported(opts);
41
+ const content = await resolveContentInput(options.content);
42
+ const result = await client.updateComment(options.commentId, content);
43
+ printResult(result, opts);
44
+ }));
45
+ program
46
+ .command("comment-delete")
47
+ .description("Delete a comment")
48
+ .requiredOption("--comment-id <id>", "Comment ID")
49
+ .action((options) => withClient(program, async (client, opts) => {
50
+ ensureOutputSupported(opts);
51
+ const result = await client.deleteComment(options.commentId);
52
+ printResult(result, opts);
53
+ }));
54
+ }
@@ -0,0 +1,21 @@
1
+ export function register(program) {
2
+ program
3
+ .command("commands")
4
+ .description("List all available commands with options (for agent discovery)")
5
+ .action(() => {
6
+ const commands = program.commands
7
+ .filter((cmd) => cmd.name() !== "commands")
8
+ .map((cmd) => ({
9
+ name: cmd.name(),
10
+ description: cmd.description(),
11
+ options: cmd.options.map((opt) => ({
12
+ flags: opt.flags,
13
+ description: opt.description,
14
+ required: opt.required || false,
15
+ ...(opt.defaultValue !== undefined && { default: opt.defaultValue }),
16
+ })),
17
+ }));
18
+ const envelope = { ok: true, data: commands, meta: { count: commands.length, hasMore: false } };
19
+ console.log(JSON.stringify(envelope, null, 2));
20
+ });
21
+ }
@@ -0,0 +1,36 @@
1
+ import { writeFileSync } from "fs";
2
+ import { resolve, relative } from "path";
3
+ import { ensureOutputSupported, printResult, withClient, } from "../lib/cli-utils.js";
4
+ export function register(program) {
5
+ program
6
+ .command("file-upload")
7
+ .description("Upload a file attachment to a page")
8
+ .requiredOption("--file <path>", "File to upload")
9
+ .requiredOption("--page-id <id>", "Page ID to attach file to")
10
+ .option("--attachment-id <id>", "Existing attachment ID to replace")
11
+ .action((options) => withClient(program, async (client, opts) => {
12
+ ensureOutputSupported(opts);
13
+ const result = await client.uploadFile(options.file, options.pageId, options.attachmentId);
14
+ printResult(result, opts);
15
+ }));
16
+ program
17
+ .command("file-download")
18
+ .description("Download a file attachment")
19
+ .requiredOption("--file-id <id>", "File ID")
20
+ .requiredOption("--file-name <name>", "File name")
21
+ .option("--output <path>", "Output file path")
22
+ .action((options) => withClient(program, async (client) => {
23
+ const data = await client.downloadFile(options.fileId, options.fileName);
24
+ if (options.output) {
25
+ const resolved = resolve(options.output);
26
+ const rel = relative(process.cwd(), resolved);
27
+ if (rel.startsWith("..") || resolve(rel) !== resolved) {
28
+ process.stderr.write(`Warning: writing to path outside CWD: ${resolved}\n`);
29
+ }
30
+ writeFileSync(resolved, Buffer.from(data));
31
+ }
32
+ else {
33
+ process.stdout.write(Buffer.from(data));
34
+ }
35
+ }));
36
+ }
@@ -0,0 +1,91 @@
1
+ import { CliError, ensureOutputSupported, parseCommaSeparatedIds, printResult, withClient, } from "../lib/cli-utils.js";
2
+ export function register(program) {
3
+ program
4
+ .command("group-list")
5
+ .description("List all available groups")
6
+ .action(() => withClient(program, async (client, opts) => {
7
+ ensureOutputSupported(opts, { allowTable: true });
8
+ const result = await client.getGroups();
9
+ printResult(result.items, opts, { allowTable: true, hasMore: result.hasMore });
10
+ }));
11
+ program
12
+ .command("group-info")
13
+ .description("Get group details")
14
+ .requiredOption("--group-id <id>", "Group ID")
15
+ .action((options) => withClient(program, async (client, opts) => {
16
+ ensureOutputSupported(opts, { allowTable: true });
17
+ const result = await client.getGroupInfo(options.groupId);
18
+ printResult(result, opts, { allowTable: true });
19
+ }));
20
+ program
21
+ .command("group-create")
22
+ .description("Create a new group")
23
+ .requiredOption("--name <name>", "Group name")
24
+ .option("--description <description>", "Group description")
25
+ .option("--user-ids <ids>", "Comma-separated user IDs")
26
+ .action((options) => withClient(program, async (client, opts) => {
27
+ ensureOutputSupported(opts);
28
+ const userIds = options.userIds
29
+ ? parseCommaSeparatedIds("--user-ids", options.userIds)
30
+ : undefined;
31
+ const result = await client.createGroup(options.name, options.description, userIds);
32
+ printResult(result, opts);
33
+ }));
34
+ program
35
+ .command("group-update")
36
+ .description("Update group settings")
37
+ .requiredOption("--group-id <id>", "Group ID")
38
+ .option("--name <name>", "Group name")
39
+ .option("--description <description>", "Group description")
40
+ .action((options) => withClient(program, async (client, opts) => {
41
+ ensureOutputSupported(opts);
42
+ const params = {
43
+ ...(options.name !== undefined && { name: options.name }),
44
+ ...(options.description !== undefined && { description: options.description }),
45
+ };
46
+ if (Object.keys(params).length === 0) {
47
+ throw new CliError("VALIDATION_ERROR", "At least one update flag is required (--name or --description).");
48
+ }
49
+ const result = await client.updateGroup(options.groupId, params);
50
+ printResult(result, opts);
51
+ }));
52
+ program
53
+ .command("group-delete")
54
+ .description("Delete a group")
55
+ .requiredOption("--group-id <id>", "Group ID")
56
+ .action((options) => withClient(program, async (client, opts) => {
57
+ ensureOutputSupported(opts);
58
+ const result = await client.deleteGroup(options.groupId);
59
+ printResult(result, opts);
60
+ }));
61
+ program
62
+ .command("group-member-list")
63
+ .description("List group members")
64
+ .requiredOption("--group-id <id>", "Group ID")
65
+ .action((options) => withClient(program, async (client, opts) => {
66
+ ensureOutputSupported(opts, { allowTable: true });
67
+ const result = await client.getGroupMembers(options.groupId);
68
+ printResult(result.items, opts, { allowTable: true, hasMore: result.hasMore });
69
+ }));
70
+ program
71
+ .command("group-member-add")
72
+ .description("Add members to a group")
73
+ .requiredOption("--group-id <id>", "Group ID")
74
+ .requiredOption("--user-ids <ids>", "Comma-separated user IDs")
75
+ .action((options) => withClient(program, async (client, opts) => {
76
+ ensureOutputSupported(opts);
77
+ const userIds = parseCommaSeparatedIds("--user-ids", options.userIds);
78
+ const result = await client.addGroupMembers(options.groupId, userIds);
79
+ printResult(result, opts);
80
+ }));
81
+ program
82
+ .command("group-member-remove")
83
+ .description("Remove a member from a group")
84
+ .requiredOption("--group-id <id>", "Group ID")
85
+ .requiredOption("--user-id <id>", "User ID to remove")
86
+ .action((options) => withClient(program, async (client, opts) => {
87
+ ensureOutputSupported(opts);
88
+ const result = await client.removeGroupMember(options.groupId, options.userId);
89
+ printResult(result, opts);
90
+ }));
91
+ }
@@ -0,0 +1,67 @@
1
+ import { Option } from "commander";
2
+ import { ensureOutputSupported, parseCommaSeparatedIds, printResult, withClient, } from "../lib/cli-utils.js";
3
+ export function register(program) {
4
+ program
5
+ .command("invite-list")
6
+ .description("List workspace invitations")
7
+ .action(() => withClient(program, async (client, opts) => {
8
+ ensureOutputSupported(opts, { allowTable: true });
9
+ const result = await client.getInvites();
10
+ printResult(result.items, opts, { allowTable: true, hasMore: result.hasMore });
11
+ }));
12
+ program
13
+ .command("invite-info")
14
+ .description("Get invitation details")
15
+ .requiredOption("--invitation-id <id>", "Invitation ID")
16
+ .action((options) => withClient(program, async (client, opts) => {
17
+ ensureOutputSupported(opts);
18
+ const result = await client.getInviteInfo(options.invitationId);
19
+ printResult(result, opts);
20
+ }));
21
+ program
22
+ .command("invite-create")
23
+ .description("Create workspace invitation(s)")
24
+ .requiredOption("--emails <emails>", "Comma-separated email addresses")
25
+ .addOption(new Option("--role <role>", "Role for invited users")
26
+ .choices(["owner", "admin", "member"])
27
+ .makeOptionMandatory())
28
+ .option("--group-ids <ids>", "Comma-separated group IDs")
29
+ .action((options) => withClient(program, async (client, opts) => {
30
+ ensureOutputSupported(opts);
31
+ const emails = parseCommaSeparatedIds("--emails", options.emails);
32
+ const groupIds = options.groupIds
33
+ ? parseCommaSeparatedIds("--group-ids", options.groupIds)
34
+ : undefined;
35
+ const result = await client.createInvite(emails, options.role, groupIds);
36
+ printResult(result, opts);
37
+ }));
38
+ program
39
+ .command("invite-revoke")
40
+ .description("Revoke a workspace invitation")
41
+ .requiredOption("--invitation-id <id>", "Invitation ID")
42
+ .action((options) => withClient(program, async (client, opts) => {
43
+ ensureOutputSupported(opts);
44
+ const result = await client.revokeInvite(options.invitationId);
45
+ printResult(result, opts);
46
+ }));
47
+ program
48
+ .command("invite-resend")
49
+ .description("Resend a workspace invitation")
50
+ .requiredOption("--invitation-id <id>", "Invitation ID")
51
+ .action((options) => withClient(program, async (client, opts) => {
52
+ ensureOutputSupported(opts);
53
+ const result = await client.resendInvite(options.invitationId);
54
+ printResult(result, opts);
55
+ }));
56
+ program
57
+ .command("invite-link")
58
+ .description("Get invitation link")
59
+ .requiredOption("--invitation-id <id>", "Invitation ID")
60
+ .action((options) => withClient(program, async (client, opts) => {
61
+ ensureOutputSupported(opts, { allowText: true });
62
+ const result = await client.getInviteLink(options.invitationId);
63
+ printResult(result, opts, {
64
+ textExtractor: (data) => data?.inviteLink,
65
+ });
66
+ }));
67
+ }
@@ -0,0 +1,227 @@
1
+ import { writeFileSync } from "fs";
2
+ import { resolve, relative } from "path";
3
+ import { Option } from "commander";
4
+ import { CliError, ensureOutputSupported, printResult, resolveContentInput, parseCommaSeparatedIds, withClient, } from "../lib/cli-utils.js";
5
+ export function register(program) {
6
+ program
7
+ .command("page-list")
8
+ .description("List pages")
9
+ .option("-s, --space-id <id>", "Filter by space ID")
10
+ .action((options) => withClient(program, async (client, opts) => {
11
+ ensureOutputSupported(opts, { allowTable: true });
12
+ const result = await client.listPages(options.spaceId);
13
+ printResult(result.items, opts, { allowTable: true, hasMore: result.hasMore });
14
+ }));
15
+ program
16
+ .command("page-info")
17
+ .description("Get page by ID")
18
+ .requiredOption("--page-id <id>", "Page ID")
19
+ .action((options) => withClient(program, async (client, opts) => {
20
+ ensureOutputSupported(opts, { allowTable: true, allowText: true });
21
+ const result = await client.getPage(options.pageId);
22
+ printResult(result.data, opts, {
23
+ allowTable: true,
24
+ textExtractor: (data) => {
25
+ return data?.content;
26
+ },
27
+ });
28
+ }));
29
+ program
30
+ .command("page-create")
31
+ .description("Create a new page")
32
+ .requiredOption("--space-id <id>", "Space ID")
33
+ .option("--title <title>", "Page title")
34
+ .option("--icon <icon>", "Page icon")
35
+ .option("--parent-page-id <id>", "Parent page ID")
36
+ .action((options) => withClient(program, async (client, opts) => {
37
+ ensureOutputSupported(opts);
38
+ const result = await client.createPage(options.spaceId, options.title, options.icon, options.parentPageId);
39
+ printResult(result, opts);
40
+ }));
41
+ program
42
+ .command("page-update")
43
+ .description("Update page metadata and/or content")
44
+ .requiredOption("--page-id <id>", "Page ID")
45
+ .option("--content <content>", "Content literal, @file, or - for stdin")
46
+ .option("--title <title>", "New page title")
47
+ .option("--icon <icon>", "Page icon")
48
+ .action((options) => withClient(program, async (client, opts) => {
49
+ ensureOutputSupported(opts);
50
+ if (options.content === undefined && options.title === undefined && options.icon === undefined) {
51
+ throw new CliError("VALIDATION_ERROR", "Provide at least one of --content, --title, or --icon.");
52
+ }
53
+ const content = options.content ? await resolveContentInput(options.content) : undefined;
54
+ const result = await client.updatePage(options.pageId, content, options.title, options.icon);
55
+ printResult(result, opts);
56
+ }));
57
+ program
58
+ .command("page-move")
59
+ .description("Move page to a different parent or to root")
60
+ .requiredOption("--page-id <id>", "Page ID")
61
+ .option("--parent-page-id <id>", "Target parent page ID")
62
+ .option("--position <pos>", "Position string", "a00000")
63
+ .option("--root", "Move page to root")
64
+ .action((options) => withClient(program, async (client, opts) => {
65
+ ensureOutputSupported(opts);
66
+ if (options.root && options.parentPageId) {
67
+ throw new CliError("VALIDATION_ERROR", "--root and --parent-page-id are mutually exclusive.");
68
+ }
69
+ if (!options.root && !options.parentPageId) {
70
+ throw new CliError("VALIDATION_ERROR", "Specify --parent-page-id <id> or --root.");
71
+ }
72
+ const parentPageId = options.root ? null : (options.parentPageId ?? null);
73
+ const result = await client.movePage(options.pageId, parentPageId, options.position);
74
+ printResult(result, opts);
75
+ }));
76
+ program
77
+ .command("page-delete")
78
+ .description("Delete a page")
79
+ .requiredOption("--page-id <id>", "Page ID")
80
+ .option("--permanently-delete", "Permanently delete page (no trash)")
81
+ .action((options) => withClient(program, async (client, opts) => {
82
+ ensureOutputSupported(opts);
83
+ const result = await client.deletePage(options.pageId, options.permanentlyDelete);
84
+ printResult(result, opts);
85
+ }));
86
+ program
87
+ .command("page-delete-bulk")
88
+ .description("Delete multiple pages")
89
+ .requiredOption("--page-ids <id1,id2,...>", "Comma-separated page IDs")
90
+ .action((options) => withClient(program, async (client, opts) => {
91
+ ensureOutputSupported(opts, { allowTable: true });
92
+ const pageIds = parseCommaSeparatedIds("--page-ids", options.pageIds);
93
+ const result = await client.deletePages(pageIds);
94
+ const failed = result.filter((r) => !r.success);
95
+ printResult(result, opts, { allowTable: true });
96
+ if (failed.length > 0) {
97
+ throw new CliError("INTERNAL_ERROR", `Failed to delete ${failed.length} of ${result.length} pages.`);
98
+ }
99
+ }));
100
+ program
101
+ .command("page-history")
102
+ .description("Get page version history")
103
+ .requiredOption("--page-id <id>", "Page ID")
104
+ .action((options) => withClient(program, async (client, opts) => {
105
+ ensureOutputSupported(opts, { allowTable: true });
106
+ const result = await client.getPageHistory(options.pageId, opts.limit, opts.maxItems);
107
+ printResult(result.items, opts, { allowTable: true, hasMore: result.hasMore });
108
+ }));
109
+ program
110
+ .command("page-history-detail")
111
+ .description("Get specific page history entry")
112
+ .requiredOption("--history-id <id>", "History entry ID")
113
+ .action((options) => withClient(program, async (client, opts) => {
114
+ ensureOutputSupported(opts, { allowTable: true, allowText: true });
115
+ const result = await client.getPageHistoryDetail(options.historyId);
116
+ printResult(result, opts, {
117
+ allowTable: true,
118
+ textExtractor: (data) => {
119
+ const value = data;
120
+ return value.content;
121
+ },
122
+ });
123
+ }));
124
+ program
125
+ .command("page-restore")
126
+ .description("Restore page from trash")
127
+ .requiredOption("--page-id <id>", "Page ID")
128
+ .action((options) => withClient(program, async (client, opts) => {
129
+ ensureOutputSupported(opts);
130
+ const result = await client.restorePage(options.pageId);
131
+ printResult(result, opts);
132
+ }));
133
+ program
134
+ .command("page-trash")
135
+ .description("List deleted pages in a space")
136
+ .requiredOption("--space-id <id>", "Space ID")
137
+ .action((options) => withClient(program, async (client, opts) => {
138
+ ensureOutputSupported(opts, { allowTable: true });
139
+ const result = await client.getTrash(options.spaceId);
140
+ printResult(result.items, opts, { allowTable: true, hasMore: result.hasMore });
141
+ }));
142
+ program
143
+ .command("page-duplicate")
144
+ .description("Duplicate page")
145
+ .requiredOption("--page-id <id>", "Page ID")
146
+ .option("--space-id <id>", "Target space ID")
147
+ .action((options) => withClient(program, async (client, opts) => {
148
+ ensureOutputSupported(opts);
149
+ const result = await client.duplicatePage(options.pageId, options.spaceId);
150
+ printResult(result, opts);
151
+ }));
152
+ program
153
+ .command("page-breadcrumbs")
154
+ .description("Get breadcrumb path for page")
155
+ .requiredOption("--page-id <id>", "Page ID")
156
+ .action((options) => withClient(program, async (client, opts) => {
157
+ ensureOutputSupported(opts, { allowTable: true });
158
+ const result = await client.getPageBreadcrumbs(options.pageId);
159
+ printResult(result, opts, { allowTable: true });
160
+ }));
161
+ program
162
+ .command("page-tree")
163
+ .description("Get page tree for a space or page")
164
+ .option("-s, --space-id <id>", "Space ID")
165
+ .option("--page-id <id>", "Page ID")
166
+ .action((options) => withClient(program, async (client, opts) => {
167
+ if (!options.spaceId && !options.pageId) {
168
+ throw new CliError("VALIDATION_ERROR", "At least one of --space-id or --page-id is required.");
169
+ }
170
+ ensureOutputSupported(opts, { allowTable: true });
171
+ const result = await client.getPageTree(options.spaceId, options.pageId);
172
+ printResult(result, opts, { allowTable: true });
173
+ }));
174
+ program
175
+ .command("page-move-to-space")
176
+ .description("Move page to a different space")
177
+ .requiredOption("--page-id <id>", "Page ID")
178
+ .requiredOption("--space-id <id>", "Target space ID")
179
+ .action((options) => withClient(program, async (client, opts) => {
180
+ ensureOutputSupported(opts);
181
+ const result = await client.movePageToSpace(options.pageId, options.spaceId);
182
+ printResult(result, opts);
183
+ }));
184
+ program
185
+ .command("page-export")
186
+ .description("Export page content")
187
+ .requiredOption("--page-id <id>", "Page ID")
188
+ .addOption(new Option("--export-format <format>", "Export format").choices(["html", "markdown"]).makeOptionMandatory())
189
+ .option("--output <path>", "Output file path")
190
+ .option("--include-children", "Include child pages")
191
+ .option("--include-attachments", "Include attachments")
192
+ .action((options) => withClient(program, async (client) => {
193
+ const data = await client.exportPage(options.pageId, options.exportFormat, options.includeChildren, options.includeAttachments);
194
+ if (options.output) {
195
+ const resolved = resolve(options.output);
196
+ const rel = relative(process.cwd(), resolved);
197
+ if (rel.startsWith("..") || resolve(rel) !== resolved) {
198
+ process.stderr.write(`Warning: writing to path outside CWD: ${resolved}\n`);
199
+ }
200
+ writeFileSync(resolved, Buffer.from(data));
201
+ }
202
+ else {
203
+ process.stdout.write(Buffer.from(data));
204
+ }
205
+ }));
206
+ program
207
+ .command("page-import")
208
+ .description("Import a page from file")
209
+ .requiredOption("--file <path>", "File to import")
210
+ .requiredOption("--space-id <id>", "Space ID")
211
+ .action((options) => withClient(program, async (client, opts) => {
212
+ ensureOutputSupported(opts);
213
+ const result = await client.importPage(options.file, options.spaceId);
214
+ printResult(result, opts);
215
+ }));
216
+ program
217
+ .command("page-import-zip")
218
+ .description("Import pages from a zip archive")
219
+ .requiredOption("--file <path>", "Zip file to import")
220
+ .requiredOption("--space-id <id>", "Space ID")
221
+ .addOption(new Option("--source <source>", "Import source").choices(["generic", "notion", "confluence"]).makeOptionMandatory())
222
+ .action((options) => withClient(program, async (client, opts) => {
223
+ ensureOutputSupported(opts);
224
+ const result = await client.importZip(options.file, options.spaceId, options.source);
225
+ printResult(result, opts);
226
+ }));
227
+ }
@@ -0,0 +1,33 @@
1
+ import { ensureOutputSupported, printResult, withClient, } from "../lib/cli-utils.js";
2
+ export function register(program) {
3
+ program
4
+ .command("search")
5
+ .description("Search pages and content")
6
+ .requiredOption("--query <q>", "Search query")
7
+ .option("-s, --space-id <id>", "Filter by space ID")
8
+ .option("--creator-id <id>", "Filter by creator ID")
9
+ .action((options) => withClient(program, async (client, opts) => {
10
+ ensureOutputSupported(opts, { allowTable: true });
11
+ const result = await client.search(options.query, options.spaceId, options.creatorId);
12
+ printResult(result.items, opts, { allowTable: true, hasMore: result.hasMore });
13
+ }));
14
+ program
15
+ .command("search-suggest")
16
+ .description("Get search suggestions")
17
+ .requiredOption("--query <q>", "Search query")
18
+ .option("-s, --space-id <id>", "Filter by space ID")
19
+ .option("--include-users", "Include users in results")
20
+ .option("--include-groups", "Include groups in results")
21
+ .option("--include-pages", "Include pages in results")
22
+ .option("--max-results <n>", "Max results", parseInt)
23
+ .action((options) => withClient(program, async (client, opts) => {
24
+ ensureOutputSupported(opts, { allowTable: true });
25
+ const result = await client.searchSuggest(options.query, options.spaceId, {
26
+ includeUsers: options.includeUsers,
27
+ includeGroups: options.includeGroups,
28
+ includePages: options.includePages,
29
+ limit: options.maxResults,
30
+ });
31
+ printResult(result, opts, { allowTable: true });
32
+ }));
33
+ }
@@ -0,0 +1,65 @@
1
+ import { Option } from "commander";
2
+ import { ensureOutputSupported, printResult, withClient, } from "../lib/cli-utils.js";
3
+ export function register(program) {
4
+ program
5
+ .command("share-list")
6
+ .description("List all shares")
7
+ .action(() => withClient(program, async (client, opts) => {
8
+ ensureOutputSupported(opts, { allowTable: true });
9
+ const result = await client.getShares();
10
+ printResult(result.items, opts, { allowTable: true, hasMore: result.hasMore });
11
+ }));
12
+ program
13
+ .command("share-info")
14
+ .description("Get share details")
15
+ .requiredOption("--share-id <id>", "Share ID")
16
+ .action((options) => withClient(program, async (client, opts) => {
17
+ ensureOutputSupported(opts);
18
+ const result = await client.getShareInfo(options.shareId);
19
+ printResult(result, opts);
20
+ }));
21
+ program
22
+ .command("share-for-page")
23
+ .description("Get share for a page")
24
+ .requiredOption("--page-id <id>", "Page ID")
25
+ .action((options) => withClient(program, async (client, opts) => {
26
+ ensureOutputSupported(opts);
27
+ const result = await client.getShareForPage(options.pageId);
28
+ printResult(result, opts);
29
+ }));
30
+ program
31
+ .command("share-create")
32
+ .description("Create a share for a page")
33
+ .requiredOption("--page-id <id>", "Page ID")
34
+ .addOption(new Option("--include-subpages <bool>", "Include subpages").choices(["true", "false"]))
35
+ .addOption(new Option("--search-indexing <bool>", "Allow search indexing").choices(["true", "false"]))
36
+ .action((options) => withClient(program, async (client, opts) => {
37
+ ensureOutputSupported(opts);
38
+ const includeSubPages = options.includeSubpages !== undefined ? options.includeSubpages === "true" : undefined;
39
+ const searchIndexing = options.searchIndexing !== undefined ? options.searchIndexing === "true" : undefined;
40
+ const result = await client.createShare(options.pageId, includeSubPages, searchIndexing);
41
+ printResult(result, opts);
42
+ }));
43
+ program
44
+ .command("share-update")
45
+ .description("Update a share")
46
+ .requiredOption("--share-id <id>", "Share ID")
47
+ .addOption(new Option("--include-subpages <bool>", "Include subpages").choices(["true", "false"]))
48
+ .addOption(new Option("--search-indexing <bool>", "Allow search indexing").choices(["true", "false"]))
49
+ .action((options) => withClient(program, async (client, opts) => {
50
+ ensureOutputSupported(opts);
51
+ const includeSubPages = options.includeSubpages !== undefined ? options.includeSubpages === "true" : undefined;
52
+ const searchIndexing = options.searchIndexing !== undefined ? options.searchIndexing === "true" : undefined;
53
+ const result = await client.updateShare(options.shareId, includeSubPages, searchIndexing);
54
+ printResult(result, opts);
55
+ }));
56
+ program
57
+ .command("share-delete")
58
+ .description("Delete a share")
59
+ .requiredOption("--share-id <id>", "Share ID")
60
+ .action((options) => withClient(program, async (client, opts) => {
61
+ ensureOutputSupported(opts);
62
+ const result = await client.deleteShare(options.shareId);
63
+ printResult(result, opts);
64
+ }));
65
+ }