@doist/twist-cli 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.
Files changed (110) hide show
  1. package/README.md +76 -0
  2. package/dist/__tests__/auth.test.d.ts +2 -0
  3. package/dist/__tests__/auth.test.d.ts.map +1 -0
  4. package/dist/__tests__/auth.test.js +300 -0
  5. package/dist/__tests__/auth.test.js.map +1 -0
  6. package/dist/__tests__/lib/dates.test.d.ts +2 -0
  7. package/dist/__tests__/lib/dates.test.d.ts.map +1 -0
  8. package/dist/__tests__/lib/dates.test.js +58 -0
  9. package/dist/__tests__/lib/dates.test.js.map +1 -0
  10. package/dist/__tests__/lib/refs.test.d.ts +2 -0
  11. package/dist/__tests__/lib/refs.test.d.ts.map +1 -0
  12. package/dist/__tests__/lib/refs.test.js +121 -0
  13. package/dist/__tests__/lib/refs.test.js.map +1 -0
  14. package/dist/__tests__/spinner.test.d.ts +2 -0
  15. package/dist/__tests__/spinner.test.d.ts.map +1 -0
  16. package/dist/__tests__/spinner.test.js +153 -0
  17. package/dist/__tests__/spinner.test.js.map +1 -0
  18. package/dist/commands/auth.d.ts +3 -0
  19. package/dist/commands/auth.d.ts.map +1 -0
  20. package/dist/commands/auth.js +93 -0
  21. package/dist/commands/auth.js.map +1 -0
  22. package/dist/commands/channel.d.ts +3 -0
  23. package/dist/commands/channel.d.ts.map +1 -0
  24. package/dist/commands/channel.js +49 -0
  25. package/dist/commands/channel.js.map +1 -0
  26. package/dist/commands/inbox.d.ts +3 -0
  27. package/dist/commands/inbox.d.ts.map +1 -0
  28. package/dist/commands/inbox.js +121 -0
  29. package/dist/commands/inbox.js.map +1 -0
  30. package/dist/commands/msg.d.ts +3 -0
  31. package/dist/commands/msg.d.ts.map +1 -0
  32. package/dist/commands/msg.js +205 -0
  33. package/dist/commands/msg.js.map +1 -0
  34. package/dist/commands/react.d.ts +3 -0
  35. package/dist/commands/react.d.ts.map +1 -0
  36. package/dist/commands/react.js +100 -0
  37. package/dist/commands/react.js.map +1 -0
  38. package/dist/commands/search.d.ts +3 -0
  39. package/dist/commands/search.d.ts.map +1 -0
  40. package/dist/commands/search.js +134 -0
  41. package/dist/commands/search.js.map +1 -0
  42. package/dist/commands/thread.d.ts +3 -0
  43. package/dist/commands/thread.d.ts.map +1 -0
  44. package/dist/commands/thread.js +219 -0
  45. package/dist/commands/thread.js.map +1 -0
  46. package/dist/commands/user.d.ts +3 -0
  47. package/dist/commands/user.d.ts.map +1 -0
  48. package/dist/commands/user.js +67 -0
  49. package/dist/commands/user.js.map +1 -0
  50. package/dist/commands/workspace.d.ts +3 -0
  51. package/dist/commands/workspace.d.ts.map +1 -0
  52. package/dist/commands/workspace.js +48 -0
  53. package/dist/commands/workspace.js.map +1 -0
  54. package/dist/index.d.ts +3 -0
  55. package/dist/index.d.ts.map +1 -0
  56. package/dist/index.js +36 -0
  57. package/dist/index.js.map +1 -0
  58. package/dist/lib/api.d.ts +10 -0
  59. package/dist/lib/api.d.ts.map +1 -0
  60. package/dist/lib/api.js +143 -0
  61. package/dist/lib/api.js.map +1 -0
  62. package/dist/lib/auth.d.ts +4 -0
  63. package/dist/lib/auth.d.ts.map +1 -0
  64. package/dist/lib/auth.js +40 -0
  65. package/dist/lib/auth.js.map +1 -0
  66. package/dist/lib/config.d.ts +9 -0
  67. package/dist/lib/config.d.ts.map +1 -0
  68. package/dist/lib/config.js +26 -0
  69. package/dist/lib/config.js.map +1 -0
  70. package/dist/lib/dates.d.ts +3 -0
  71. package/dist/lib/dates.d.ts.map +1 -0
  72. package/dist/lib/dates.js +44 -0
  73. package/dist/lib/dates.js.map +1 -0
  74. package/dist/lib/input.d.ts +3 -0
  75. package/dist/lib/input.d.ts.map +1 -0
  76. package/dist/lib/input.js +52 -0
  77. package/dist/lib/input.js.map +1 -0
  78. package/dist/lib/markdown.d.ts +2 -0
  79. package/dist/lib/markdown.d.ts.map +1 -0
  80. package/dist/lib/markdown.js +12 -0
  81. package/dist/lib/markdown.js.map +1 -0
  82. package/dist/lib/oauth-server.d.ts +13 -0
  83. package/dist/lib/oauth-server.d.ts.map +1 -0
  84. package/dist/lib/oauth-server.js +168 -0
  85. package/dist/lib/oauth-server.js.map +1 -0
  86. package/dist/lib/oauth.d.ts +28 -0
  87. package/dist/lib/oauth.d.ts.map +1 -0
  88. package/dist/lib/oauth.js +125 -0
  89. package/dist/lib/oauth.js.map +1 -0
  90. package/dist/lib/output.d.ts +22 -0
  91. package/dist/lib/output.d.ts.map +1 -0
  92. package/dist/lib/output.js +104 -0
  93. package/dist/lib/output.js.map +1 -0
  94. package/dist/lib/pkce.d.ts +16 -0
  95. package/dist/lib/pkce.d.ts.map +1 -0
  96. package/dist/lib/pkce.js +35 -0
  97. package/dist/lib/pkce.js.map +1 -0
  98. package/dist/lib/refs.d.ts +29 -0
  99. package/dist/lib/refs.d.ts.map +1 -0
  100. package/dist/lib/refs.js +168 -0
  101. package/dist/lib/refs.js.map +1 -0
  102. package/dist/lib/search-api.d.ts +25 -0
  103. package/dist/lib/search-api.d.ts.map +1 -0
  104. package/dist/lib/search-api.js +85 -0
  105. package/dist/lib/search-api.js.map +1 -0
  106. package/dist/lib/spinner.d.ts +20 -0
  107. package/dist/lib/spinner.d.ts.map +1 -0
  108. package/dist/lib/spinner.js +70 -0
  109. package/dist/lib/spinner.js.map +1 -0
  110. package/package.json +71 -0
@@ -0,0 +1,205 @@
1
+ import { getFullTwistURL } from '@doist/twist-sdk';
2
+ import chalk from 'chalk';
3
+ import { getCurrentWorkspaceId, getTwistClient } from '../lib/api.js';
4
+ import { formatRelativeDate } from '../lib/dates.js';
5
+ import { openEditor, readStdin } from '../lib/input.js';
6
+ import { renderMarkdown } from '../lib/markdown.js';
7
+ import { colors, formatJson, formatNdjson } from '../lib/output.js';
8
+ import { resolveConversationId, resolveWorkspaceRef } from '../lib/refs.js';
9
+ async function showUnread(workspaceRef, options) {
10
+ let workspaceId;
11
+ if (workspaceRef) {
12
+ const workspace = await resolveWorkspaceRef(workspaceRef);
13
+ workspaceId = workspace.id;
14
+ }
15
+ else if (options.workspace) {
16
+ const workspace = await resolveWorkspaceRef(options.workspace);
17
+ workspaceId = workspace.id;
18
+ }
19
+ else {
20
+ workspaceId = await getCurrentWorkspaceId();
21
+ }
22
+ const client = await getTwistClient();
23
+ const unreadConversations = await client.conversations.getUnread(workspaceId);
24
+ if (unreadConversations.length === 0) {
25
+ console.log('No unread conversations.');
26
+ return;
27
+ }
28
+ const conversationCalls = unreadConversations.map((uc) => client.conversations.getConversation(uc.conversationId, { batch: true }));
29
+ const conversationResponses = await client.batch(...conversationCalls);
30
+ const conversations = conversationResponses.map((r) => r.data);
31
+ const userIds = new Set();
32
+ for (const conv of conversations) {
33
+ for (const id of conv.userIds) {
34
+ userIds.add(id);
35
+ }
36
+ }
37
+ const userCalls = [...userIds].map((id) => client.workspaceUsers.getUserById({ workspaceId, userId: id }, { batch: true }));
38
+ const userResponses = await client.batch(...userCalls);
39
+ const userMap = new Map(userResponses.map((r) => [r.data.id, r.data.name]));
40
+ if (options.json) {
41
+ const output = conversations.map((c) => ({
42
+ ...c,
43
+ participantNames: c.userIds.map((id) => userMap.get(id)),
44
+ url: getFullTwistURL({ workspaceId, conversationId: c.id }),
45
+ }));
46
+ console.log(formatJson(output, 'conversation', options.full));
47
+ return;
48
+ }
49
+ if (options.ndjson) {
50
+ const output = conversations.map((c) => ({
51
+ ...c,
52
+ participantNames: c.userIds.map((id) => userMap.get(id)),
53
+ url: getFullTwistURL({ workspaceId, conversationId: c.id }),
54
+ }));
55
+ console.log(formatNdjson(output, 'conversation', options.full));
56
+ return;
57
+ }
58
+ for (const conv of conversations) {
59
+ const participants = conv.userIds.map((id) => userMap.get(id) || `user:${id}`).join(', ');
60
+ const title = conv.title || `Conversation with ${participants}`;
61
+ const _unreadInfo = unreadConversations.find((uc) => uc.conversationId === conv.id);
62
+ console.log(chalk.bold(title));
63
+ console.log(` ${colors.timestamp(`id:${conv.id}`)} ${colors.author(participants)}`);
64
+ console.log(` ${colors.url(getFullTwistURL({ workspaceId, conversationId: conv.id }))}`);
65
+ console.log('');
66
+ }
67
+ }
68
+ async function viewConversation(ref, options) {
69
+ const conversationId = resolveConversationId(ref);
70
+ const client = await getTwistClient();
71
+ const limit = options.limit ? parseInt(options.limit, 10) : 50;
72
+ const [convResponse, messagesResponse] = await client.batch(client.conversations.getConversation(conversationId, { batch: true }), client.conversationMessages.getMessages({
73
+ conversationId,
74
+ limit,
75
+ }, { batch: true }));
76
+ const conversation = convResponse.data;
77
+ const messages = messagesResponse.data;
78
+ const userIds = new Set([...conversation.userIds, ...messages.map((m) => m.creator)]);
79
+ const userCalls = [...userIds].map((id) => client.workspaceUsers.getUserById({ workspaceId: conversation.workspaceId, userId: id }, { batch: true }));
80
+ const userResponses = await client.batch(...userCalls);
81
+ const userMap = new Map(userResponses.map((r) => [r.data.id, r.data.name]));
82
+ if (options.json) {
83
+ const output = {
84
+ conversation: {
85
+ ...conversation,
86
+ participantNames: conversation.userIds.map((id) => userMap.get(id)),
87
+ url: getFullTwistURL({
88
+ workspaceId: conversation.workspaceId,
89
+ conversationId: conversation.id,
90
+ }),
91
+ },
92
+ messages: messages.map((m) => ({
93
+ ...m,
94
+ creatorName: userMap.get(m.creator),
95
+ url: getFullTwistURL({
96
+ workspaceId: conversation.workspaceId,
97
+ conversationId: conversation.id,
98
+ messageId: m.id,
99
+ }),
100
+ })),
101
+ };
102
+ console.log(formatJson(output, undefined, options.full));
103
+ return;
104
+ }
105
+ if (options.ndjson) {
106
+ console.log(JSON.stringify({
107
+ type: 'conversation',
108
+ ...conversation,
109
+ participantNames: conversation.userIds.map((id) => userMap.get(id)),
110
+ }));
111
+ for (const m of messages) {
112
+ console.log(JSON.stringify({ type: 'message', ...m, creatorName: userMap.get(m.creator) }));
113
+ }
114
+ return;
115
+ }
116
+ const participants = conversation.userIds
117
+ .map((id) => userMap.get(id) || `user:${id}`)
118
+ .join(', ');
119
+ const title = conversation.title || `Conversation with ${participants}`;
120
+ console.log(chalk.bold(title));
121
+ console.log(colors.timestamp(`id:${conversation.id}`));
122
+ console.log('');
123
+ if (messages.length === 0) {
124
+ console.log('No messages.');
125
+ return;
126
+ }
127
+ for (const message of messages) {
128
+ const author = colors.author(userMap.get(message.creator) || `user:${message.creator}`);
129
+ const time = colors.timestamp(formatRelativeDate(message.posted));
130
+ console.log(`${author} ${time} ${colors.timestamp(`id:${message.id}`)}`);
131
+ console.log(options.raw ? message.content : renderMarkdown(message.content));
132
+ console.log('');
133
+ }
134
+ }
135
+ async function replyToConversation(ref, content, options) {
136
+ const conversationId = resolveConversationId(ref);
137
+ let replyContent = await readStdin();
138
+ if (!replyContent && content) {
139
+ replyContent = content;
140
+ }
141
+ if (!replyContent) {
142
+ replyContent = await openEditor();
143
+ }
144
+ if (!replyContent || replyContent.trim() === '') {
145
+ console.error('No content provided.');
146
+ process.exit(1);
147
+ }
148
+ if (options.dryRun) {
149
+ console.log('Dry run: would send message to conversation', conversationId);
150
+ console.log('');
151
+ console.log(replyContent);
152
+ return;
153
+ }
154
+ const client = await getTwistClient();
155
+ const conversation = await client.conversations.getConversation(conversationId);
156
+ const message = await client.conversationMessages.createMessage({
157
+ conversationId,
158
+ content: replyContent,
159
+ });
160
+ const url = getFullTwistURL({
161
+ workspaceId: conversation.workspaceId,
162
+ conversationId,
163
+ messageId: message.id,
164
+ });
165
+ console.log(`Message sent: ${url}`);
166
+ }
167
+ async function markConversationDone(ref, options) {
168
+ const conversationId = resolveConversationId(ref);
169
+ if (options.dryRun) {
170
+ console.log(`Dry run: would archive conversation ${conversationId}`);
171
+ return;
172
+ }
173
+ const client = await getTwistClient();
174
+ await client.conversations.archiveConversation(conversationId);
175
+ console.log(`Conversation ${conversationId} archived.`);
176
+ }
177
+ export function registerMsgCommand(program) {
178
+ const msg = program.command('msg').description('Conversation (DM/group) operations');
179
+ msg.command('unread [workspace-ref]')
180
+ .description('List unread conversations')
181
+ .option('--workspace <ref>', 'Workspace ID or name')
182
+ .option('--json', 'Output as JSON')
183
+ .option('--ndjson', 'Output as newline-delimited JSON')
184
+ .option('--full', 'Include all fields in JSON output')
185
+ .action(showUnread);
186
+ msg.command('view <conversation-ref>')
187
+ .description('Display a conversation with its messages')
188
+ .option('--limit <n>', 'Max messages to show (default: 50)')
189
+ .option('--since <date>', 'Messages newer than')
190
+ .option('--until <date>', 'Messages older than')
191
+ .option('--raw', 'Show raw markdown instead of rendered')
192
+ .option('--json', 'Output as JSON')
193
+ .option('--ndjson', 'Output as newline-delimited JSON')
194
+ .option('--full', 'Include all fields in JSON output')
195
+ .action(viewConversation);
196
+ msg.command('reply <conversation-ref> [content]')
197
+ .description('Send a message in a conversation')
198
+ .option('--dry-run', 'Show what would be sent without sending')
199
+ .action(replyToConversation);
200
+ msg.command('done <conversation-ref>')
201
+ .description('Archive a conversation')
202
+ .option('--dry-run', 'Show what would happen without executing')
203
+ .action(markConversationDone);
204
+ }
205
+ //# sourceMappingURL=msg.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"msg.js","sourceRoot":"","sources":["../../src/commands/msg.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import { Command } from 'commander';
2
+ export declare function registerReactCommand(program: Command): void;
3
+ //# sourceMappingURL=react.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"react.d.ts","sourceRoot":"","sources":["../../src/commands/react.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AA0GnC,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CA4B3D"}
@@ -0,0 +1,100 @@
1
+ import { getTwistClient } from '../lib/api.js';
2
+ function parseTargetId(ref) {
3
+ const id = ref.startsWith('id:') ? ref.slice(3) : ref;
4
+ const parsed = parseInt(id, 10);
5
+ if (Number.isNaN(parsed)) {
6
+ throw new Error(`Invalid ID: ${ref}`);
7
+ }
8
+ return parsed;
9
+ }
10
+ function normalizeEmoji(emoji) {
11
+ const shortcodeMap = {
12
+ '+1': '👍',
13
+ '-1': '👎',
14
+ heart: '❤️',
15
+ tada: '🎉',
16
+ smile: '😊',
17
+ laughing: '😂',
18
+ thinking: '🤔',
19
+ fire: '🔥',
20
+ check: '✅',
21
+ x: '❌',
22
+ eyes: '👀',
23
+ pray: '🙏',
24
+ clap: '👏',
25
+ rocket: '🚀',
26
+ wave: '👋',
27
+ };
28
+ return shortcodeMap[emoji.toLowerCase()] || emoji;
29
+ }
30
+ async function addReaction(targetType, targetRef, emoji, options) {
31
+ const targetId = parseTargetId(targetRef);
32
+ const normalizedEmoji = normalizeEmoji(emoji);
33
+ if (options.dryRun) {
34
+ console.log(`Dry run: would add ${normalizedEmoji} to ${targetType} ${targetId}`);
35
+ return;
36
+ }
37
+ const client = await getTwistClient();
38
+ const params = {
39
+ reaction: normalizedEmoji,
40
+ };
41
+ if (targetType === 'thread') {
42
+ params.threadId = targetId;
43
+ }
44
+ else if (targetType === 'comment') {
45
+ params.commentId = targetId;
46
+ }
47
+ else {
48
+ params.messageId = targetId;
49
+ }
50
+ await client.reactions.add(params);
51
+ console.log(`Added ${normalizedEmoji} to ${targetType} ${targetId}`);
52
+ }
53
+ async function removeReaction(targetType, targetRef, emoji, options) {
54
+ const targetId = parseTargetId(targetRef);
55
+ const normalizedEmoji = normalizeEmoji(emoji);
56
+ if (options.dryRun) {
57
+ console.log(`Dry run: would remove ${normalizedEmoji} from ${targetType} ${targetId}`);
58
+ return;
59
+ }
60
+ const client = await getTwistClient();
61
+ const params = {
62
+ reaction: normalizedEmoji,
63
+ };
64
+ if (targetType === 'thread') {
65
+ params.threadId = targetId;
66
+ }
67
+ else if (targetType === 'comment') {
68
+ params.commentId = targetId;
69
+ }
70
+ else {
71
+ params.messageId = targetId;
72
+ }
73
+ await client.reactions.remove(params);
74
+ console.log(`Removed ${normalizedEmoji} from ${targetType} ${targetId}`);
75
+ }
76
+ export function registerReactCommand(program) {
77
+ program
78
+ .command('react <target-type> <target-ref> <emoji>')
79
+ .description('Add an emoji reaction (target-type: thread, comment, message)')
80
+ .option('--dry-run', 'Show what would happen without executing')
81
+ .action((targetType, targetRef, emoji, options) => {
82
+ if (!['thread', 'comment', 'message'].includes(targetType)) {
83
+ console.error(`Invalid target type: ${targetType}. Use: thread, comment, or message`);
84
+ process.exit(1);
85
+ }
86
+ return addReaction(targetType, targetRef, emoji, options);
87
+ });
88
+ program
89
+ .command('unreact <target-type> <target-ref> <emoji>')
90
+ .description('Remove an emoji reaction (target-type: thread, comment, message)')
91
+ .option('--dry-run', 'Show what would happen without executing')
92
+ .action((targetType, targetRef, emoji, options) => {
93
+ if (!['thread', 'comment', 'message'].includes(targetType)) {
94
+ console.error(`Invalid target type: ${targetType}. Use: thread, comment, or message`);
95
+ process.exit(1);
96
+ }
97
+ return removeReaction(targetType, targetRef, emoji, options);
98
+ });
99
+ }
100
+ //# sourceMappingURL=react.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"react.js","sourceRoot":"","sources":["../../src/commands/react.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import { Command } from 'commander';
2
+ export declare function registerSearchCommand(program: Command): void;
3
+ //# sourceMappingURL=search.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"search.d.ts","sourceRoot":"","sources":["../../src/commands/search.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AAgKnC,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAoB5D"}
@@ -0,0 +1,134 @@
1
+ import { getFullTwistURL } from '@doist/twist-sdk';
2
+ import { getCurrentWorkspaceId } from '../lib/api.js';
3
+ import { formatRelativeDate } from '../lib/dates.js';
4
+ import { colors, formatJson } from '../lib/output.js';
5
+ import { resolveUserRefs, resolveWorkspaceRef } from '../lib/refs.js';
6
+ import { extendedSearch } from '../lib/search-api.js';
7
+ async function resolveUserRefsOrExit(refs, workspaceId) {
8
+ if (!refs)
9
+ return undefined;
10
+ try {
11
+ return await resolveUserRefs(refs, workspaceId);
12
+ }
13
+ catch (e) {
14
+ console.error(e.message);
15
+ process.exit(1);
16
+ }
17
+ }
18
+ async function search(query, workspaceRef, options) {
19
+ let workspaceId;
20
+ if (workspaceRef) {
21
+ const workspace = await resolveWorkspaceRef(workspaceRef);
22
+ workspaceId = workspace.id;
23
+ }
24
+ else if (options.workspace) {
25
+ const workspace = await resolveWorkspaceRef(options.workspace);
26
+ workspaceId = workspace.id;
27
+ }
28
+ else {
29
+ workspaceId = await getCurrentWorkspaceId();
30
+ }
31
+ const limit = options.limit ? parseInt(options.limit, 10) : 50;
32
+ const channelIds = options.channel
33
+ ? options.channel.split(',').map((id) => parseInt(id.trim(), 10))
34
+ : undefined;
35
+ const authorIds = await resolveUserRefsOrExit(options.author, workspaceId);
36
+ const toUserIds = await resolveUserRefsOrExit(options.to, workspaceId);
37
+ const conversationIds = options.conversation
38
+ ? options.conversation.split(',').map((id) => parseInt(id.trim(), 10))
39
+ : undefined;
40
+ const response = await extendedSearch({
41
+ workspaceId,
42
+ query: options.titleOnly ? undefined : query,
43
+ title: options.titleOnly ? query : undefined,
44
+ type: options.type,
45
+ channelIds,
46
+ conversationIds,
47
+ authorIds,
48
+ toUserIds,
49
+ mentionSelf: options.mentionMe,
50
+ dateFrom: options.since,
51
+ dateTo: options.until,
52
+ limit,
53
+ cursor: options.cursor,
54
+ });
55
+ if (response.items.length === 0) {
56
+ console.log('No results found.');
57
+ return;
58
+ }
59
+ if (options.json) {
60
+ const output = {
61
+ results: response.items.map((r) => ({
62
+ ...r,
63
+ url: buildSearchResultUrl(workspaceId, r),
64
+ })),
65
+ nextCursor: response.nextCursorMark || null,
66
+ };
67
+ console.log(formatJson(output, undefined, options.full));
68
+ return;
69
+ }
70
+ if (options.ndjson) {
71
+ for (const r of response.items) {
72
+ console.log(JSON.stringify({ ...r, url: buildSearchResultUrl(workspaceId, r) }));
73
+ }
74
+ if (response.nextCursorMark) {
75
+ console.log(JSON.stringify({ _meta: true, nextCursor: response.nextCursorMark }));
76
+ }
77
+ return;
78
+ }
79
+ for (const result of response.items) {
80
+ const type = colors.channel(`[${result.type}]`);
81
+ const title = result.title || result.snippet.slice(0, 50);
82
+ const time = colors.timestamp(formatRelativeDate(result.snippetLastUpdated));
83
+ console.log(`${type} ${title}`);
84
+ console.log(` ${colors.timestamp(result.snippet.slice(0, 100))}`);
85
+ console.log(` ${time} ${colors.url(buildSearchResultUrl(workspaceId, result))}`);
86
+ console.log('');
87
+ }
88
+ if (response.hasMore) {
89
+ console.log(colors.timestamp(`More results available. Use --cursor ${response.nextCursorMark}`));
90
+ }
91
+ }
92
+ function buildSearchResultUrl(workspaceId, result) {
93
+ if (result.type === 'thread' && result.threadId && result.channelId) {
94
+ return getFullTwistURL({
95
+ workspaceId,
96
+ channelId: result.channelId,
97
+ threadId: result.threadId,
98
+ });
99
+ }
100
+ if (result.type === 'comment' && result.threadId && result.channelId && result.commentId) {
101
+ return getFullTwistURL({
102
+ workspaceId,
103
+ channelId: result.channelId,
104
+ threadId: result.threadId,
105
+ commentId: result.commentId,
106
+ });
107
+ }
108
+ if (result.type === 'message' && result.conversationId) {
109
+ return getFullTwistURL({ workspaceId, conversationId: result.conversationId });
110
+ }
111
+ return `https://twist.com/a/${workspaceId}`;
112
+ }
113
+ export function registerSearchCommand(program) {
114
+ program
115
+ .command('search <query> [workspace-ref]')
116
+ .description('Search content across a workspace')
117
+ .option('--workspace <ref>', 'Workspace ID or name')
118
+ .option('--channel <channel-refs>', 'Filter by channels (comma-separated IDs)')
119
+ .option('--author <user-refs>', 'Filter by author (comma-separated IDs)')
120
+ .option('--to <user-refs>', 'Messages sent TO user (comma-separated IDs)')
121
+ .option('--type <type>', 'Filter: threads, messages, or all')
122
+ .option('--title-only', 'Search in thread titles only')
123
+ .option('--conversation <refs>', 'Limit to conversations (comma-separated IDs)')
124
+ .option('--mention-me', 'Only results mentioning current user')
125
+ .option('--since <date>', 'Content from date')
126
+ .option('--until <date>', 'Content until date')
127
+ .option('--limit <n>', 'Max results (default: 50)')
128
+ .option('--cursor <cursor>', 'Pagination cursor')
129
+ .option('--json', 'Output as JSON')
130
+ .option('--ndjson', 'Output as newline-delimited JSON')
131
+ .option('--full', 'Include all fields in JSON output')
132
+ .action(search);
133
+ }
134
+ //# sourceMappingURL=search.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"search.js","sourceRoot":"","sources":["../../src/commands/search.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import { Command } from 'commander';
2
+ export declare function registerThreadCommand(program: Command): void;
3
+ //# sourceMappingURL=thread.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"thread.d.ts","sourceRoot":"","sources":["../../src/commands/thread.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AA+QnC,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CA4B5D"}