@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,104 @@
1
+ import chalk from 'chalk';
2
+ export const colors = {
3
+ author: chalk.cyan,
4
+ timestamp: chalk.dim,
5
+ channel: chalk.blue,
6
+ unread: chalk.bold,
7
+ url: chalk.dim,
8
+ error: chalk.red,
9
+ };
10
+ const THREAD_ESSENTIAL_FIELDS = [
11
+ 'id',
12
+ 'title',
13
+ 'channelId',
14
+ 'workspaceId',
15
+ 'creator',
16
+ 'posted',
17
+ 'commentCount',
18
+ 'isArchived',
19
+ ];
20
+ const COMMENT_ESSENTIAL_FIELDS = ['id', 'content', 'creator', 'threadId', 'posted'];
21
+ const CONVERSATION_ESSENTIAL_FIELDS = [
22
+ 'id',
23
+ 'workspaceId',
24
+ 'userIds',
25
+ 'title',
26
+ 'messageCount',
27
+ 'lastActive',
28
+ 'archived',
29
+ ];
30
+ const MESSAGE_ESSENTIAL_FIELDS = ['id', 'content', 'creator', 'conversationId', 'posted'];
31
+ const WORKSPACE_ESSENTIAL_FIELDS = ['id', 'name', 'creator', 'plan'];
32
+ const USER_ESSENTIAL_FIELDS = ['id', 'name', 'email', 'timezone', 'userType'];
33
+ const CHANNEL_ESSENTIAL_FIELDS = ['id', 'name', 'workspaceId'];
34
+ function getEssentialFields(type) {
35
+ switch (type) {
36
+ case 'thread':
37
+ return THREAD_ESSENTIAL_FIELDS;
38
+ case 'comment':
39
+ return COMMENT_ESSENTIAL_FIELDS;
40
+ case 'conversation':
41
+ return CONVERSATION_ESSENTIAL_FIELDS;
42
+ case 'message':
43
+ return MESSAGE_ESSENTIAL_FIELDS;
44
+ case 'workspace':
45
+ return WORKSPACE_ESSENTIAL_FIELDS;
46
+ case 'user':
47
+ return USER_ESSENTIAL_FIELDS;
48
+ case 'channel':
49
+ return CHANNEL_ESSENTIAL_FIELDS;
50
+ }
51
+ }
52
+ function pickFields(item, fields) {
53
+ const result = {};
54
+ for (const field of fields) {
55
+ if (field in item) {
56
+ ;
57
+ result[field] = item[field];
58
+ }
59
+ }
60
+ return result;
61
+ }
62
+ export function formatJson(data, type, full = false) {
63
+ if (full || !type) {
64
+ return JSON.stringify(data, null, 2);
65
+ }
66
+ const fields = getEssentialFields(type);
67
+ if (Array.isArray(data)) {
68
+ return JSON.stringify(data.map((item) => pickFields(item, fields)), null, 2);
69
+ }
70
+ return JSON.stringify(pickFields(data, fields), null, 2);
71
+ }
72
+ export function formatNdjson(items, type, full = false) {
73
+ if (full || !type) {
74
+ return items.map((item) => JSON.stringify(item)).join('\n');
75
+ }
76
+ const fields = getEssentialFields(type);
77
+ return items.map((item) => JSON.stringify(pickFields(item, fields))).join('\n');
78
+ }
79
+ export function formatPaginatedJson(data, type, full = false) {
80
+ const fields = type && !full ? getEssentialFields(type) : null;
81
+ const results = fields ? data.results.map((item) => pickFields(item, fields)) : data.results;
82
+ return JSON.stringify({ results, nextCursor: data.nextCursor }, null, 2);
83
+ }
84
+ export function formatPaginatedNdjson(data, type, full = false) {
85
+ const fields = type && !full ? getEssentialFields(type) : null;
86
+ const lines = data.results.map((item) => JSON.stringify(fields ? pickFields(item, fields) : item));
87
+ if (data.nextCursor) {
88
+ lines.push(JSON.stringify({ _meta: true, nextCursor: data.nextCursor }));
89
+ }
90
+ return lines.join('\n');
91
+ }
92
+ export function formatError(message) {
93
+ return colors.error(message);
94
+ }
95
+ export function printError(message) {
96
+ console.error(formatError(message));
97
+ }
98
+ export function printJson(data, type, full = false) {
99
+ console.log(formatJson(data, type, full));
100
+ }
101
+ export function printNdjson(items, type, full = false) {
102
+ console.log(formatNdjson(items, type, full));
103
+ }
104
+ //# sourceMappingURL=output.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"output.js","sourceRoot":"","sources":["../../src/lib/output.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Generate a cryptographically secure random code verifier for PKCE.
3
+ * Returns a base64url-encoded string with 43-128 characters.
4
+ */
5
+ export declare function generateCodeVerifier(): string;
6
+ /**
7
+ * Generate a code challenge from a code verifier using SHA256 and base64url encoding.
8
+ * This is the S256 method as specified in RFC 7636.
9
+ */
10
+ export declare function generateCodeChallenge(verifier: string): string;
11
+ /**
12
+ * Generate a cryptographically secure random state parameter for CSRF protection.
13
+ * Returns a base64url-encoded string.
14
+ */
15
+ export declare function generateState(): string;
16
+ //# sourceMappingURL=pkce.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pkce.d.ts","sourceRoot":"","sources":["../../src/lib/pkce.ts"],"names":[],"mappings":"AAEA;;;GAGG;AACH,wBAAgB,oBAAoB,IAAI,MAAM,CAI7C;AAED;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAG9D;AAED;;;GAGG;AACH,wBAAgB,aAAa,IAAI,MAAM,CAItC"}
@@ -0,0 +1,35 @@
1
+ import { createHash, randomBytes } from 'node:crypto';
2
+ /**
3
+ * Generate a cryptographically secure random code verifier for PKCE.
4
+ * Returns a base64url-encoded string with 43-128 characters.
5
+ */
6
+ export function generateCodeVerifier() {
7
+ // Generate 32 random bytes (256 bits) which gives us 43 base64url characters
8
+ const buffer = randomBytes(32);
9
+ return base64urlEncode(buffer);
10
+ }
11
+ /**
12
+ * Generate a code challenge from a code verifier using SHA256 and base64url encoding.
13
+ * This is the S256 method as specified in RFC 7636.
14
+ */
15
+ export function generateCodeChallenge(verifier) {
16
+ const hash = createHash('sha256').update(verifier).digest();
17
+ return base64urlEncode(hash);
18
+ }
19
+ /**
20
+ * Generate a cryptographically secure random state parameter for CSRF protection.
21
+ * Returns a base64url-encoded string.
22
+ */
23
+ export function generateState() {
24
+ // Generate 16 random bytes (128 bits) for the state parameter
25
+ const buffer = randomBytes(16);
26
+ return base64urlEncode(buffer);
27
+ }
28
+ /**
29
+ * Base64url encode a buffer (RFC 4648 Section 5).
30
+ * This removes padding and uses URL-safe characters.
31
+ */
32
+ function base64urlEncode(buffer) {
33
+ return buffer.toString('base64').replace(/\+/g, '-').replace(/\//g, '_').replace(/=/g, '');
34
+ }
35
+ //# sourceMappingURL=pkce.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pkce.js","sourceRoot":"","sources":["../../src/lib/pkce.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AAErD;;;GAGG;AACH,MAAM,UAAU,oBAAoB;IAChC,6EAA6E;IAC7E,MAAM,MAAM,GAAG,WAAW,CAAC,EAAE,CAAC,CAAA;IAC9B,OAAO,eAAe,CAAC,MAAM,CAAC,CAAA;AAClC,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,qBAAqB,CAAC,QAAgB;IAClD,MAAM,IAAI,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,MAAM,EAAE,CAAA;IAC3D,OAAO,eAAe,CAAC,IAAI,CAAC,CAAA;AAChC,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,aAAa;IACzB,8DAA8D;IAC9D,MAAM,MAAM,GAAG,WAAW,CAAC,EAAE,CAAC,CAAA;IAC9B,OAAO,eAAe,CAAC,MAAM,CAAC,CAAA;AAClC,CAAC;AAED;;;GAGG;AACH,SAAS,eAAe,CAAC,MAAc;IACnC,OAAO,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC,CAAA;AAC9F,CAAC"}
@@ -0,0 +1,29 @@
1
+ import type { Workspace } from '@doist/twist-sdk';
2
+ export declare function isIdRef(ref: string): boolean;
3
+ export declare function extractId(ref: string): number;
4
+ export interface ParsedTwistUrl {
5
+ workspaceId?: number;
6
+ channelId?: number;
7
+ threadId?: number;
8
+ commentId?: number;
9
+ conversationId?: number;
10
+ messageId?: number;
11
+ }
12
+ export declare function parseTwistUrl(url: string): ParsedTwistUrl | null;
13
+ export declare function parseRef(ref: string): {
14
+ type: 'id';
15
+ id: number;
16
+ } | {
17
+ type: 'url';
18
+ parsed: ParsedTwistUrl;
19
+ } | {
20
+ type: 'name';
21
+ name: string;
22
+ };
23
+ export declare function resolveWorkspaceRef(ref: string): Promise<Workspace>;
24
+ export declare function resolveThreadId(ref: string): number;
25
+ export declare function resolveCommentId(ref: string): number;
26
+ export declare function resolveConversationId(ref: string): number;
27
+ export declare function resolveMessageId(ref: string): number;
28
+ export declare function resolveUserRefs(refs: string, workspaceId: number): Promise<number[]>;
29
+ //# sourceMappingURL=refs.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"refs.d.ts","sourceRoot":"","sources":["../../src/lib/refs.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAA;AAGjD,wBAAgB,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAE5C;AAED,wBAAgB,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAO7C;AAED,MAAM,WAAW,cAAc;IAC3B,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,SAAS,CAAC,EAAE,MAAM,CAAA;CACrB;AAED,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,cAAc,GAAG,IAAI,CA8ChE;AAED,wBAAgB,QAAQ,CACpB,GAAG,EAAE,MAAM,GAET;IAAE,IAAI,EAAE,IAAI,CAAC;IAAC,EAAE,EAAE,MAAM,CAAA;CAAE,GAC1B;IAAE,IAAI,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,cAAc,CAAA;CAAE,GACvC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAkBnC;AAED,wBAAsB,mBAAmB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,CAAC,CAqCzE;AAED,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAYnD;AAED,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAYpD;AAED,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAYzD;AAED,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAYpD;AAED,wBAAsB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAgC1F"}
@@ -0,0 +1,168 @@
1
+ import { fetchWorkspaces } from './api.js';
2
+ export function isIdRef(ref) {
3
+ return ref.startsWith('id:');
4
+ }
5
+ export function extractId(ref) {
6
+ const idStr = ref.startsWith('id:') ? ref.slice(3) : ref;
7
+ const id = parseInt(idStr, 10);
8
+ if (Number.isNaN(id)) {
9
+ throw new Error(`Invalid ID: ${ref}`);
10
+ }
11
+ return id;
12
+ }
13
+ export function parseTwistUrl(url) {
14
+ try {
15
+ const parsed = new URL(url);
16
+ if (!parsed.hostname.includes('twist.com')) {
17
+ return null;
18
+ }
19
+ const path = parsed.pathname;
20
+ const result = {};
21
+ // Pattern: /a/{workspaceId}/ch/{channelId}/t/{threadId}/c/{commentId}
22
+ // Pattern: /a/{workspaceId}/msg/{conversationId}/m/{messageId}
23
+ const workspaceMatch = path.match(/\/a\/(\d+)/);
24
+ if (workspaceMatch) {
25
+ result.workspaceId = parseInt(workspaceMatch[1], 10);
26
+ }
27
+ const channelMatch = path.match(/\/ch\/(\d+)/);
28
+ if (channelMatch) {
29
+ result.channelId = parseInt(channelMatch[1], 10);
30
+ }
31
+ const threadMatch = path.match(/\/t\/(\d+)/);
32
+ if (threadMatch) {
33
+ result.threadId = parseInt(threadMatch[1], 10);
34
+ }
35
+ const commentMatch = path.match(/\/c\/(\d+)/);
36
+ if (commentMatch) {
37
+ result.commentId = parseInt(commentMatch[1], 10);
38
+ }
39
+ const conversationMatch = path.match(/\/msg\/(\d+)/);
40
+ if (conversationMatch) {
41
+ result.conversationId = parseInt(conversationMatch[1], 10);
42
+ }
43
+ const messageMatch = path.match(/\/m\/(\d+)/);
44
+ if (messageMatch) {
45
+ result.messageId = parseInt(messageMatch[1], 10);
46
+ }
47
+ return Object.keys(result).length > 0 ? result : null;
48
+ }
49
+ catch {
50
+ return null;
51
+ }
52
+ }
53
+ export function parseRef(ref) {
54
+ if (isIdRef(ref)) {
55
+ return { type: 'id', id: extractId(ref) };
56
+ }
57
+ if (ref.startsWith('http://') || ref.startsWith('https://')) {
58
+ const parsed = parseTwistUrl(ref);
59
+ if (parsed) {
60
+ return { type: 'url', parsed };
61
+ }
62
+ }
63
+ const bareId = parseInt(ref, 10);
64
+ if (!Number.isNaN(bareId) && String(bareId) === ref) {
65
+ return { type: 'id', id: bareId };
66
+ }
67
+ return { type: 'name', name: ref };
68
+ }
69
+ export async function resolveWorkspaceRef(ref) {
70
+ const workspaces = await fetchWorkspaces();
71
+ const parsed = parseRef(ref);
72
+ if (parsed.type === 'id') {
73
+ const workspace = workspaces.find((w) => w.id === parsed.id);
74
+ if (!workspace) {
75
+ throw new Error(`Workspace with ID ${parsed.id} not found`);
76
+ }
77
+ return workspace;
78
+ }
79
+ if (parsed.type === 'url' && parsed.parsed.workspaceId) {
80
+ const workspace = workspaces.find((w) => w.id === parsed.parsed.workspaceId);
81
+ if (!workspace) {
82
+ throw new Error(`Workspace with ID ${parsed.parsed.workspaceId} not found`);
83
+ }
84
+ return workspace;
85
+ }
86
+ if (parsed.type === 'name') {
87
+ const lower = parsed.name.toLowerCase();
88
+ const exact = workspaces.find((w) => w.name.toLowerCase() === lower);
89
+ if (exact)
90
+ return exact;
91
+ const partial = workspaces.filter((w) => w.name.toLowerCase().includes(lower));
92
+ if (partial.length === 1)
93
+ return partial[0];
94
+ if (partial.length > 1) {
95
+ const matches = partial
96
+ .slice(0, 5)
97
+ .map((w) => `"${w.name}" (id:${w.id})`)
98
+ .join(', ');
99
+ throw new Error(`Multiple workspaces match "${ref}": ${matches}`);
100
+ }
101
+ }
102
+ throw new Error(`Workspace "${ref}" not found`);
103
+ }
104
+ export function resolveThreadId(ref) {
105
+ const parsed = parseRef(ref);
106
+ if (parsed.type === 'id') {
107
+ return parsed.id;
108
+ }
109
+ if (parsed.type === 'url' && parsed.parsed.threadId) {
110
+ return parsed.parsed.threadId;
111
+ }
112
+ throw new Error(`Invalid thread reference: ${ref}. Use thread ID or Twist URL.`);
113
+ }
114
+ export function resolveCommentId(ref) {
115
+ const parsed = parseRef(ref);
116
+ if (parsed.type === 'id') {
117
+ return parsed.id;
118
+ }
119
+ if (parsed.type === 'url' && parsed.parsed.commentId) {
120
+ return parsed.parsed.commentId;
121
+ }
122
+ throw new Error(`Invalid comment reference: ${ref}. Use comment ID or Twist URL.`);
123
+ }
124
+ export function resolveConversationId(ref) {
125
+ const parsed = parseRef(ref);
126
+ if (parsed.type === 'id') {
127
+ return parsed.id;
128
+ }
129
+ if (parsed.type === 'url' && parsed.parsed.conversationId) {
130
+ return parsed.parsed.conversationId;
131
+ }
132
+ throw new Error(`Invalid conversation reference: ${ref}. Use conversation ID or Twist URL.`);
133
+ }
134
+ export function resolveMessageId(ref) {
135
+ const parsed = parseRef(ref);
136
+ if (parsed.type === 'id') {
137
+ return parsed.id;
138
+ }
139
+ if (parsed.type === 'url' && parsed.parsed.messageId) {
140
+ return parsed.parsed.messageId;
141
+ }
142
+ throw new Error(`Invalid message reference: ${ref}. Use message ID or Twist URL.`);
143
+ }
144
+ export async function resolveUserRefs(refs, workspaceId) {
145
+ const { getWorkspaceUsers } = await import('./api.js');
146
+ const users = await getWorkspaceUsers(workspaceId);
147
+ const parts = refs.split(',').map((r) => r.trim());
148
+ const ids = [];
149
+ for (const ref of parts) {
150
+ const parsed = parseRef(ref);
151
+ if (parsed.type === 'id') {
152
+ ids.push(parsed.id);
153
+ continue;
154
+ }
155
+ const query = ref.toLowerCase();
156
+ const matches = users.filter((u) => u.name.toLowerCase().includes(query) || u.email?.toLowerCase().includes(query));
157
+ if (matches.length === 0) {
158
+ throw new Error(`No user found matching "${ref}"`);
159
+ }
160
+ if (matches.length > 1) {
161
+ const list = matches.map((u) => ` ${u.id} ${u.name} <${u.email ?? ''}>`).join('\n');
162
+ throw new Error(`Multiple users match "${ref}":\n${list}\n\nUse numeric ID to specify.`);
163
+ }
164
+ ids.push(matches[0].id);
165
+ }
166
+ return ids;
167
+ }
168
+ //# sourceMappingURL=refs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"refs.js","sourceRoot":"","sources":["../../src/lib/refs.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,25 @@
1
+ import type { SearchResult } from '@doist/twist-sdk';
2
+ export type SearchType = 'threads' | 'messages' | 'all';
3
+ export interface ExtendedSearchParams {
4
+ workspaceId: number;
5
+ query?: string;
6
+ title?: string;
7
+ type?: SearchType;
8
+ channelIds?: number[];
9
+ conversationIds?: number[];
10
+ authorIds?: number[];
11
+ toUserIds?: number[];
12
+ mentionSelf?: boolean;
13
+ dateFrom?: string;
14
+ dateTo?: string;
15
+ limit?: number;
16
+ cursor?: string;
17
+ }
18
+ export interface ExtendedSearchResponse {
19
+ items: SearchResult[];
20
+ nextCursorMark?: string;
21
+ hasMore: boolean;
22
+ isPlanRestricted: boolean;
23
+ }
24
+ export declare function extendedSearch(params: ExtendedSearchParams): Promise<ExtendedSearchResponse>;
25
+ //# sourceMappingURL=search-api.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"search-api.d.ts","sourceRoot":"","sources":["../../src/lib/search-api.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAA;AAKpD,MAAM,MAAM,UAAU,GAAG,SAAS,GAAG,UAAU,GAAG,KAAK,CAAA;AAEvD,MAAM,WAAW,oBAAoB;IACjC,WAAW,EAAE,MAAM,CAAA;IACnB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,IAAI,CAAC,EAAE,UAAU,CAAA;IACjB,UAAU,CAAC,EAAE,MAAM,EAAE,CAAA;IACrB,eAAe,CAAC,EAAE,MAAM,EAAE,CAAA;IAC1B,SAAS,CAAC,EAAE,MAAM,EAAE,CAAA;IACpB,SAAS,CAAC,EAAE,MAAM,EAAE,CAAA;IACpB,WAAW,CAAC,EAAE,OAAO,CAAA;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,MAAM,CAAC,EAAE,MAAM,CAAA;CAClB;AAED,MAAM,WAAW,sBAAsB;IACnC,KAAK,EAAE,YAAY,EAAE,CAAA;IACrB,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,OAAO,EAAE,OAAO,CAAA;IAChB,gBAAgB,EAAE,OAAO,CAAA;CAC5B;AA8BD,wBAAsB,cAAc,CAChC,MAAM,EAAE,oBAAoB,GAC7B,OAAO,CAAC,sBAAsB,CAAC,CAqDjC"}
@@ -0,0 +1,85 @@
1
+ import { getApiToken } from './auth.js';
2
+ const BASE_URL = 'https://api.twist.com/api/v3';
3
+ function toCamelCase(str) {
4
+ return str.replace(/_([a-z])/g, (_, letter) => letter.toUpperCase());
5
+ }
6
+ function camelCaseKeys(obj) {
7
+ if (Array.isArray(obj)) {
8
+ return obj.map((item) => camelCaseKeys(item));
9
+ }
10
+ if (obj !== null && typeof obj === 'object') {
11
+ const result = {};
12
+ for (const [key, value] of Object.entries(obj)) {
13
+ const camelKey = toCamelCase(key);
14
+ result[camelKey] = camelCaseKeys(value);
15
+ }
16
+ return result;
17
+ }
18
+ return obj;
19
+ }
20
+ function transformSearchResult(item) {
21
+ const result = camelCaseKeys(item);
22
+ if (typeof result.snippetLastUpdatedTs === 'number') {
23
+ result.snippetLastUpdated = new Date(result.snippetLastUpdatedTs * 1000);
24
+ delete result.snippetLastUpdatedTs;
25
+ }
26
+ return result;
27
+ }
28
+ export async function extendedSearch(params) {
29
+ const token = await getApiToken();
30
+ const apiParams = {
31
+ workspace_id: params.workspaceId,
32
+ };
33
+ if (params.query)
34
+ apiParams.query = params.query;
35
+ if (params.title) {
36
+ apiParams.title = params.title;
37
+ if (!params.query)
38
+ apiParams.query = params.title;
39
+ }
40
+ if (params.type)
41
+ apiParams.type = params.type;
42
+ if (params.channelIds)
43
+ apiParams.channel_ids = JSON.stringify(params.channelIds);
44
+ if (params.conversationIds)
45
+ apiParams.conversation_ids = JSON.stringify(params.conversationIds);
46
+ if (params.authorIds)
47
+ apiParams.from_user_id = params.authorIds[0];
48
+ if (params.toUserIds)
49
+ apiParams.to_user_id = params.toUserIds[0];
50
+ if (params.mentionSelf)
51
+ apiParams.mention_self = params.mentionSelf;
52
+ if (params.dateFrom)
53
+ apiParams.after_ts = new Date(params.dateFrom).getTime() / 1000;
54
+ if (params.dateTo)
55
+ apiParams.before_ts = new Date(params.dateTo).getTime() / 1000;
56
+ if (params.limit)
57
+ apiParams.limit = params.limit;
58
+ if (params.cursor)
59
+ apiParams.cursor_mark = params.cursor;
60
+ const searchParams = new URLSearchParams();
61
+ for (const [key, value] of Object.entries(apiParams)) {
62
+ searchParams.append(key, String(value));
63
+ }
64
+ const url = `${BASE_URL}/search?${searchParams.toString()}`;
65
+ const response = await fetch(url, {
66
+ method: 'GET',
67
+ headers: {
68
+ Authorization: `Bearer ${token}`,
69
+ 'Content-Type': 'application/json',
70
+ },
71
+ });
72
+ if (!response.ok) {
73
+ const errorText = await response.text();
74
+ throw new Error(`Search API error (${response.status}): ${errorText}`);
75
+ }
76
+ const data = await response.json();
77
+ const items = (data.items || []).map((item) => transformSearchResult(item));
78
+ return {
79
+ items,
80
+ nextCursorMark: data.next_cursor_mark,
81
+ hasMore: data.has_more ?? false,
82
+ isPlanRestricted: data.is_plan_restricted ?? false,
83
+ };
84
+ }
85
+ //# sourceMappingURL=search-api.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"search-api.js","sourceRoot":"","sources":["../../src/lib/search-api.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,20 @@
1
+ interface SpinnerOptions {
2
+ text: string;
3
+ color?: 'green' | 'yellow' | 'blue' | 'red' | 'gray' | 'cyan' | 'magenta';
4
+ noSpinner?: boolean;
5
+ }
6
+ declare class LoadingSpinner {
7
+ private spinnerInstance;
8
+ start(options: SpinnerOptions): this;
9
+ succeed(text?: string): void;
10
+ fail(text?: string): void;
11
+ stop(): void;
12
+ private shouldDisableSpinner;
13
+ }
14
+ /**
15
+ * High-level wrapper function for running async operations with a loading spinner.
16
+ * Automatically handles success/failure states and cleanup.
17
+ */
18
+ export declare function withSpinner<T>(options: SpinnerOptions, asyncOperation: () => Promise<T>): Promise<T>;
19
+ export { LoadingSpinner, type SpinnerOptions };
20
+ //# sourceMappingURL=spinner.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"spinner.d.ts","sourceRoot":"","sources":["../../src/lib/spinner.ts"],"names":[],"mappings":"AAGA,UAAU,cAAc;IACpB,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,CAAC,EAAE,OAAO,GAAG,QAAQ,GAAG,MAAM,GAAG,KAAK,GAAG,MAAM,GAAG,MAAM,GAAG,SAAS,CAAA;IACzE,SAAS,CAAC,EAAE,OAAO,CAAA;CACtB;AAED,cAAM,cAAc;IAChB,OAAO,CAAC,eAAe,CAA+C;IAEtE,KAAK,CAAC,OAAO,EAAE,cAAc;IAe7B,OAAO,CAAC,IAAI,CAAC,EAAE,MAAM;IAOrB,IAAI,CAAC,IAAI,CAAC,EAAE,MAAM;IAOlB,IAAI;IAOJ,OAAO,CAAC,oBAAoB;CAmB/B;AAED;;;GAGG;AACH,wBAAsB,WAAW,CAAC,CAAC,EAC/B,OAAO,EAAE,cAAc,EACvB,cAAc,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GACjC,OAAO,CAAC,CAAC,CAAC,CAWZ;AAED,OAAO,EAAE,cAAc,EAAE,KAAK,cAAc,EAAE,CAAA"}
@@ -0,0 +1,70 @@
1
+ import chalk from 'chalk';
2
+ import yoctoSpinner from 'yocto-spinner';
3
+ class LoadingSpinner {
4
+ spinnerInstance = null;
5
+ start(options) {
6
+ // Don't show spinner in non-interactive environments, when disabled via options, or when JSON output is expected
7
+ if (!process.stdout.isTTY || options.noSpinner || this.shouldDisableSpinner()) {
8
+ return this;
9
+ }
10
+ const colorFn = chalk[options.color || 'blue'];
11
+ this.spinnerInstance = yoctoSpinner({
12
+ text: colorFn(options.text),
13
+ // yocto-spinner uses dots spinner by default which matches NPM's braille pattern
14
+ });
15
+ this.spinnerInstance.start();
16
+ return this;
17
+ }
18
+ succeed(text) {
19
+ if (this.spinnerInstance) {
20
+ this.spinnerInstance.success(text ? chalk.green(`✓ ${text}`) : undefined);
21
+ this.spinnerInstance = null;
22
+ }
23
+ }
24
+ fail(text) {
25
+ if (this.spinnerInstance) {
26
+ this.spinnerInstance.error(text ? chalk.red(`✗ ${text}`) : undefined);
27
+ this.spinnerInstance = null;
28
+ }
29
+ }
30
+ stop() {
31
+ if (this.spinnerInstance) {
32
+ this.spinnerInstance.stop();
33
+ this.spinnerInstance = null;
34
+ }
35
+ }
36
+ shouldDisableSpinner() {
37
+ // Check for environment variables that should disable spinners
38
+ if (process.env.TW_SPINNER === 'false') {
39
+ return true;
40
+ }
41
+ // Check if we're in CI environment
42
+ if (process.env.CI) {
43
+ return true;
44
+ }
45
+ // Check process arguments for JSON output flags and --no-spinner
46
+ const args = process.argv;
47
+ if (args.includes('--json') || args.includes('--ndjson') || args.includes('--no-spinner')) {
48
+ return true;
49
+ }
50
+ return false;
51
+ }
52
+ }
53
+ /**
54
+ * High-level wrapper function for running async operations with a loading spinner.
55
+ * Automatically handles success/failure states and cleanup.
56
+ */
57
+ export async function withSpinner(options, asyncOperation) {
58
+ const loadingSpinner = new LoadingSpinner().start(options);
59
+ try {
60
+ const result = await asyncOperation();
61
+ loadingSpinner.stop(); // Don't show success message by default - let the command handle its own output
62
+ return result;
63
+ }
64
+ catch (error) {
65
+ loadingSpinner.fail();
66
+ throw error;
67
+ }
68
+ }
69
+ export { LoadingSpinner };
70
+ //# sourceMappingURL=spinner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"spinner.js","sourceRoot":"","sources":["../../src/lib/spinner.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AACzB,OAAO,YAAY,MAAM,eAAe,CAAA;AAQxC,MAAM,cAAc;IACR,eAAe,GAA2C,IAAI,CAAA;IAEtE,KAAK,CAAC,OAAuB;QACzB,iHAAiH;QACjH,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,IAAI,OAAO,CAAC,SAAS,IAAI,IAAI,CAAC,oBAAoB,EAAE,EAAE,CAAC;YAC5E,OAAO,IAAI,CAAA;QACf,CAAC;QAED,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC,KAAK,IAAI,MAAM,CAAC,CAAA;QAC9C,IAAI,CAAC,eAAe,GAAG,YAAY,CAAC;YAChC,IAAI,EAAE,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC;YAC3B,iFAAiF;SACpF,CAAC,CAAA;QACF,IAAI,CAAC,eAAe,CAAC,KAAK,EAAE,CAAA;QAC5B,OAAO,IAAI,CAAA;IACf,CAAC;IAED,OAAO,CAAC,IAAa;QACjB,IAAI,IAAI,CAAC,eAAe,EAAE,CAAC;YACvB,IAAI,CAAC,eAAe,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAA;YACzE,IAAI,CAAC,eAAe,GAAG,IAAI,CAAA;QAC/B,CAAC;IACL,CAAC;IAED,IAAI,CAAC,IAAa;QACd,IAAI,IAAI,CAAC,eAAe,EAAE,CAAC;YACvB,IAAI,CAAC,eAAe,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAA;YACrE,IAAI,CAAC,eAAe,GAAG,IAAI,CAAA;QAC/B,CAAC;IACL,CAAC;IAED,IAAI;QACA,IAAI,IAAI,CAAC,eAAe,EAAE,CAAC;YACvB,IAAI,CAAC,eAAe,CAAC,IAAI,EAAE,CAAA;YAC3B,IAAI,CAAC,eAAe,GAAG,IAAI,CAAA;QAC/B,CAAC;IACL,CAAC;IAEO,oBAAoB;QACxB,+DAA+D;QAC/D,IAAI,OAAO,CAAC,GAAG,CAAC,UAAU,KAAK,OAAO,EAAE,CAAC;YACrC,OAAO,IAAI,CAAA;QACf,CAAC;QAED,mCAAmC;QACnC,IAAI,OAAO,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;YACjB,OAAO,IAAI,CAAA;QACf,CAAC;QAED,iEAAiE;QACjE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAA;QACzB,IAAI,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,cAAc,CAAC,EAAE,CAAC;YACxF,OAAO,IAAI,CAAA;QACf,CAAC;QAED,OAAO,KAAK,CAAA;IAChB,CAAC;CACJ;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW,CAC7B,OAAuB,EACvB,cAAgC;IAEhC,MAAM,cAAc,GAAG,IAAI,cAAc,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,CAAA;IAE1D,IAAI,CAAC;QACD,MAAM,MAAM,GAAG,MAAM,cAAc,EAAE,CAAA;QACrC,cAAc,CAAC,IAAI,EAAE,CAAA,CAAC,gFAAgF;QACtG,OAAO,MAAM,CAAA;IACjB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACb,cAAc,CAAC,IAAI,EAAE,CAAA;QACrB,MAAM,KAAK,CAAA;IACf,CAAC;AACL,CAAC;AAED,OAAO,EAAE,cAAc,EAAuB,CAAA"}