@doist/comms-sdk 2.0.1 → 3.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.
- package/dist/esm/utils/multipart-upload.js +73 -15
- package/dist/esm/utils/url-helpers.js +104 -16
- package/dist/types/utils/multipart-upload.d.ts +3 -4
- package/dist/types/utils/url-helpers.d.ts +41 -0
- package/package.json +5 -10
- package/dist/cjs/authentication.js +0 -256
- package/dist/cjs/clients/add-comment-helper.js +0 -43
- package/dist/cjs/clients/attachments-client.js +0 -71
- package/dist/cjs/clients/base-client.js +0 -33
- package/dist/cjs/clients/channels-client.js +0 -211
- package/dist/cjs/clients/comments-client.js +0 -175
- package/dist/cjs/clients/conversation-messages-client.js +0 -169
- package/dist/cjs/clients/conversations-client.js +0 -283
- package/dist/cjs/clients/groups-client.js +0 -172
- package/dist/cjs/clients/hooks-client.js +0 -52
- package/dist/cjs/clients/inbox-client.js +0 -184
- package/dist/cjs/clients/notify-audience.js +0 -45
- package/dist/cjs/clients/reactions-client.js +0 -97
- package/dist/cjs/clients/search-client.js +0 -138
- package/dist/cjs/clients/threads-client.js +0 -364
- package/dist/cjs/clients/users-client.js +0 -326
- package/dist/cjs/clients/workspace-users-client.js +0 -252
- package/dist/cjs/clients/workspaces-client.js +0 -174
- package/dist/cjs/comms-api.js +0 -70
- package/dist/cjs/consts/endpoints.js +0 -34
- package/dist/cjs/index.js +0 -53
- package/dist/cjs/migration.js +0 -96
- package/dist/cjs/package.json +0 -1
- package/dist/cjs/testUtils/msw-handlers.js +0 -51
- package/dist/cjs/testUtils/msw-setup.js +0 -35
- package/dist/cjs/testUtils/obsidian-fetch-adapter.js +0 -53
- package/dist/cjs/testUtils/test-defaults.js +0 -106
- package/dist/cjs/transport/fetch-with-retry.js +0 -146
- package/dist/cjs/transport/http-client.js +0 -56
- package/dist/cjs/transport/http-dispatcher.js +0 -190
- package/dist/cjs/types/api-version.js +0 -8
- package/dist/cjs/types/entities.js +0 -496
- package/dist/cjs/types/enums.js +0 -37
- package/dist/cjs/types/errors.js +0 -12
- package/dist/cjs/types/http.js +0 -4
- package/dist/cjs/types/index.js +0 -22
- package/dist/cjs/types/requests.js +0 -183
- package/dist/cjs/utils/case-conversion.js +0 -54
- package/dist/cjs/utils/index.js +0 -19
- package/dist/cjs/utils/multipart-upload.js +0 -144
- package/dist/cjs/utils/timestamp-conversion.js +0 -58
- package/dist/cjs/utils/url-helpers.js +0 -133
- package/dist/cjs/utils/uuidv7.js +0 -182
|
@@ -1,183 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.THREAD_ACTIONS = exports.UnsubscribeHookArgsSchema = exports.SubscribeHookArgsSchema = exports.SubscribeMessageHookArgsSchema = exports.SubscribeNonMessageHookArgsSchema = exports.SubscribeHookArgsBaseSchema = exports.HookTargetUrlSchema = exports.HookEventSchema = exports.MessageHookEventSchema = exports.NonMessageHookEventSchema = exports.HOOK_EVENTS = exports.MESSAGE_HOOK_EVENTS = exports.NON_MESSAGE_HOOK_EVENTS = exports.ARCHIVE_FILTER_VALUES = exports.GetOrCreateConversationArgsSchema = exports.GetConversationsArgsSchema = exports.GetCommentsArgsSchema = exports.GetThreadsArgsSchema = exports.GetChannelsArgsSchema = exports.CreateMessageArgsSchema = exports.CreateConversationArgsSchema = exports.UpdateCommentArgsSchema = exports.CreateCommentArgsSchema = exports.UpdateThreadArgsSchema = exports.CreateThreadArgsSchema = exports.UpdateChannelArgsSchema = exports.CreateChannelArgsSchema = void 0;
|
|
4
|
-
const zod_1 = require("zod");
|
|
5
|
-
const entities_1 = require("./entities");
|
|
6
|
-
const enums_1 = require("./enums");
|
|
7
|
-
/**
|
|
8
|
-
* Create-side requests require an `id` on the wire. The SDK clients accept
|
|
9
|
-
* `id` as optional and auto-generate one via
|
|
10
|
-
* {@link import('../utils/uuidv7').generateId} when the caller doesn't pass
|
|
11
|
-
* one — callers can still mint their own ID locally (e.g. for optimistic
|
|
12
|
-
* UI) and have it stick.
|
|
13
|
-
*/
|
|
14
|
-
exports.CreateChannelArgsSchema = zod_1.z.object({
|
|
15
|
-
workspaceId: zod_1.z.number(),
|
|
16
|
-
name: zod_1.z.string(),
|
|
17
|
-
id: zod_1.z.string().optional(),
|
|
18
|
-
userIds: zod_1.z.array(zod_1.z.number()).nullable().optional(),
|
|
19
|
-
color: zod_1.z.number().nullable().optional(),
|
|
20
|
-
public: zod_1.z.boolean().nullable().optional(),
|
|
21
|
-
description: zod_1.z.string().nullable().optional(),
|
|
22
|
-
defaultGroups: zod_1.z.array(zod_1.z.string()).nullable().optional(),
|
|
23
|
-
defaultRecipients: zod_1.z.array(zod_1.z.number()).nullable().optional(),
|
|
24
|
-
isFavorited: zod_1.z.boolean().nullable().optional(),
|
|
25
|
-
icon: zod_1.z.number().nullable().optional(),
|
|
26
|
-
});
|
|
27
|
-
exports.UpdateChannelArgsSchema = zod_1.z.object({
|
|
28
|
-
id: zod_1.z.string(),
|
|
29
|
-
name: zod_1.z.string(),
|
|
30
|
-
color: zod_1.z.number().nullable().optional(),
|
|
31
|
-
public: zod_1.z.boolean().nullable().optional(),
|
|
32
|
-
description: zod_1.z.string().nullable().optional(),
|
|
33
|
-
defaultGroups: zod_1.z.array(zod_1.z.string()).nullable().optional(),
|
|
34
|
-
defaultRecipients: zod_1.z.array(zod_1.z.number()).nullable().optional(),
|
|
35
|
-
isFavorited: zod_1.z.boolean().nullable().optional(),
|
|
36
|
-
icon: zod_1.z.number().nullable().optional(),
|
|
37
|
-
});
|
|
38
|
-
exports.CreateThreadArgsSchema = zod_1.z.object({
|
|
39
|
-
channelId: zod_1.z.string(),
|
|
40
|
-
content: zod_1.z.string(),
|
|
41
|
-
title: zod_1.z.string().nullable().optional(),
|
|
42
|
-
id: zod_1.z.string().optional(),
|
|
43
|
-
recipients: zod_1.z.array(zod_1.z.number()).nullable().optional(),
|
|
44
|
-
groups: zod_1.z.array(zod_1.z.string()).nullable().optional(),
|
|
45
|
-
notifyAudience: zod_1.z.enum(enums_1.NOTIFY_AUDIENCES).nullable().optional(),
|
|
46
|
-
attachments: zod_1.z.array(entities_1.RequestAttachmentSchema).nullable().optional(),
|
|
47
|
-
});
|
|
48
|
-
exports.UpdateThreadArgsSchema = zod_1.z.object({
|
|
49
|
-
id: zod_1.z.string(),
|
|
50
|
-
title: zod_1.z.string().nullable().optional(),
|
|
51
|
-
content: zod_1.z.string().nullable().optional(),
|
|
52
|
-
});
|
|
53
|
-
exports.CreateCommentArgsSchema = zod_1.z.object({
|
|
54
|
-
threadId: zod_1.z.string(),
|
|
55
|
-
content: zod_1.z.string(),
|
|
56
|
-
id: zod_1.z.string().optional(),
|
|
57
|
-
attachments: zod_1.z.array(entities_1.RequestAttachmentSchema).nullable().optional(),
|
|
58
|
-
actions: zod_1.z.unknown().nullable().optional(),
|
|
59
|
-
recipients: zod_1.z.array(zod_1.z.number()).nullable().optional(),
|
|
60
|
-
groups: zod_1.z.array(zod_1.z.string()).nullable().optional(),
|
|
61
|
-
directMentions: zod_1.z.array(zod_1.z.number()).nullable().optional(),
|
|
62
|
-
directGroupMentions: zod_1.z.array(zod_1.z.string()).nullable().optional(),
|
|
63
|
-
notifyAudience: zod_1.z.enum(enums_1.NOTIFY_AUDIENCES).nullable().optional(),
|
|
64
|
-
});
|
|
65
|
-
exports.UpdateCommentArgsSchema = zod_1.z.object({
|
|
66
|
-
id: zod_1.z.string(),
|
|
67
|
-
content: zod_1.z.string(),
|
|
68
|
-
});
|
|
69
|
-
exports.CreateConversationArgsSchema = zod_1.z.object({
|
|
70
|
-
workspaceId: zod_1.z.number(),
|
|
71
|
-
recipients: zod_1.z.array(zod_1.z.number()),
|
|
72
|
-
id: zod_1.z.string().optional(),
|
|
73
|
-
title: zod_1.z.string().nullable().optional(),
|
|
74
|
-
});
|
|
75
|
-
exports.CreateMessageArgsSchema = zod_1.z
|
|
76
|
-
.object({
|
|
77
|
-
conversationId: zod_1.z.string().nullable().optional(),
|
|
78
|
-
threadId: zod_1.z.string().nullable().optional(),
|
|
79
|
-
content: zod_1.z.string(),
|
|
80
|
-
id: zod_1.z.string().optional(),
|
|
81
|
-
attachments: zod_1.z.array(entities_1.RequestAttachmentSchema).nullable().optional(),
|
|
82
|
-
})
|
|
83
|
-
.refine((data) => {
|
|
84
|
-
return ((data.conversationId && !data.threadId) || (!data.conversationId && data.threadId));
|
|
85
|
-
}, {
|
|
86
|
-
message: 'Exactly one of conversationId or threadId must be provided',
|
|
87
|
-
});
|
|
88
|
-
exports.GetChannelsArgsSchema = zod_1.z.object({
|
|
89
|
-
workspaceId: zod_1.z.number(),
|
|
90
|
-
archived: zod_1.z.boolean().nullable().optional(),
|
|
91
|
-
});
|
|
92
|
-
exports.GetThreadsArgsSchema = zod_1.z.object({
|
|
93
|
-
workspaceId: zod_1.z.number(),
|
|
94
|
-
channelId: zod_1.z.string().nullable().optional(),
|
|
95
|
-
archived: zod_1.z.boolean().nullable().optional(),
|
|
96
|
-
newerThan: zod_1.z.date().nullable().optional(),
|
|
97
|
-
olderThan: zod_1.z.date().nullable().optional(),
|
|
98
|
-
limit: zod_1.z.number().nullable().optional(),
|
|
99
|
-
});
|
|
100
|
-
exports.GetCommentsArgsSchema = zod_1.z.object({
|
|
101
|
-
threadId: zod_1.z.string(),
|
|
102
|
-
newerThan: zod_1.z.date().nullable().optional(),
|
|
103
|
-
olderThan: zod_1.z.date().nullable().optional(),
|
|
104
|
-
limit: zod_1.z.number().nullable().optional(),
|
|
105
|
-
});
|
|
106
|
-
exports.GetConversationsArgsSchema = zod_1.z.object({
|
|
107
|
-
workspaceId: zod_1.z.number(),
|
|
108
|
-
archived: zod_1.z.boolean().nullable().optional(),
|
|
109
|
-
olderThan: zod_1.z.date().nullable().optional(),
|
|
110
|
-
beforeId: zod_1.z.string().nullable().optional(),
|
|
111
|
-
limit: zod_1.z.number().nullable().optional(),
|
|
112
|
-
});
|
|
113
|
-
exports.GetOrCreateConversationArgsSchema = zod_1.z.object({
|
|
114
|
-
workspaceId: zod_1.z.number(),
|
|
115
|
-
userIds: zod_1.z.array(zod_1.z.number()),
|
|
116
|
-
id: zod_1.z.string().optional(),
|
|
117
|
-
});
|
|
118
|
-
// Inbox
|
|
119
|
-
exports.ARCHIVE_FILTER_VALUES = ['active', 'archived', 'all'];
|
|
120
|
-
// Hooks
|
|
121
|
-
exports.NON_MESSAGE_HOOK_EVENTS = [
|
|
122
|
-
'workspace_added',
|
|
123
|
-
'workspace_updated',
|
|
124
|
-
'workspace_deleted',
|
|
125
|
-
'workspace_user_added',
|
|
126
|
-
'workspace_user_updated',
|
|
127
|
-
'workspace_user_removed',
|
|
128
|
-
'channel_added',
|
|
129
|
-
'channel_updated',
|
|
130
|
-
'channel_deleted',
|
|
131
|
-
'channel_user_added',
|
|
132
|
-
'channel_user_removed',
|
|
133
|
-
'thread_added',
|
|
134
|
-
'thread_updated',
|
|
135
|
-
'thread_deleted',
|
|
136
|
-
'comment_added',
|
|
137
|
-
'comment_updated',
|
|
138
|
-
'comment_deleted',
|
|
139
|
-
'group_added',
|
|
140
|
-
'group_updated',
|
|
141
|
-
'group_deleted',
|
|
142
|
-
'group_user_added',
|
|
143
|
-
'group_user_removed',
|
|
144
|
-
];
|
|
145
|
-
exports.MESSAGE_HOOK_EVENTS = ['message_added', 'message_updated'];
|
|
146
|
-
exports.HOOK_EVENTS = [...exports.NON_MESSAGE_HOOK_EVENTS, ...exports.MESSAGE_HOOK_EVENTS];
|
|
147
|
-
exports.NonMessageHookEventSchema = zod_1.z.enum(exports.NON_MESSAGE_HOOK_EVENTS);
|
|
148
|
-
exports.MessageHookEventSchema = zod_1.z.enum(exports.MESSAGE_HOOK_EVENTS);
|
|
149
|
-
exports.HookEventSchema = zod_1.z.enum(exports.HOOK_EVENTS);
|
|
150
|
-
exports.HookTargetUrlSchema = zod_1.z
|
|
151
|
-
.url()
|
|
152
|
-
.max(150)
|
|
153
|
-
.refine((value) => {
|
|
154
|
-
try {
|
|
155
|
-
return new URL(value).protocol === 'https:';
|
|
156
|
-
}
|
|
157
|
-
catch {
|
|
158
|
-
return false;
|
|
159
|
-
}
|
|
160
|
-
}, { message: 'URL must use HTTPS' });
|
|
161
|
-
exports.SubscribeHookArgsBaseSchema = zod_1.z.object({
|
|
162
|
-
targetUrl: exports.HookTargetUrlSchema,
|
|
163
|
-
workspaceId: zod_1.z.number().nullable().optional(),
|
|
164
|
-
channelId: zod_1.z.string().nullable().optional(),
|
|
165
|
-
threadId: zod_1.z.string().nullable().optional(),
|
|
166
|
-
});
|
|
167
|
-
exports.SubscribeNonMessageHookArgsSchema = exports.SubscribeHookArgsBaseSchema.extend({
|
|
168
|
-
event: exports.NonMessageHookEventSchema,
|
|
169
|
-
conversationId: zod_1.z.never().optional(),
|
|
170
|
-
});
|
|
171
|
-
exports.SubscribeMessageHookArgsSchema = exports.SubscribeHookArgsBaseSchema.extend({
|
|
172
|
-
event: exports.MessageHookEventSchema,
|
|
173
|
-
conversationId: zod_1.z.string().nullable().optional(),
|
|
174
|
-
});
|
|
175
|
-
exports.SubscribeHookArgsSchema = zod_1.z.union([
|
|
176
|
-
exports.SubscribeNonMessageHookArgsSchema,
|
|
177
|
-
exports.SubscribeMessageHookArgsSchema,
|
|
178
|
-
]);
|
|
179
|
-
exports.UnsubscribeHookArgsSchema = zod_1.z.object({
|
|
180
|
-
targetUrl: exports.HookTargetUrlSchema,
|
|
181
|
-
});
|
|
182
|
-
// Threads
|
|
183
|
-
exports.THREAD_ACTIONS = ['close', 'reopen'];
|
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.camelCaseKeys = camelCaseKeys;
|
|
7
|
-
exports.snakeCaseKeys = snakeCaseKeys;
|
|
8
|
-
const camelcase_1 = __importDefault(require("camelcase"));
|
|
9
|
-
function isObject(value) {
|
|
10
|
-
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
11
|
-
}
|
|
12
|
-
function isArray(value) {
|
|
13
|
-
return Array.isArray(value);
|
|
14
|
-
}
|
|
15
|
-
function toSnakeCase(str) {
|
|
16
|
-
return str
|
|
17
|
-
.replace(/([A-Z])/g, '_$1')
|
|
18
|
-
.toLowerCase()
|
|
19
|
-
.replace(/^_/, '');
|
|
20
|
-
}
|
|
21
|
-
/**
|
|
22
|
-
* @internal
|
|
23
|
-
*/
|
|
24
|
-
function camelCaseKeys(obj) {
|
|
25
|
-
if (isArray(obj)) {
|
|
26
|
-
return obj.map(camelCaseKeys);
|
|
27
|
-
}
|
|
28
|
-
if (isObject(obj)) {
|
|
29
|
-
const result = {};
|
|
30
|
-
for (const [key, value] of Object.entries(obj)) {
|
|
31
|
-
const camelKey = (0, camelcase_1.default)(key);
|
|
32
|
-
result[camelKey] = camelCaseKeys(value);
|
|
33
|
-
}
|
|
34
|
-
return result;
|
|
35
|
-
}
|
|
36
|
-
return obj;
|
|
37
|
-
}
|
|
38
|
-
/**
|
|
39
|
-
* @internal
|
|
40
|
-
*/
|
|
41
|
-
function snakeCaseKeys(obj) {
|
|
42
|
-
if (isArray(obj)) {
|
|
43
|
-
return obj.map(snakeCaseKeys);
|
|
44
|
-
}
|
|
45
|
-
if (isObject(obj)) {
|
|
46
|
-
const result = {};
|
|
47
|
-
for (const [key, value] of Object.entries(obj)) {
|
|
48
|
-
const snakeKey = toSnakeCase(key);
|
|
49
|
-
result[snakeKey] = snakeCaseKeys(value);
|
|
50
|
-
}
|
|
51
|
-
return result;
|
|
52
|
-
}
|
|
53
|
-
return obj;
|
|
54
|
-
}
|
package/dist/cjs/utils/index.js
DELETED
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
-
if (k2 === undefined) k2 = k;
|
|
4
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
-
}
|
|
8
|
-
Object.defineProperty(o, k2, desc);
|
|
9
|
-
}) : (function(o, m, k, k2) {
|
|
10
|
-
if (k2 === undefined) k2 = k;
|
|
11
|
-
o[k2] = m[k];
|
|
12
|
-
}));
|
|
13
|
-
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
-
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
-
};
|
|
16
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
-
__exportStar(require("./case-conversion"), exports);
|
|
18
|
-
__exportStar(require("./url-helpers"), exports);
|
|
19
|
-
__exportStar(require("./uuidv7"), exports);
|
|
@@ -1,144 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.getContentTypeFromFileName = getContentTypeFromFileName;
|
|
4
|
-
exports.uploadMultipartFile = uploadMultipartFile;
|
|
5
|
-
const fetch_with_retry_1 = require("../transport/fetch-with-retry");
|
|
6
|
-
/**
|
|
7
|
-
* Determine a content-type from a filename extension. Falls back to
|
|
8
|
-
* `application/octet-stream` for unknown extensions.
|
|
9
|
-
*/
|
|
10
|
-
function getContentTypeFromFileName(fileName) {
|
|
11
|
-
const extension = fileName.toLowerCase().split('.').pop();
|
|
12
|
-
return extension ? (MIME_BY_EXTENSION[extension] ?? DEFAULT_MIME_TYPE) : DEFAULT_MIME_TYPE;
|
|
13
|
-
}
|
|
14
|
-
const DEFAULT_MIME_TYPE = 'application/octet-stream';
|
|
15
|
-
/**
|
|
16
|
-
* Extension → MIME map covering the formats commonly attached to messages.
|
|
17
|
-
* Anything not listed falls back to {@link DEFAULT_MIME_TYPE}; callers can
|
|
18
|
-
* always override via the `contentType` argument.
|
|
19
|
-
*/
|
|
20
|
-
const MIME_BY_EXTENSION = {
|
|
21
|
-
// Images
|
|
22
|
-
png: 'image/png',
|
|
23
|
-
jpg: 'image/jpeg',
|
|
24
|
-
jpeg: 'image/jpeg',
|
|
25
|
-
gif: 'image/gif',
|
|
26
|
-
webp: 'image/webp',
|
|
27
|
-
svg: 'image/svg+xml',
|
|
28
|
-
bmp: 'image/bmp',
|
|
29
|
-
ico: 'image/x-icon',
|
|
30
|
-
tif: 'image/tiff',
|
|
31
|
-
tiff: 'image/tiff',
|
|
32
|
-
heic: 'image/heic',
|
|
33
|
-
heif: 'image/heif',
|
|
34
|
-
avif: 'image/avif',
|
|
35
|
-
// Documents / text
|
|
36
|
-
pdf: 'application/pdf',
|
|
37
|
-
txt: 'text/plain',
|
|
38
|
-
md: 'text/markdown',
|
|
39
|
-
csv: 'text/csv',
|
|
40
|
-
json: 'application/json',
|
|
41
|
-
xml: 'application/xml',
|
|
42
|
-
html: 'text/html',
|
|
43
|
-
htm: 'text/html',
|
|
44
|
-
rtf: 'application/rtf',
|
|
45
|
-
doc: 'application/msword',
|
|
46
|
-
docx: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
|
|
47
|
-
xls: 'application/vnd.ms-excel',
|
|
48
|
-
xlsx: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
|
|
49
|
-
ppt: 'application/vnd.ms-powerpoint',
|
|
50
|
-
pptx: 'application/vnd.openxmlformats-officedocument.presentationml.presentation',
|
|
51
|
-
// Archives
|
|
52
|
-
zip: 'application/zip',
|
|
53
|
-
gz: 'application/gzip',
|
|
54
|
-
tar: 'application/x-tar',
|
|
55
|
-
'7z': 'application/x-7z-compressed',
|
|
56
|
-
rar: 'application/vnd.rar',
|
|
57
|
-
// Audio
|
|
58
|
-
mp3: 'audio/mpeg',
|
|
59
|
-
wav: 'audio/wav',
|
|
60
|
-
ogg: 'audio/ogg',
|
|
61
|
-
m4a: 'audio/mp4',
|
|
62
|
-
flac: 'audio/flac',
|
|
63
|
-
aac: 'audio/aac',
|
|
64
|
-
// Video
|
|
65
|
-
mp4: 'video/mp4',
|
|
66
|
-
m4v: 'video/mp4',
|
|
67
|
-
mov: 'video/quicktime',
|
|
68
|
-
avi: 'video/x-msvideo',
|
|
69
|
-
webm: 'video/webm',
|
|
70
|
-
mkv: 'video/x-matroska',
|
|
71
|
-
};
|
|
72
|
-
/**
|
|
73
|
-
* Normalise a supported {@link UploadFile} into a `Blob` plus a resolved file name and
|
|
74
|
-
* content type, so uploads use the cross-platform global `FormData`/`Blob` body that
|
|
75
|
-
* `undici` and browsers both accept natively.
|
|
76
|
-
*/
|
|
77
|
-
function toBlob(file, fileName, contentType) {
|
|
78
|
-
if (file instanceof Blob) {
|
|
79
|
-
// Duck-type the name rather than `instanceof File`: `File` isn't a global in
|
|
80
|
-
// Node 18, so a `node:buffer` `File` (which carries a real `name`) would
|
|
81
|
-
// otherwise fall back to `'upload'` and lose its inferred file name.
|
|
82
|
-
const blobName = file.name;
|
|
83
|
-
const name = fileName || (typeof blobName === 'string' ? blobName : undefined) || 'upload';
|
|
84
|
-
const type = contentType || file.type || getContentTypeFromFileName(name);
|
|
85
|
-
// Re-wrap only when stamping a type the Blob doesn't already carry.
|
|
86
|
-
const blob = file.type === type ? file : new Blob([file], { type });
|
|
87
|
-
return { blob, fileName: name, contentType: type };
|
|
88
|
-
}
|
|
89
|
-
if (file instanceof Uint8Array) {
|
|
90
|
-
if (!fileName) {
|
|
91
|
-
throw new Error('fileName is required when uploading raw bytes');
|
|
92
|
-
}
|
|
93
|
-
const 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 }), 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 Comms upload shape); any
|
|
106
|
-
* `additionalFields` are merged in and override the derived values. Authentication uses
|
|
107
|
-
* `Authorization: Bearer`, matching every other Comms 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
|
-
async function uploadMultipartFile(args) {
|
|
114
|
-
const { baseUrl, authToken, endpoint, file, fileName, contentType, additionalFields, maxRetries = 0, requestId, customFetch, } = args;
|
|
115
|
-
const { blob, fileName: resolvedFileName, contentType: resolvedType, } = toBlob(file, fileName, contentType);
|
|
116
|
-
const fields = {
|
|
117
|
-
file_name: resolvedFileName,
|
|
118
|
-
file_size: blob.size,
|
|
119
|
-
underlying_type: resolvedType,
|
|
120
|
-
...additionalFields,
|
|
121
|
-
};
|
|
122
|
-
const form = new FormData();
|
|
123
|
-
form.append('file', blob, resolvedFileName);
|
|
124
|
-
for (const [key, value] of Object.entries(fields)) {
|
|
125
|
-
if (value !== undefined && value !== null) {
|
|
126
|
-
form.append(key, String(value));
|
|
127
|
-
}
|
|
128
|
-
}
|
|
129
|
-
const headers = {
|
|
130
|
-
Authorization: `Bearer ${authToken}`,
|
|
131
|
-
};
|
|
132
|
-
if (requestId) {
|
|
133
|
-
headers['X-Request-Id'] = requestId;
|
|
134
|
-
}
|
|
135
|
-
const url = new URL(endpoint, baseUrl).toString();
|
|
136
|
-
const response = await (0, fetch_with_retry_1.fetchWithRetry)(url, {
|
|
137
|
-
method: 'POST',
|
|
138
|
-
headers,
|
|
139
|
-
body: form,
|
|
140
|
-
// Don't set Content-Type — the runtime adds the multipart boundary.
|
|
141
|
-
timeout: 30000,
|
|
142
|
-
}, maxRetries, customFetch);
|
|
143
|
-
return response.data;
|
|
144
|
-
}
|
|
@@ -1,58 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.timestampToDate = timestampToDate;
|
|
4
|
-
exports.transformTimestamps = transformTimestamps;
|
|
5
|
-
/**
|
|
6
|
-
* Converts a Unix timestamp (in seconds) to a Date object.
|
|
7
|
-
* @param timestamp - Unix timestamp in seconds
|
|
8
|
-
* @returns Date object
|
|
9
|
-
*/
|
|
10
|
-
function timestampToDate(timestamp) {
|
|
11
|
-
return new Date(timestamp * 1000);
|
|
12
|
-
}
|
|
13
|
-
const timestampFieldTargetOverrides = new Map([['pinnedTs', 'pinnedDate']]);
|
|
14
|
-
/**
|
|
15
|
-
* Recursively transforms timestamp fields (ending in 'Ts') in an object to Date objects.
|
|
16
|
-
* Also renames converted fields by removing the 'Ts' suffix.
|
|
17
|
-
* @param obj - The object to transform
|
|
18
|
-
* @returns The transformed object with Date fields
|
|
19
|
-
*/
|
|
20
|
-
function transformTimestamps(obj) {
|
|
21
|
-
if (obj === null || obj === undefined) {
|
|
22
|
-
return obj;
|
|
23
|
-
}
|
|
24
|
-
if (Array.isArray(obj)) {
|
|
25
|
-
return obj.map((item) => transformTimestamps(item));
|
|
26
|
-
}
|
|
27
|
-
if (typeof obj === 'object') {
|
|
28
|
-
const result = {};
|
|
29
|
-
for (const [key, value] of Object.entries(obj)) {
|
|
30
|
-
// Check if the key ends with 'Ts'
|
|
31
|
-
if (key.endsWith('Ts')) {
|
|
32
|
-
const overriddenTargetKey = timestampFieldTargetOverrides.get(key);
|
|
33
|
-
if (typeof value === 'number') {
|
|
34
|
-
// Remove 'Ts' suffix and convert to Date
|
|
35
|
-
const newKey = key.slice(0, -2);
|
|
36
|
-
// If the base key already exists in the original object, use *Date suffix
|
|
37
|
-
// to avoid overwriting it (e.g. posted + postedTs → posted + postedDate)
|
|
38
|
-
const targetKey = overriddenTargetKey ??
|
|
39
|
-
(newKey in obj ? `${newKey}Date` : newKey);
|
|
40
|
-
result[targetKey] = timestampToDate(value);
|
|
41
|
-
continue;
|
|
42
|
-
}
|
|
43
|
-
if (overriddenTargetKey) {
|
|
44
|
-
result[overriddenTargetKey] = value;
|
|
45
|
-
continue;
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
if (typeof value === 'object' && value !== null) {
|
|
49
|
-
// Recursively transform nested objects
|
|
50
|
-
result[key] = transformTimestamps(value);
|
|
51
|
-
continue;
|
|
52
|
-
}
|
|
53
|
-
result[key] = value;
|
|
54
|
-
}
|
|
55
|
-
return result;
|
|
56
|
-
}
|
|
57
|
-
return obj;
|
|
58
|
-
}
|
|
@@ -1,133 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/**
|
|
3
|
-
* Helper functions for creating Comms permalinks (`https://comms.todoist.com/...`).
|
|
4
|
-
*/
|
|
5
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.getCommsURL = getCommsURL;
|
|
7
|
-
exports.getFullCommsURL = getFullCommsURL;
|
|
8
|
-
exports.getThreadURL = getThreadURL;
|
|
9
|
-
exports.getChannelURL = getChannelURL;
|
|
10
|
-
exports.getConversationURL = getConversationURL;
|
|
11
|
-
exports.getMessageURL = getMessageURL;
|
|
12
|
-
exports.getCommentURL = getCommentURL;
|
|
13
|
-
exports.getThreadsRootURL = getThreadsRootURL;
|
|
14
|
-
exports.getInboxURL = getInboxURL;
|
|
15
|
-
exports.getMessagesRootURL = getMessagesRootURL;
|
|
16
|
-
exports.getUserProfileURL = getUserProfileURL;
|
|
17
|
-
exports.getSavedThreadsRootURL = getSavedThreadsRootURL;
|
|
18
|
-
exports.getSavedThreadURL = getSavedThreadURL;
|
|
19
|
-
exports.getSearchRootURL = getSearchRootURL;
|
|
20
|
-
exports.getSearchQueryURL = getSearchQueryURL;
|
|
21
|
-
exports.getSettingsURL = getSettingsURL;
|
|
22
|
-
exports.getTeamMembersRootURL = getTeamMembersRootURL;
|
|
23
|
-
const COMMS_BASE_URL = 'https://comms.todoist.com';
|
|
24
|
-
/**
|
|
25
|
-
* Builds a relative Comms URL based on the provided parameters
|
|
26
|
-
* @param params - URL parameters including workspace, channel, conversation, thread, etc.
|
|
27
|
-
* @returns A relative URL path
|
|
28
|
-
* @example
|
|
29
|
-
* getCommsURL({ workspaceId: 1, channelId: '7Yp...', threadId: '7Yq...' })
|
|
30
|
-
* // returns '/1/ch/7Yp.../t/7Yq.../'
|
|
31
|
-
*/
|
|
32
|
-
function getCommsURL(params) {
|
|
33
|
-
const { workspaceId, channelId, conversationId, threadId, commentId, messageId, userId } = params;
|
|
34
|
-
let url = `/${workspaceId}/`;
|
|
35
|
-
if (channelId) {
|
|
36
|
-
url += `ch/${channelId}/`;
|
|
37
|
-
if (threadId) {
|
|
38
|
-
url += `t/${threadId}/`;
|
|
39
|
-
if (commentId) {
|
|
40
|
-
url += `c/${commentId}`;
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
else if (threadId) {
|
|
45
|
-
url += `inbox/t/${threadId}/`;
|
|
46
|
-
if (commentId) {
|
|
47
|
-
url += `c/${commentId}`;
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
else if (conversationId) {
|
|
51
|
-
url += `msg/${conversationId}/`;
|
|
52
|
-
if (messageId) {
|
|
53
|
-
url += `m/${messageId}`;
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
else if (userId) {
|
|
57
|
-
url += `people/u/${userId}`;
|
|
58
|
-
}
|
|
59
|
-
return url;
|
|
60
|
-
}
|
|
61
|
-
/**
|
|
62
|
-
* Builds a full Comms URL (with protocol and hostname) based on the provided parameters
|
|
63
|
-
* @param params - URL parameters including workspace, channel, conversation, thread, etc.
|
|
64
|
-
* @param baseUrl - Optional base URL (defaults to 'https://comms.todoist.com')
|
|
65
|
-
*/
|
|
66
|
-
function getFullCommsURL(params, baseUrl = COMMS_BASE_URL) {
|
|
67
|
-
// Strip a trailing slash so links don't double up — `getCommsURL` paths start with '/'.
|
|
68
|
-
const normalizedBase = baseUrl.endsWith('/') ? baseUrl.slice(0, -1) : baseUrl;
|
|
69
|
-
return `${normalizedBase}${getCommsURL(params)}`;
|
|
70
|
-
}
|
|
71
|
-
/** Returns the URL for a thread in a channel. */
|
|
72
|
-
function getThreadURL(params) {
|
|
73
|
-
return getCommsURL(params);
|
|
74
|
-
}
|
|
75
|
-
/** Returns the URL for a channel. */
|
|
76
|
-
function getChannelURL(params) {
|
|
77
|
-
return getCommsURL(params);
|
|
78
|
-
}
|
|
79
|
-
/** Returns the URL for a conversation. */
|
|
80
|
-
function getConversationURL(params) {
|
|
81
|
-
return getCommsURL(params);
|
|
82
|
-
}
|
|
83
|
-
/** Returns the URL for a specific message in a conversation. */
|
|
84
|
-
function getMessageURL(params) {
|
|
85
|
-
return getCommsURL(params);
|
|
86
|
-
}
|
|
87
|
-
/** Returns the URL for a comment in a thread. */
|
|
88
|
-
function getCommentURL(params) {
|
|
89
|
-
return getCommsURL(params);
|
|
90
|
-
}
|
|
91
|
-
/** Returns the URL for the threads root (channels view). */
|
|
92
|
-
function getThreadsRootURL(workspaceId) {
|
|
93
|
-
return `/${workspaceId}/ch`;
|
|
94
|
-
}
|
|
95
|
-
/** Returns the URL for the inbox. */
|
|
96
|
-
function getInboxURL(workspaceId, tab) {
|
|
97
|
-
const tabParam = tab ? `/${tab}` : '';
|
|
98
|
-
return `/${workspaceId}/inbox${tabParam}`;
|
|
99
|
-
}
|
|
100
|
-
/** Returns the URL for the messages/conversations root. */
|
|
101
|
-
function getMessagesRootURL(workspaceId) {
|
|
102
|
-
return `/${workspaceId}/msg`;
|
|
103
|
-
}
|
|
104
|
-
/** Returns the URL for a user profile. */
|
|
105
|
-
function getUserProfileURL(params) {
|
|
106
|
-
return `/${params.workspaceId}/people/u/${params.userId}`;
|
|
107
|
-
}
|
|
108
|
-
/** Returns the URL for the saved threads view. */
|
|
109
|
-
function getSavedThreadsRootURL(workspaceId) {
|
|
110
|
-
return `/${workspaceId}/saved`;
|
|
111
|
-
}
|
|
112
|
-
/** Returns the URL for a saved thread. */
|
|
113
|
-
function getSavedThreadURL(params) {
|
|
114
|
-
return `/${params.workspaceId}/saved/t/${params.threadId}`;
|
|
115
|
-
}
|
|
116
|
-
/** Returns the URL for the search root. */
|
|
117
|
-
function getSearchRootURL(workspaceId) {
|
|
118
|
-
return `/${workspaceId}/search`;
|
|
119
|
-
}
|
|
120
|
-
/** Returns the URL for a search with a query. */
|
|
121
|
-
function getSearchQueryURL(params) {
|
|
122
|
-
return `/${params.workspaceId}/search?q=${decodeURIComponent(params.query)}`;
|
|
123
|
-
}
|
|
124
|
-
/** Returns the URL for settings. */
|
|
125
|
-
function getSettingsURL(params) {
|
|
126
|
-
return params.initialLocation
|
|
127
|
-
? `/${params.workspaceId}/settings/${params.initialLocation}`
|
|
128
|
-
: `/${params.workspaceId}/settings`;
|
|
129
|
-
}
|
|
130
|
-
/** Returns the URL for the team members root. */
|
|
131
|
-
function getTeamMembersRootURL(workspaceId) {
|
|
132
|
-
return `/${workspaceId}/people/u`;
|
|
133
|
-
}
|