@doist/twist-sdk 2.7.0 → 2.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/clients/add-comment-helper.js +1 -2
- package/dist/cjs/clients/attachments-client.js +124 -0
- package/dist/cjs/clients/base-client.js +10 -0
- package/dist/cjs/clients/channels-client.js +9 -6
- package/dist/cjs/clients/comments-client.js +16 -6
- package/dist/cjs/clients/conversation-messages-client.js +9 -8
- package/dist/cjs/clients/conversations-client.js +11 -8
- package/dist/cjs/clients/inbox-client.js +6 -3
- package/dist/cjs/clients/threads-client.js +18 -9
- package/dist/cjs/clients/workspace-users-client.js +9 -2
- package/dist/cjs/clients/workspaces-client.js +7 -3
- package/dist/cjs/consts/endpoints.js +2 -1
- package/dist/cjs/index.js +3 -1
- package/dist/cjs/twist-api.js +2 -0
- package/dist/cjs/types/entities.js +99 -79
- package/dist/cjs/utils/multipart-upload.js +154 -0
- package/dist/esm/clients/add-comment-helper.js +1 -2
- package/dist/esm/clients/attachments-client.js +121 -0
- package/dist/esm/clients/base-client.js +10 -0
- package/dist/esm/clients/channels-client.js +10 -7
- package/dist/esm/clients/comments-client.js +17 -7
- package/dist/esm/clients/conversation-messages-client.js +10 -9
- package/dist/esm/clients/conversations-client.js +12 -9
- package/dist/esm/clients/inbox-client.js +7 -4
- package/dist/esm/clients/threads-client.js +19 -10
- package/dist/esm/clients/workspace-users-client.js +9 -2
- package/dist/esm/clients/workspaces-client.js +8 -4
- package/dist/esm/consts/endpoints.js +1 -0
- package/dist/esm/index.js +1 -0
- package/dist/esm/twist-api.js +2 -0
- package/dist/esm/types/entities.js +92 -78
- package/dist/esm/utils/multipart-upload.js +150 -0
- package/dist/types/clients/add-comment-helper.d.ts +3 -1
- package/dist/types/clients/attachments-client.d.ts +39 -0
- package/dist/types/clients/base-client.d.ts +4 -0
- package/dist/types/clients/channels-client.d.ts +1 -0
- package/dist/types/clients/comments-client.d.ts +1 -0
- package/dist/types/clients/conversation-messages-client.d.ts +1 -0
- package/dist/types/clients/conversations-client.d.ts +1 -0
- package/dist/types/clients/inbox-client.d.ts +1 -0
- package/dist/types/clients/threads-client.d.ts +2 -0
- package/dist/types/clients/workspace-users-client.d.ts +5 -0
- package/dist/types/clients/workspaces-client.d.ts +1 -0
- package/dist/types/consts/endpoints.d.ts +1 -0
- package/dist/types/index.d.ts +1 -0
- package/dist/types/twist-api.d.ts +2 -0
- package/dist/types/types/entities.d.ts +1539 -185
- package/dist/types/types/requests.d.ts +22 -0
- package/dist/types/utils/multipart-upload.d.ts +53 -0
- package/package.json +6 -2
|
@@ -109,8 +109,7 @@ export var WorkspaceSchema = z.object({
|
|
|
109
109
|
plan: z.enum(WORKSPACE_PLANS).nullable().optional(),
|
|
110
110
|
});
|
|
111
111
|
// Channel entity from API
|
|
112
|
-
export var
|
|
113
|
-
.object({
|
|
112
|
+
export var ChannelObjectSchema = z.object({
|
|
114
113
|
id: z.number(),
|
|
115
114
|
name: z.string(),
|
|
116
115
|
description: z.string().nullable().optional(),
|
|
@@ -128,11 +127,13 @@ export var ChannelSchema = z
|
|
|
128
127
|
icon: z.number().nullable().optional(),
|
|
129
128
|
version: z.number(),
|
|
130
129
|
filters: z.record(z.string(), z.string()).nullable().optional(),
|
|
131
|
-
})
|
|
132
|
-
|
|
130
|
+
});
|
|
131
|
+
export function createChannelSchema(linkBaseUrl) {
|
|
132
|
+
return ChannelObjectSchema.transform(function (data) { return (__assign(__assign({}, data), { url: getFullTwistURL({ workspaceId: data.workspaceId, channelId: data.id }, linkBaseUrl) })); });
|
|
133
|
+
}
|
|
134
|
+
export var ChannelSchema = createChannelSchema();
|
|
133
135
|
// Thread entity from API
|
|
134
|
-
export var
|
|
135
|
-
.object({
|
|
136
|
+
export var ThreadObjectSchema = z.object({
|
|
136
137
|
id: z.number(),
|
|
137
138
|
title: z.string(),
|
|
138
139
|
content: z.string(),
|
|
@@ -195,12 +196,15 @@ export var ThreadSchema = z
|
|
|
195
196
|
})
|
|
196
197
|
.nullable()
|
|
197
198
|
.optional(),
|
|
198
|
-
})
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
199
|
+
});
|
|
200
|
+
export function createThreadSchema(linkBaseUrl) {
|
|
201
|
+
return ThreadObjectSchema.transform(function (data) { return (__assign(__assign({}, data), { url: getFullTwistURL({
|
|
202
|
+
workspaceId: data.workspaceId,
|
|
203
|
+
channelId: data.channelId,
|
|
204
|
+
threadId: data.id,
|
|
205
|
+
}, linkBaseUrl) })); });
|
|
206
|
+
}
|
|
207
|
+
export var ThreadSchema = createThreadSchema();
|
|
204
208
|
// Group entity from API
|
|
205
209
|
export var GroupSchema = z.object({
|
|
206
210
|
id: z.number(),
|
|
@@ -211,8 +215,7 @@ export var GroupSchema = z.object({
|
|
|
211
215
|
version: z.number(),
|
|
212
216
|
});
|
|
213
217
|
// Conversation entity from API
|
|
214
|
-
export var
|
|
215
|
-
.object({
|
|
218
|
+
export var ConversationObjectSchema = z.object({
|
|
216
219
|
id: z.number(),
|
|
217
220
|
workspaceId: z.number(),
|
|
218
221
|
userIds: z.array(z.number()),
|
|
@@ -248,11 +251,13 @@ export var ConversationSchema = z
|
|
|
248
251
|
})
|
|
249
252
|
.nullable()
|
|
250
253
|
.optional(),
|
|
251
|
-
})
|
|
252
|
-
|
|
254
|
+
});
|
|
255
|
+
export function createConversationSchema(linkBaseUrl) {
|
|
256
|
+
return ConversationObjectSchema.transform(function (data) { return (__assign(__assign({}, data), { url: getFullTwistURL({ workspaceId: data.workspaceId, conversationId: data.id }, linkBaseUrl) })); });
|
|
257
|
+
}
|
|
258
|
+
export var ConversationSchema = createConversationSchema();
|
|
253
259
|
// Comment entity from API
|
|
254
|
-
export var
|
|
255
|
-
.object({
|
|
260
|
+
export var CommentObjectSchema = z.object({
|
|
256
261
|
id: z.number(),
|
|
257
262
|
content: z.string(),
|
|
258
263
|
creator: z.number(),
|
|
@@ -277,13 +282,16 @@ export var CommentSchema = z
|
|
|
277
282
|
deletedBy: z.number().nullable().optional(),
|
|
278
283
|
version: z.number().nullable().optional(),
|
|
279
284
|
actions: z.array(z.unknown()).nullable().optional(),
|
|
280
|
-
})
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
285
|
+
});
|
|
286
|
+
export function createCommentSchema(linkBaseUrl) {
|
|
287
|
+
return CommentObjectSchema.transform(function (data) { return (__assign(__assign({}, data), { url: getFullTwistURL({
|
|
288
|
+
workspaceId: data.workspaceId,
|
|
289
|
+
channelId: data.channelId,
|
|
290
|
+
threadId: data.threadId,
|
|
291
|
+
commentId: data.id,
|
|
292
|
+
}, linkBaseUrl) })); });
|
|
293
|
+
}
|
|
294
|
+
export var CommentSchema = createCommentSchema();
|
|
287
295
|
// WorkspaceUser entity from v4 API
|
|
288
296
|
export var WorkspaceUserSchema = BaseUserSchema.extend({
|
|
289
297
|
email: z.string().nullable().optional(),
|
|
@@ -295,8 +303,7 @@ export var WorkspaceUserSchema = BaseUserSchema.extend({
|
|
|
295
303
|
version: z.number(),
|
|
296
304
|
});
|
|
297
305
|
// ConversationMessage entity from API
|
|
298
|
-
export var
|
|
299
|
-
.object({
|
|
306
|
+
export var ConversationMessageObjectSchema = z.object({
|
|
300
307
|
id: z.number(),
|
|
301
308
|
content: z.string(),
|
|
302
309
|
creator: z.number(),
|
|
@@ -313,58 +320,65 @@ export var ConversationMessageSchema = z
|
|
|
313
320
|
directMentions: z.array(z.number()).nullable().optional(),
|
|
314
321
|
version: z.number().nullable().optional(),
|
|
315
322
|
workspaceId: z.number(),
|
|
316
|
-
})
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
323
|
+
});
|
|
324
|
+
export function createConversationMessageSchema(linkBaseUrl) {
|
|
325
|
+
return ConversationMessageObjectSchema.transform(function (data) { return (__assign(__assign({}, data), { url: getFullTwistURL({
|
|
326
|
+
workspaceId: data.workspaceId,
|
|
327
|
+
conversationId: data.conversationId,
|
|
328
|
+
messageId: data.id,
|
|
329
|
+
}, linkBaseUrl) })); });
|
|
330
|
+
}
|
|
331
|
+
export var ConversationMessageSchema = createConversationMessageSchema();
|
|
322
332
|
// InboxThread entity from API - returns full Thread objects with additional inbox metadata
|
|
323
|
-
|
|
324
|
-
.object({
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
})
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
333
|
+
function createInboxThreadObjectSchema(linkBaseUrl) {
|
|
334
|
+
return z.object({
|
|
335
|
+
id: z.number(),
|
|
336
|
+
title: z.string(),
|
|
337
|
+
content: z.string(),
|
|
338
|
+
creator: z.number(),
|
|
339
|
+
creatorName: z.string().nullable().optional(),
|
|
340
|
+
channelId: z.number(),
|
|
341
|
+
workspaceId: z.number(),
|
|
342
|
+
actions: z.array(z.unknown()).nullable().optional(),
|
|
343
|
+
attachments: z.array(AttachmentSchema).nullable().optional(),
|
|
344
|
+
commentCount: z.number(),
|
|
345
|
+
directGroupMentions: z.array(z.number()).nullable().optional(),
|
|
346
|
+
directMentions: z.array(z.number()).nullable().optional(),
|
|
347
|
+
groups: z.array(z.number()).nullable().optional(),
|
|
348
|
+
lastEdited: z.date().nullable().optional(),
|
|
349
|
+
lastObjIndex: z.number().nullable().optional(),
|
|
350
|
+
lastUpdated: z.date(),
|
|
351
|
+
mutedUntil: z.date().nullable().optional(),
|
|
352
|
+
participants: z.array(z.number()).nullable().optional(),
|
|
353
|
+
pinned: z.boolean(),
|
|
354
|
+
pinnedDate: z.date().nullable().optional(),
|
|
355
|
+
posted: z.date(),
|
|
356
|
+
reactions: z.record(z.string(), z.array(z.number())).nullable().optional(),
|
|
357
|
+
recipients: z.array(z.number()).nullable().optional(),
|
|
358
|
+
snippet: z.string(),
|
|
359
|
+
snippetCreator: z.number(),
|
|
360
|
+
snippetMaskAvatarUrl: z.string().nullable().optional(),
|
|
361
|
+
snippetMaskPoster: z.string().nullable().optional(),
|
|
362
|
+
starred: z.boolean(),
|
|
363
|
+
systemMessage: SystemMessageSchema,
|
|
364
|
+
isArchived: z.boolean(),
|
|
365
|
+
inInbox: z.boolean(),
|
|
366
|
+
isSaved: z.boolean().nullable().optional(),
|
|
367
|
+
closed: z.boolean(),
|
|
368
|
+
responders: z.array(z.number()).nullable().optional(),
|
|
369
|
+
lastComment: createCommentSchema(linkBaseUrl).nullable().optional(),
|
|
370
|
+
toEmails: z.array(z.string()).nullable().optional(),
|
|
371
|
+
version: z.number().nullable().optional(),
|
|
372
|
+
});
|
|
373
|
+
}
|
|
374
|
+
export function createInboxThreadSchema(linkBaseUrl) {
|
|
375
|
+
return createInboxThreadObjectSchema(linkBaseUrl).transform(function (data) { return (__assign(__assign({}, data), { url: getFullTwistURL({
|
|
376
|
+
workspaceId: data.workspaceId,
|
|
377
|
+
channelId: data.channelId,
|
|
378
|
+
threadId: data.id,
|
|
379
|
+
}, linkBaseUrl) })); });
|
|
380
|
+
}
|
|
381
|
+
export var InboxThreadSchema = createInboxThreadSchema();
|
|
368
382
|
// UnreadThread entity from API - simplified thread reference for unread threads
|
|
369
383
|
export var UnreadThreadSchema = z.object({
|
|
370
384
|
threadId: z.number(),
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
var __assign = (this && this.__assign) || function () {
|
|
2
|
+
__assign = Object.assign || function(t) {
|
|
3
|
+
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
|
4
|
+
s = arguments[i];
|
|
5
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
|
|
6
|
+
t[p] = s[p];
|
|
7
|
+
}
|
|
8
|
+
return t;
|
|
9
|
+
};
|
|
10
|
+
return __assign.apply(this, arguments);
|
|
11
|
+
};
|
|
12
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
13
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
14
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
15
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
16
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
17
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
18
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
19
|
+
});
|
|
20
|
+
};
|
|
21
|
+
var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
22
|
+
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
|
|
23
|
+
return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
|
24
|
+
function verb(n) { return function (v) { return step([n, v]); }; }
|
|
25
|
+
function step(op) {
|
|
26
|
+
if (f) throw new TypeError("Generator is already executing.");
|
|
27
|
+
while (g && (g = 0, op[0] && (_ = 0)), _) try {
|
|
28
|
+
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
|
29
|
+
if (y = 0, t) op = [op[0] & 2, t.value];
|
|
30
|
+
switch (op[0]) {
|
|
31
|
+
case 0: case 1: t = op; break;
|
|
32
|
+
case 4: _.label++; return { value: op[1], done: false };
|
|
33
|
+
case 5: _.label++; y = op[1]; op = [0]; continue;
|
|
34
|
+
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
|
35
|
+
default:
|
|
36
|
+
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
|
37
|
+
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
|
38
|
+
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
|
39
|
+
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
|
40
|
+
if (t[2]) _.ops.pop();
|
|
41
|
+
_.trys.pop(); continue;
|
|
42
|
+
}
|
|
43
|
+
op = body.call(thisArg, _);
|
|
44
|
+
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
|
45
|
+
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
import { fetchWithRetry } from '../transport/fetch-with-retry.js';
|
|
49
|
+
/**
|
|
50
|
+
* Determine a content-type from a filename extension. Falls back to
|
|
51
|
+
* `application/octet-stream` for unknown extensions.
|
|
52
|
+
*/
|
|
53
|
+
export function getContentTypeFromFileName(fileName) {
|
|
54
|
+
var extension = fileName.toLowerCase().split('.').pop();
|
|
55
|
+
switch (extension) {
|
|
56
|
+
case 'png':
|
|
57
|
+
return 'image/png';
|
|
58
|
+
case 'jpg':
|
|
59
|
+
case 'jpeg':
|
|
60
|
+
return 'image/jpeg';
|
|
61
|
+
case 'gif':
|
|
62
|
+
return 'image/gif';
|
|
63
|
+
case 'webp':
|
|
64
|
+
return 'image/webp';
|
|
65
|
+
case 'svg':
|
|
66
|
+
return 'image/svg+xml';
|
|
67
|
+
case 'pdf':
|
|
68
|
+
return 'application/pdf';
|
|
69
|
+
default:
|
|
70
|
+
return 'application/octet-stream';
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Normalise a supported {@link UploadFile} into a `Blob` plus a resolved file name and
|
|
75
|
+
* content type, so uploads use the cross-platform global `FormData`/`Blob` body that
|
|
76
|
+
* `undici` and browsers both accept natively.
|
|
77
|
+
*/
|
|
78
|
+
function toBlob(file, fileName, contentType) {
|
|
79
|
+
if (file instanceof Blob) {
|
|
80
|
+
// `File` is not a global in Node 18, so guard the check before using it.
|
|
81
|
+
var name_1 = fileName ||
|
|
82
|
+
(typeof File !== 'undefined' && file instanceof File ? file.name : undefined) ||
|
|
83
|
+
'upload';
|
|
84
|
+
var type = contentType || file.type || getContentTypeFromFileName(name_1);
|
|
85
|
+
// Re-wrap only when stamping a type the Blob doesn't already carry.
|
|
86
|
+
var blob = file.type === type ? file : new Blob([file], { type: type });
|
|
87
|
+
return { blob: blob, fileName: name_1, contentType: type };
|
|
88
|
+
}
|
|
89
|
+
if (file instanceof Uint8Array) {
|
|
90
|
+
if (!fileName) {
|
|
91
|
+
throw new Error('fileName is required when uploading raw bytes');
|
|
92
|
+
}
|
|
93
|
+
var type = contentType || getContentTypeFromFileName(fileName);
|
|
94
|
+
// `Blob` accepts any `ArrayBufferView`; the cast satisfies the stricter lib
|
|
95
|
+
// `BlobPart` type (which pins the backing buffer to `ArrayBuffer`).
|
|
96
|
+
return { blob: new Blob([file], { type: type }), fileName: fileName, contentType: type };
|
|
97
|
+
}
|
|
98
|
+
throw new Error('Unsupported file type for upload: expected a Blob or Uint8Array');
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Upload a file using `multipart/form-data`.
|
|
102
|
+
*
|
|
103
|
+
* Builds the request body with the global `FormData`/`Blob` so it works unchanged in the
|
|
104
|
+
* browser and in Node.js (via `undici`). The `file` part is sent alongside `file_name`,
|
|
105
|
+
* `file_size`, and `underlying_type` fields (the canonical Twist upload shape); any
|
|
106
|
+
* `additionalFields` are merged in and override the derived values. Authentication uses
|
|
107
|
+
* `Authorization: Bearer`, matching every other Twist SDK client, and `Content-Type` is
|
|
108
|
+
* intentionally left unset so the runtime adds the correct multipart boundary.
|
|
109
|
+
*
|
|
110
|
+
* The response is JSON-parsed and camel-cased by {@link fetchWithRetry}; callers validate
|
|
111
|
+
* the returned shape with the appropriate schema.
|
|
112
|
+
*/
|
|
113
|
+
export function uploadMultipartFile(args) {
|
|
114
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
115
|
+
var baseUrl, authToken, endpoint, file, fileName, contentType, additionalFields, requestId, customFetch, _a, blob, resolvedFileName, resolvedType, fields, form, _i, _b, _c, key, value, headers, url, response;
|
|
116
|
+
return __generator(this, function (_d) {
|
|
117
|
+
switch (_d.label) {
|
|
118
|
+
case 0:
|
|
119
|
+
baseUrl = args.baseUrl, authToken = args.authToken, endpoint = args.endpoint, file = args.file, fileName = args.fileName, contentType = args.contentType, additionalFields = args.additionalFields, requestId = args.requestId, customFetch = args.customFetch;
|
|
120
|
+
_a = toBlob(file, fileName, contentType), blob = _a.blob, resolvedFileName = _a.fileName, resolvedType = _a.contentType;
|
|
121
|
+
fields = __assign({ file_name: resolvedFileName, file_size: blob.size, underlying_type: resolvedType }, additionalFields);
|
|
122
|
+
form = new FormData();
|
|
123
|
+
form.append('file', blob, resolvedFileName);
|
|
124
|
+
for (_i = 0, _b = Object.entries(fields); _i < _b.length; _i++) {
|
|
125
|
+
_c = _b[_i], key = _c[0], value = _c[1];
|
|
126
|
+
if (value !== undefined && value !== null) {
|
|
127
|
+
form.append(key, String(value));
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
headers = {
|
|
131
|
+
Authorization: "Bearer ".concat(authToken),
|
|
132
|
+
};
|
|
133
|
+
if (requestId) {
|
|
134
|
+
headers['X-Request-Id'] = requestId;
|
|
135
|
+
}
|
|
136
|
+
url = new URL(endpoint, baseUrl).toString();
|
|
137
|
+
return [4 /*yield*/, fetchWithRetry(url, {
|
|
138
|
+
method: 'POST',
|
|
139
|
+
headers: headers,
|
|
140
|
+
body: form,
|
|
141
|
+
// Don't set Content-Type — the runtime adds the multipart boundary.
|
|
142
|
+
timeout: 30000,
|
|
143
|
+
}, 3, customFetch)];
|
|
144
|
+
case 1:
|
|
145
|
+
response = _d.sent();
|
|
146
|
+
return [2 /*return*/, response.data];
|
|
147
|
+
}
|
|
148
|
+
});
|
|
149
|
+
});
|
|
150
|
+
}
|
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
import type { BatchRequestDescriptor } from '../types/batch.js';
|
|
2
|
-
import { type Comment } from '../types/entities.js';
|
|
2
|
+
import { type Comment, type createCommentSchema } from '../types/entities.js';
|
|
3
3
|
import type { CustomFetch } from '../types/http.js';
|
|
4
4
|
import type { CreateCommentArgs, ThreadAction } from '../types/requests.js';
|
|
5
5
|
type ClientContext = {
|
|
6
6
|
baseUri: string;
|
|
7
7
|
apiToken: string;
|
|
8
8
|
customFetch?: CustomFetch;
|
|
9
|
+
/** Per-client Comment schema, base-bound for the returned comment's web `url`. */
|
|
10
|
+
schema: ReturnType<typeof createCommentSchema>;
|
|
9
11
|
};
|
|
10
12
|
export declare function addCommentRequest(context: ClientContext, params: CreateCommentArgs, options?: {
|
|
11
13
|
batch?: boolean;
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { type Attachment } from '../types/entities.js';
|
|
2
|
+
import type { UploadAttachmentArgs } from '../types/requests.js';
|
|
3
|
+
import { BaseClient } from './base-client.js';
|
|
4
|
+
/**
|
|
5
|
+
* Client for uploading file attachments to Twist.
|
|
6
|
+
*
|
|
7
|
+
* Attachments are uploaded independently, then referenced by passing the returned
|
|
8
|
+
* {@link Attachment} into the `attachments` array of `comments.createComment`,
|
|
9
|
+
* `conversationMessages.createMessage`, and similar calls.
|
|
10
|
+
*/
|
|
11
|
+
export declare class AttachmentsClient extends BaseClient {
|
|
12
|
+
/**
|
|
13
|
+
* Uploads a file and returns the created {@link Attachment}.
|
|
14
|
+
*
|
|
15
|
+
* Mirrors the canonical multipart upload used by twist-web: `POST /attachments/upload`
|
|
16
|
+
* with the `file` binary plus `file_name`, `file_size`, `attachment_id`, and
|
|
17
|
+
* `underlying_type` form fields.
|
|
18
|
+
*
|
|
19
|
+
* @param args - The file to upload and optional metadata.
|
|
20
|
+
* @returns The created attachment, ready to attach to a comment or message.
|
|
21
|
+
*
|
|
22
|
+
* @example
|
|
23
|
+
* ```typescript
|
|
24
|
+
* import { readFile } from 'node:fs/promises'
|
|
25
|
+
*
|
|
26
|
+
* const attachment = await api.attachments.upload({
|
|
27
|
+
* file: await readFile('./diagram.png'),
|
|
28
|
+
* fileName: 'diagram.png',
|
|
29
|
+
* })
|
|
30
|
+
*
|
|
31
|
+
* await api.comments.createComment({
|
|
32
|
+
* threadId: 789,
|
|
33
|
+
* content: 'See attached',
|
|
34
|
+
* attachments: [attachment],
|
|
35
|
+
* })
|
|
36
|
+
* ```
|
|
37
|
+
*/
|
|
38
|
+
upload(args: UploadAttachmentArgs): Promise<Attachment>;
|
|
39
|
+
}
|
|
@@ -28,4 +28,8 @@ export declare class BaseClient {
|
|
|
28
28
|
* @returns Base URI with guaranteed trailing slash for proper URL resolution
|
|
29
29
|
*/
|
|
30
30
|
protected getBaseUri(version?: ApiVersion): string;
|
|
31
|
+
/**
|
|
32
|
+
* Base URL for entity web links, or `undefined` to use getFullTwistURL's default web app.
|
|
33
|
+
*/
|
|
34
|
+
protected getLinkBaseUrl(): string | undefined;
|
|
31
35
|
}
|
|
@@ -6,6 +6,7 @@ import { BaseClient } from './base-client.js';
|
|
|
6
6
|
* Client for interacting with Twist conversation message endpoints.
|
|
7
7
|
*/
|
|
8
8
|
export declare class ConversationMessagesClient extends BaseClient {
|
|
9
|
+
private readonly messageSchema;
|
|
9
10
|
/**
|
|
10
11
|
* Gets all messages in a conversation.
|
|
11
12
|
*
|
|
@@ -6,6 +6,7 @@ import { BaseClient } from './base-client.js';
|
|
|
6
6
|
* Client for interacting with Twist conversation endpoints.
|
|
7
7
|
*/
|
|
8
8
|
export declare class ConversationsClient extends BaseClient {
|
|
9
|
+
private readonly conversationSchema;
|
|
9
10
|
/**
|
|
10
11
|
* Gets all conversations for a workspace.
|
|
11
12
|
*
|
|
@@ -6,6 +6,8 @@ import { BaseClient } from './base-client.js';
|
|
|
6
6
|
* Client for interacting with Twist thread endpoints.
|
|
7
7
|
*/
|
|
8
8
|
export declare class ThreadsClient extends BaseClient {
|
|
9
|
+
private readonly threadSchema;
|
|
10
|
+
private readonly commentSchema;
|
|
9
11
|
/**
|
|
10
12
|
* Gets all threads in a channel.
|
|
11
13
|
*
|
|
@@ -10,9 +10,14 @@ export declare class WorkspaceUsersClient extends BaseClient {
|
|
|
10
10
|
/**
|
|
11
11
|
* Returns a list of workspace user objects for the given workspace id.
|
|
12
12
|
*
|
|
13
|
+
* Removed users are excluded by default; set `args.includeRemoved` to `true` to include them.
|
|
14
|
+
* The Twist API always returns removed users, so the filtering happens client-side (in both the
|
|
15
|
+
* awaited and batch modes).
|
|
16
|
+
*
|
|
13
17
|
* @param args - The arguments for getting workspace users.
|
|
14
18
|
* @param args.workspaceId - The workspace ID.
|
|
15
19
|
* @param args.archived - Optional flag to filter archived users.
|
|
20
|
+
* @param args.includeRemoved - Include users removed from the workspace. Defaults to `false`.
|
|
16
21
|
* @param options - Optional configuration. Set `batch: true` to return a descriptor for batch requests.
|
|
17
22
|
* @returns An array of workspace user objects.
|
|
18
23
|
*
|
|
@@ -24,3 +24,4 @@ export declare const ENDPOINT_INBOX = "inbox";
|
|
|
24
24
|
export declare const ENDPOINT_REACTIONS = "reactions";
|
|
25
25
|
export declare const ENDPOINT_SEARCH = "search";
|
|
26
26
|
export declare const ENDPOINT_CONVERSATION_MESSAGES = "conversation_messages";
|
|
27
|
+
export declare const ENDPOINT_ATTACHMENTS = "attachments";
|
package/dist/types/index.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
export * from './authentication.js';
|
|
2
2
|
export { BatchBuilder } from './batch-builder.js';
|
|
3
|
+
export { AttachmentsClient } from './clients/attachments-client.js';
|
|
3
4
|
export { ConversationMessagesClient } from './clients/conversation-messages-client.js';
|
|
4
5
|
export { InboxClient } from './clients/inbox-client.js';
|
|
5
6
|
export { ReactionsClient } from './clients/reactions-client.js';
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { AttachmentsClient } from './clients/attachments-client.js';
|
|
1
2
|
import { ChannelsClient } from './clients/channels-client.js';
|
|
2
3
|
import { CommentsClient } from './clients/comments-client.js';
|
|
3
4
|
import { ConversationMessagesClient } from './clients/conversation-messages-client.js';
|
|
@@ -42,6 +43,7 @@ export declare class TwistApi {
|
|
|
42
43
|
inbox: InboxClient;
|
|
43
44
|
reactions: ReactionsClient;
|
|
44
45
|
search: SearchClient;
|
|
46
|
+
attachments: AttachmentsClient;
|
|
45
47
|
private authToken;
|
|
46
48
|
private baseUrl?;
|
|
47
49
|
private customFetch?;
|