@doist/comms-sdk 0.0.1 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (115) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +143 -45
  3. package/dist/cjs/authentication.js +211 -0
  4. package/dist/cjs/clients/add-comment-helper.js +70 -0
  5. package/dist/cjs/clients/base-client.js +25 -0
  6. package/dist/cjs/clients/channels-client.js +200 -0
  7. package/dist/cjs/clients/comments-client.js +159 -0
  8. package/dist/cjs/clients/conversation-messages-client.js +158 -0
  9. package/dist/cjs/clients/conversations-client.js +243 -0
  10. package/dist/cjs/clients/groups-client.js +164 -0
  11. package/dist/cjs/clients/inbox-client.js +171 -0
  12. package/dist/cjs/clients/reactions-client.js +97 -0
  13. package/dist/cjs/clients/search-client.js +138 -0
  14. package/dist/cjs/clients/threads-client.js +330 -0
  15. package/dist/cjs/clients/users-client.js +326 -0
  16. package/dist/cjs/clients/workspace-users-client.js +240 -0
  17. package/dist/cjs/clients/workspaces-client.js +166 -0
  18. package/dist/cjs/comms-api.js +66 -0
  19. package/dist/cjs/consts/endpoints.js +32 -0
  20. package/dist/cjs/index.js +48 -0
  21. package/dist/cjs/package.json +1 -0
  22. package/dist/cjs/testUtils/msw-handlers.js +51 -0
  23. package/dist/cjs/testUtils/msw-setup.js +21 -0
  24. package/dist/cjs/testUtils/obsidian-fetch-adapter.js +53 -0
  25. package/dist/cjs/testUtils/test-defaults.js +104 -0
  26. package/dist/cjs/transport/fetch-with-retry.js +136 -0
  27. package/dist/cjs/transport/http-client.js +56 -0
  28. package/dist/cjs/transport/http-dispatcher.js +143 -0
  29. package/dist/cjs/types/api-version.js +8 -0
  30. package/dist/cjs/types/entities.js +411 -0
  31. package/dist/cjs/types/enums.js +37 -0
  32. package/dist/cjs/types/errors.js +12 -0
  33. package/dist/cjs/types/http.js +4 -0
  34. package/dist/cjs/types/index.js +22 -0
  35. package/dist/cjs/types/requests.js +116 -0
  36. package/dist/cjs/utils/case-conversion.js +54 -0
  37. package/dist/cjs/utils/index.js +19 -0
  38. package/dist/cjs/utils/timestamp-conversion.js +49 -0
  39. package/dist/cjs/utils/url-helpers.js +131 -0
  40. package/dist/cjs/utils/uuidv7.js +174 -0
  41. package/dist/esm/authentication.js +203 -0
  42. package/dist/esm/clients/add-comment-helper.js +67 -0
  43. package/dist/esm/clients/base-client.js +21 -0
  44. package/dist/esm/clients/channels-client.js +196 -0
  45. package/dist/esm/clients/comments-client.js +155 -0
  46. package/dist/esm/clients/conversation-messages-client.js +154 -0
  47. package/dist/esm/clients/conversations-client.js +239 -0
  48. package/dist/esm/clients/groups-client.js +160 -0
  49. package/dist/esm/clients/inbox-client.js +167 -0
  50. package/dist/esm/clients/reactions-client.js +93 -0
  51. package/dist/esm/clients/search-client.js +134 -0
  52. package/dist/esm/clients/threads-client.js +326 -0
  53. package/dist/esm/clients/users-client.js +322 -0
  54. package/dist/esm/clients/workspace-users-client.js +236 -0
  55. package/dist/esm/clients/workspaces-client.js +162 -0
  56. package/dist/esm/comms-api.js +62 -0
  57. package/dist/esm/consts/endpoints.js +28 -0
  58. package/dist/esm/index.js +17 -0
  59. package/dist/esm/testUtils/msw-handlers.js +45 -0
  60. package/dist/esm/testUtils/msw-setup.js +18 -0
  61. package/dist/esm/testUtils/obsidian-fetch-adapter.js +50 -0
  62. package/dist/esm/testUtils/test-defaults.js +101 -0
  63. package/dist/esm/transport/fetch-with-retry.js +133 -0
  64. package/dist/esm/transport/http-client.js +51 -0
  65. package/dist/esm/transport/http-dispatcher.js +104 -0
  66. package/dist/esm/types/api-version.js +5 -0
  67. package/dist/esm/types/entities.js +408 -0
  68. package/dist/esm/types/enums.js +34 -0
  69. package/dist/esm/types/errors.js +8 -0
  70. package/dist/esm/types/http.js +1 -0
  71. package/dist/esm/types/index.js +6 -0
  72. package/dist/esm/types/requests.js +113 -0
  73. package/dist/esm/utils/case-conversion.js +47 -0
  74. package/dist/esm/utils/index.js +3 -0
  75. package/dist/esm/utils/timestamp-conversion.js +45 -0
  76. package/dist/esm/utils/url-helpers.js +112 -0
  77. package/dist/esm/utils/uuidv7.js +163 -0
  78. package/dist/types/authentication.d.ts +160 -0
  79. package/dist/types/clients/add-comment-helper.d.ts +29 -0
  80. package/dist/types/clients/base-client.d.ts +28 -0
  81. package/dist/types/clients/channels-client.d.ts +208 -0
  82. package/dist/types/clients/comments-client.d.ts +224 -0
  83. package/dist/types/clients/conversation-messages-client.d.ts +198 -0
  84. package/dist/types/clients/conversations-client.d.ts +346 -0
  85. package/dist/types/clients/groups-client.d.ts +148 -0
  86. package/dist/types/clients/inbox-client.d.ts +96 -0
  87. package/dist/types/clients/reactions-client.d.ts +57 -0
  88. package/dist/types/clients/search-client.d.ts +70 -0
  89. package/dist/types/clients/threads-client.d.ts +536 -0
  90. package/dist/types/clients/users-client.d.ts +250 -0
  91. package/dist/types/clients/workspace-users-client.d.ts +147 -0
  92. package/dist/types/clients/workspaces-client.d.ts +152 -0
  93. package/dist/types/comms-api.d.ts +62 -0
  94. package/dist/types/consts/endpoints.d.ts +24 -0
  95. package/dist/types/index.d.ts +18 -0
  96. package/dist/types/testUtils/msw-handlers.d.ts +28 -0
  97. package/dist/types/testUtils/msw-setup.d.ts +1 -0
  98. package/dist/types/testUtils/obsidian-fetch-adapter.d.ts +29 -0
  99. package/dist/types/testUtils/test-defaults.d.ts +17 -0
  100. package/dist/types/transport/fetch-with-retry.d.ts +4 -0
  101. package/dist/types/transport/http-client.d.ts +13 -0
  102. package/dist/types/transport/http-dispatcher.d.ts +10 -0
  103. package/dist/types/types/api-version.d.ts +6 -0
  104. package/dist/types/types/entities.d.ts +1288 -0
  105. package/dist/types/types/enums.d.ts +55 -0
  106. package/dist/types/types/errors.d.ts +6 -0
  107. package/dist/types/types/http.d.ts +54 -0
  108. package/dist/types/types/index.d.ts +6 -0
  109. package/dist/types/types/requests.d.ts +366 -0
  110. package/dist/types/utils/case-conversion.d.ts +8 -0
  111. package/dist/types/utils/index.d.ts +3 -0
  112. package/dist/types/utils/timestamp-conversion.d.ts +13 -0
  113. package/dist/types/utils/url-helpers.d.ts +88 -0
  114. package/dist/types/utils/uuidv7.d.ts +40 -0
  115. package/package.json +91 -8
@@ -0,0 +1,411 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SearchResultSchema = exports.SEARCH_RESULT_TYPES = exports.UnreadConversationSchema = exports.UnreadThreadSchema = exports.InboxThreadSchema = exports.ConversationMessageSchema = exports.WorkspaceUserSchema = exports.CommentSchema = exports.ConversationSchema = exports.GroupSchema = exports.ThreadSchema = exports.ChannelSchema = exports.WorkspaceSchema = exports.UserSchema = exports.BaseUserSchema = exports.AttachmentSchema = exports.StatusOkSchema = exports.SystemMessageSchema = void 0;
4
+ const zod_1 = require("zod");
5
+ const url_helpers_1 = require("../utils/url-helpers");
6
+ const enums_1 = require("./enums");
7
+ // EVERYONE / EVERYONE_IN_THREAD / GROUP_ID_MARKERS / GroupId / GroupIdMarker
8
+ // are defined in `./enums` (re-exported through `./index`) to keep this
9
+ // module from depending back on `./enums` for them. They're available
10
+ // from the same public surface (`@doist/comms-sdk`) either way.
11
+ // Reusable schema for system messages that can be either a string or an
12
+ // object. Nullable — the backend returns `null` when there is no system
13
+ // message.
14
+ exports.SystemMessageSchema = zod_1.z.union([zod_1.z.string(), zod_1.z.unknown()]).nullable().optional();
15
+ /**
16
+ * Shared `{ status: "ok" }` response shape. Pinned to the literal `'ok'`
17
+ * so a regression on the backend (e.g. a status code change) surfaces as
18
+ * a parse error here instead of being silently typed away. Most write
19
+ * endpoints that don't return an entity use this — archive / unarchive /
20
+ * mark-read / mark-all-read / mute / clear-unread / etc.
21
+ */
22
+ exports.StatusOkSchema = zod_1.z.object({ status: zod_1.z.literal('ok') });
23
+ // Attachment entity from API. Mirrors the canonical backend shape produced
24
+ // by `unify_attachments` / `validate_file_attachment_json`. Only
25
+ // `attachmentId` and `urlType` are guaranteed; everything else depends on
26
+ // the attachment kind (file vs image vs link preview vs unfurled GIF).
27
+ // Loose: unknown keys from the backend pass through rather than being
28
+ // stripped, so newly-added or off-spec fields stay accessible to callers.
29
+ exports.AttachmentSchema = zod_1.z
30
+ .object({
31
+ attachmentId: zod_1.z.string(),
32
+ urlType: zod_1.z.string(),
33
+ title: zod_1.z.string().nullable().optional(),
34
+ url: zod_1.z.string().nullable().optional(),
35
+ fileName: zod_1.z.string().nullable().optional(),
36
+ fileSize: zod_1.z.number().int().nonnegative().nullable().optional(),
37
+ underlyingType: zod_1.z.string().nullable().optional(),
38
+ description: zod_1.z.string().nullable().optional(),
39
+ image: zod_1.z.string().nullable().optional(),
40
+ imageWidth: zod_1.z.number().int().nonnegative().nullable().optional(),
41
+ imageHeight: zod_1.z.number().int().nonnegative().nullable().optional(),
42
+ duration: zod_1.z.string().nullable().optional(),
43
+ uploadState: zod_1.z.string().nullable().optional(),
44
+ video: zod_1.z.string().nullable().optional(),
45
+ videoType: zod_1.z.string().nullable().optional(),
46
+ videoAutoPlay: zod_1.z.boolean().nullable().optional(),
47
+ })
48
+ .loose();
49
+ // Fields shared by `User` and `WorkspaceUser`. Profile fields
50
+ // (`fullName`, `imageId`, avatar URLs) are sourced from Todoist-ID.
51
+ exports.BaseUserSchema = zod_1.z.object({
52
+ id: zod_1.z.number(),
53
+ fullName: zod_1.z.string(),
54
+ shortName: zod_1.z.string(),
55
+ firstName: zod_1.z.string().nullable().optional(),
56
+ timezone: zod_1.z.string(),
57
+ removed: zod_1.z.boolean(),
58
+ imageId: zod_1.z.string().nullable().optional(),
59
+ avatarUrls: zod_1.z
60
+ .object({
61
+ s35: zod_1.z.string(),
62
+ s60: zod_1.z.string(),
63
+ s195: zod_1.z.string(),
64
+ s640: zod_1.z.string(),
65
+ })
66
+ .nullable()
67
+ .optional(),
68
+ restricted: zod_1.z.boolean().nullable().optional(),
69
+ setupPending: zod_1.z.boolean().nullable().optional(),
70
+ });
71
+ // User entity from API.
72
+ exports.UserSchema = exports.BaseUserSchema.extend({
73
+ email: zod_1.z.email(),
74
+ clientId: zod_1.z.string().nullable().optional(),
75
+ cometChannel: zod_1.z.string().nullable().optional(),
76
+ lang: zod_1.z.string(),
77
+ cometServer: zod_1.z.string().nullable().optional(),
78
+ token: zod_1.z.string().nullable().optional(),
79
+ scheduledBanners: zod_1.z.array(zod_1.z.string()).nullable().optional(),
80
+ });
81
+ // Workspace entity from API. `default_conversation` is a base58 UUIDv7
82
+ // string. `avatar_id` is kept (unlike the User rename to `image_id`,
83
+ // which is a User-only change per Comms_API_changes.md PR #125).
84
+ // `plan` is intentionally `z.string()` — see {@link WORKSPACE_PLANS}.
85
+ exports.WorkspaceSchema = zod_1.z.object({
86
+ id: zod_1.z.number(),
87
+ name: zod_1.z.string(),
88
+ defaultConversation: zod_1.z.string().nullable().optional(),
89
+ creator: zod_1.z.number(),
90
+ created: zod_1.z.date(),
91
+ avatarId: zod_1.z.string().nullable().optional(),
92
+ avatarUrls: zod_1.z
93
+ .object({
94
+ s35: zod_1.z.string(),
95
+ s60: zod_1.z.string(),
96
+ s195: zod_1.z.string(),
97
+ s640: zod_1.z.string(),
98
+ })
99
+ .nullable()
100
+ .optional(),
101
+ plan: zod_1.z.string().nullable().optional(),
102
+ });
103
+ exports.ChannelSchema = zod_1.z
104
+ .object({
105
+ id: zod_1.z.string(),
106
+ name: zod_1.z.string(),
107
+ description: zod_1.z.string().nullable().optional(),
108
+ creator: zod_1.z.number(),
109
+ userIds: zod_1.z.array(zod_1.z.number()).nullable().optional(),
110
+ color: zod_1.z.number().nullable().optional(),
111
+ public: zod_1.z.boolean(),
112
+ workspaceId: zod_1.z.number(),
113
+ archived: zod_1.z.boolean(),
114
+ created: zod_1.z.date(),
115
+ useDefaultRecipients: zod_1.z.boolean().nullable().optional(),
116
+ defaultGroups: zod_1.z.array(zod_1.z.string()).nullable().optional(),
117
+ defaultRecipients: zod_1.z.array(zod_1.z.number()).nullable().optional(),
118
+ isFavorited: zod_1.z.boolean().nullable().optional(),
119
+ icon: zod_1.z.number().nullable().optional(),
120
+ version: zod_1.z.number(),
121
+ filters: zod_1.z.record(zod_1.z.string(), zod_1.z.string()).nullable().optional(),
122
+ })
123
+ .transform((data) => ({
124
+ ...data,
125
+ url: (0, url_helpers_1.getFullCommsURL)({ workspaceId: data.workspaceId, channelId: data.id }),
126
+ }));
127
+ // Thread entity from API. `pinned` (boolean) and `pinnedTs` (epoch ms or
128
+ // null) are both surfaced — `pinned` is kept for Zapier/webhook clients.
129
+ exports.ThreadSchema = zod_1.z
130
+ .object({
131
+ id: zod_1.z.string(),
132
+ title: zod_1.z.string(),
133
+ content: zod_1.z.string(),
134
+ creator: zod_1.z.number(),
135
+ creatorName: zod_1.z.string().nullable().optional(),
136
+ channelId: zod_1.z.string(),
137
+ workspaceId: zod_1.z.number(),
138
+ actions: zod_1.z.array(zod_1.z.unknown()).nullable().optional(),
139
+ attachments: zod_1.z.array(exports.AttachmentSchema).nullable().optional(),
140
+ commentCount: zod_1.z.number(),
141
+ closed: zod_1.z.boolean().nullable().optional(),
142
+ directGroupMentions: zod_1.z.array(zod_1.z.string()).nullable().optional(),
143
+ directMentions: zod_1.z.array(zod_1.z.number()).nullable().optional(),
144
+ groups: zod_1.z.array(zod_1.z.string()).nullable().optional(),
145
+ lastEdited: zod_1.z.date().nullable().optional(),
146
+ lastObjIndex: zod_1.z.number().nullable().optional(),
147
+ lastUpdated: zod_1.z.date(),
148
+ mutedUntil: zod_1.z.date().nullable().optional(),
149
+ participants: zod_1.z.array(zod_1.z.number()).nullable().optional(),
150
+ // Backend wire shape only includes `pinned_ts` (epoch ms or null);
151
+ // derive `pinned` from `pinnedTs != null` if you need a bool.
152
+ pinned: zod_1.z.boolean().optional(),
153
+ pinnedTs: zod_1.z.number().int().nullable().optional(),
154
+ posted: zod_1.z.date(),
155
+ reactions: zod_1.z.record(zod_1.z.string(), zod_1.z.unknown()).nullable().optional(),
156
+ recipients: zod_1.z.array(zod_1.z.number()).nullable().optional(),
157
+ responders: zod_1.z.array(zod_1.z.number()).nullable().optional(),
158
+ snippet: zod_1.z.string(),
159
+ snippetCreator: zod_1.z.number(),
160
+ snippetMaskAvatarUrl: zod_1.z.string().nullable().optional(),
161
+ snippetMaskPoster: zod_1.z.string().nullable().optional(),
162
+ systemMessage: exports.SystemMessageSchema,
163
+ toEmails: zod_1.z.array(zod_1.z.string()).nullable().optional(),
164
+ isArchived: zod_1.z.boolean(),
165
+ isSaved: zod_1.z.boolean().nullable().optional(),
166
+ inInbox: zod_1.z.boolean().nullable().optional(),
167
+ lastComment: zod_1.z
168
+ .object({
169
+ id: zod_1.z.string(),
170
+ content: zod_1.z.string(),
171
+ creator: zod_1.z.number(),
172
+ creatorName: zod_1.z.string(),
173
+ threadId: zod_1.z.string(),
174
+ channelId: zod_1.z.string(),
175
+ posted: zod_1.z.date(),
176
+ systemMessage: exports.SystemMessageSchema,
177
+ attachments: zod_1.z.array(exports.AttachmentSchema).nullable().optional(),
178
+ reactions: zod_1.z.record(zod_1.z.string(), zod_1.z.array(zod_1.z.number())).nullable().optional(),
179
+ actions: zod_1.z.array(zod_1.z.unknown()).nullable().optional(),
180
+ objIndex: zod_1.z.number(),
181
+ lastEdited: zod_1.z.date().nullable().optional(),
182
+ deleted: zod_1.z.boolean(),
183
+ deletedBy: zod_1.z.number().nullable().optional(),
184
+ directGroupMentions: zod_1.z.array(zod_1.z.string()).nullable().optional(),
185
+ directMentions: zod_1.z.array(zod_1.z.number()).nullable().optional(),
186
+ groups: zod_1.z.array(zod_1.z.string()).nullable().optional(),
187
+ recipients: zod_1.z.array(zod_1.z.number()).nullable().optional(),
188
+ toEmails: zod_1.z.array(zod_1.z.string()).nullable().optional(),
189
+ version: zod_1.z.number(),
190
+ workspaceId: zod_1.z.number(),
191
+ })
192
+ .nullable()
193
+ .optional(),
194
+ })
195
+ .transform((data) => ({
196
+ ...data,
197
+ url: (0, url_helpers_1.getFullCommsURL)({
198
+ workspaceId: data.workspaceId,
199
+ channelId: data.channelId,
200
+ threadId: data.id,
201
+ }),
202
+ }));
203
+ // Group entity from API. The broadcast markers `EVERYONE` and
204
+ // `EVERYONE_IN_THREAD` can appear in place of a real `id` in group-bearing
205
+ // fields on threads/comments/channels.
206
+ exports.GroupSchema = zod_1.z.object({
207
+ id: zod_1.z.string(),
208
+ name: zod_1.z.string(),
209
+ description: zod_1.z.string().nullable().optional(),
210
+ workspaceId: zod_1.z.number(),
211
+ userIds: zod_1.z.array(zod_1.z.number()),
212
+ version: zod_1.z.number(),
213
+ });
214
+ // Conversation entity from API.
215
+ exports.ConversationSchema = zod_1.z
216
+ .object({
217
+ id: zod_1.z.string(),
218
+ workspaceId: zod_1.z.number(),
219
+ userIds: zod_1.z.array(zod_1.z.number()),
220
+ messageCount: zod_1.z.number().nullable().optional(),
221
+ lastObjIndex: zod_1.z.number(),
222
+ snippet: zod_1.z.string(),
223
+ snippetCreators: zod_1.z.array(zod_1.z.number()),
224
+ lastActive: zod_1.z.date(),
225
+ mutedUntil: zod_1.z.date().nullable().optional(),
226
+ archived: zod_1.z.boolean(),
227
+ created: zod_1.z.date(),
228
+ creator: zod_1.z.number(),
229
+ title: zod_1.z.string().nullable().optional(),
230
+ private: zod_1.z.boolean().nullable().optional(),
231
+ lastMessage: zod_1.z
232
+ .object({
233
+ // `id` may be string or number depending on the endpoint; coerced.
234
+ id: zod_1.z.union([zod_1.z.string(), zod_1.z.number()]).transform(String),
235
+ content: zod_1.z.string(),
236
+ creator: zod_1.z.number(),
237
+ conversationId: zod_1.z.string(),
238
+ posted: zod_1.z.date(),
239
+ systemMessage: exports.SystemMessageSchema,
240
+ attachments: zod_1.z.array(exports.AttachmentSchema).nullable().optional(),
241
+ reactions: zod_1.z.record(zod_1.z.string(), zod_1.z.array(zod_1.z.number())).nullable().optional(),
242
+ actions: zod_1.z.array(zod_1.z.unknown()).nullable().optional(),
243
+ objIndex: zod_1.z.number().nullable().optional(),
244
+ lastEdited: zod_1.z.date().nullable().optional(),
245
+ deleted: zod_1.z.boolean().nullable().optional(),
246
+ directGroupMentions: zod_1.z.array(zod_1.z.string()).nullable().optional(),
247
+ directMentions: zod_1.z.array(zod_1.z.number()).nullable().optional(),
248
+ version: zod_1.z.number().nullable().optional(),
249
+ workspaceId: zod_1.z.number().nullable().optional(),
250
+ })
251
+ .nullable()
252
+ .optional(),
253
+ })
254
+ .transform((data) => ({
255
+ ...data,
256
+ url: (0, url_helpers_1.getFullCommsURL)({ workspaceId: data.workspaceId, conversationId: data.id }),
257
+ }));
258
+ exports.CommentSchema = zod_1.z
259
+ .object({
260
+ id: zod_1.z.string(),
261
+ content: zod_1.z.string(),
262
+ creator: zod_1.z.number(),
263
+ threadId: zod_1.z.string(),
264
+ workspaceId: zod_1.z.number(),
265
+ conversationId: zod_1.z.string().nullable().optional(),
266
+ posted: zod_1.z.date(),
267
+ lastEdited: zod_1.z.date().nullable().optional(),
268
+ directMentions: zod_1.z.array(zod_1.z.number()).nullable().optional(),
269
+ directGroupMentions: zod_1.z.array(zod_1.z.string()).nullable().optional(),
270
+ systemMessage: exports.SystemMessageSchema,
271
+ attachments: zod_1.z.array(exports.AttachmentSchema).nullable().optional(),
272
+ reactions: zod_1.z.record(zod_1.z.string(), zod_1.z.unknown()).nullable().optional(),
273
+ objIndex: zod_1.z.number().nullable().optional(),
274
+ creatorName: zod_1.z.string().nullable().optional(),
275
+ channelId: zod_1.z.string(),
276
+ recipients: zod_1.z.array(zod_1.z.number()).nullable().optional(),
277
+ groups: zod_1.z.array(zod_1.z.string()).nullable().optional(),
278
+ toEmails: zod_1.z.array(zod_1.z.string()).nullable().optional(),
279
+ deleted: zod_1.z.boolean().nullable().optional(),
280
+ deletedBy: zod_1.z.number().nullable().optional(),
281
+ version: zod_1.z.number().nullable().optional(),
282
+ actions: zod_1.z.array(zod_1.z.unknown()).nullable().optional(),
283
+ })
284
+ .transform((data) => ({
285
+ ...data,
286
+ url: (0, url_helpers_1.getFullCommsURL)({
287
+ workspaceId: data.workspaceId,
288
+ channelId: data.channelId,
289
+ threadId: data.threadId,
290
+ commentId: data.id,
291
+ }),
292
+ }));
293
+ exports.WorkspaceUserSchema = exports.BaseUserSchema.extend({
294
+ email: zod_1.z.string().nullable().optional(),
295
+ userType: zod_1.z.enum(enums_1.USER_TYPES),
296
+ dateFormat: zod_1.z.string().nullable().optional(),
297
+ theme: zod_1.z.number().int().nullable().optional(),
298
+ timeFormat: zod_1.z.string().nullable().optional(),
299
+ version: zod_1.z.number(),
300
+ });
301
+ // ConversationMessage entity from API. `id` is widened to `string | number`
302
+ // (coerced to a string post-parse) because the backend currently emits
303
+ // either shape depending on the endpoint; the URL/reaction helpers accept
304
+ // both.
305
+ exports.ConversationMessageSchema = zod_1.z
306
+ .object({
307
+ id: zod_1.z.union([zod_1.z.string(), zod_1.z.number()]).transform(String),
308
+ content: zod_1.z.string(),
309
+ creator: zod_1.z.number(),
310
+ conversationId: zod_1.z.string(),
311
+ posted: zod_1.z.date(),
312
+ systemMessage: exports.SystemMessageSchema,
313
+ attachments: zod_1.z.array(exports.AttachmentSchema).nullable().optional(),
314
+ reactions: zod_1.z.record(zod_1.z.string(), zod_1.z.array(zod_1.z.number())).nullable().optional(),
315
+ actions: zod_1.z.array(zod_1.z.unknown()).nullable().optional(),
316
+ objIndex: zod_1.z.number().nullable().optional(),
317
+ lastEdited: zod_1.z.date().nullable().optional(),
318
+ isDeleted: zod_1.z.boolean().nullable().optional(),
319
+ directGroupMentions: zod_1.z.array(zod_1.z.string()).nullable().optional(),
320
+ directMentions: zod_1.z.array(zod_1.z.number()).nullable().optional(),
321
+ version: zod_1.z.number().nullable().optional(),
322
+ workspaceId: zod_1.z.number(),
323
+ })
324
+ .transform((data) => ({
325
+ ...data,
326
+ url: (0, url_helpers_1.getFullCommsURL)({
327
+ workspaceId: data.workspaceId,
328
+ conversationId: data.conversationId,
329
+ messageId: data.id,
330
+ }),
331
+ }));
332
+ // InboxThread entity from API - returns full Thread objects with additional inbox metadata.
333
+ exports.InboxThreadSchema = zod_1.z
334
+ .object({
335
+ id: zod_1.z.string(),
336
+ title: zod_1.z.string(),
337
+ content: zod_1.z.string(),
338
+ creator: zod_1.z.number(),
339
+ creatorName: zod_1.z.string().nullable().optional(),
340
+ channelId: zod_1.z.string(),
341
+ workspaceId: zod_1.z.number(),
342
+ actions: zod_1.z.array(zod_1.z.unknown()).nullable().optional(),
343
+ attachments: zod_1.z.array(exports.AttachmentSchema).nullable().optional(),
344
+ commentCount: zod_1.z.number(),
345
+ directGroupMentions: zod_1.z.array(zod_1.z.string()).nullable().optional(),
346
+ directMentions: zod_1.z.array(zod_1.z.number()).nullable().optional(),
347
+ groups: zod_1.z.array(zod_1.z.string()).nullable().optional(),
348
+ lastEdited: zod_1.z.date().nullable().optional(),
349
+ lastObjIndex: zod_1.z.number().nullable().optional(),
350
+ lastUpdated: zod_1.z.date(),
351
+ mutedUntil: zod_1.z.date().nullable().optional(),
352
+ participants: zod_1.z.array(zod_1.z.number()).nullable().optional(),
353
+ // Backend wire shape only includes `pinned_ts` (epoch ms or null);
354
+ // derive `pinned` from `pinnedTs != null` if you need a bool.
355
+ pinned: zod_1.z.boolean().optional(),
356
+ pinnedTs: zod_1.z.number().int().nullable().optional(),
357
+ posted: zod_1.z.date(),
358
+ reactions: zod_1.z.record(zod_1.z.string(), zod_1.z.array(zod_1.z.number())).nullable().optional(),
359
+ recipients: zod_1.z.array(zod_1.z.number()).nullable().optional(),
360
+ snippet: zod_1.z.string(),
361
+ snippetCreator: zod_1.z.number(),
362
+ snippetMaskAvatarUrl: zod_1.z.string().nullable().optional(),
363
+ snippetMaskPoster: zod_1.z.string().nullable().optional(),
364
+ systemMessage: exports.SystemMessageSchema,
365
+ isArchived: zod_1.z.boolean(),
366
+ inInbox: zod_1.z.boolean(),
367
+ isSaved: zod_1.z.boolean().nullable().optional(),
368
+ closed: zod_1.z.boolean(),
369
+ responders: zod_1.z.array(zod_1.z.number()).nullable().optional(),
370
+ lastComment: exports.CommentSchema.nullable().optional(),
371
+ toEmails: zod_1.z.array(zod_1.z.string()).nullable().optional(),
372
+ version: zod_1.z.number().nullable().optional(),
373
+ })
374
+ .transform((data) => ({
375
+ ...data,
376
+ url: (0, url_helpers_1.getFullCommsURL)({
377
+ workspaceId: data.workspaceId,
378
+ channelId: data.channelId,
379
+ threadId: data.id,
380
+ }),
381
+ }));
382
+ // UnreadThread entity from API - simplified thread reference.
383
+ exports.UnreadThreadSchema = zod_1.z.object({
384
+ threadId: zod_1.z.string(),
385
+ channelId: zod_1.z.string(),
386
+ objIndex: zod_1.z.number(),
387
+ directMention: zod_1.z.boolean(),
388
+ });
389
+ // UnreadConversation entity from API - simplified conversation reference.
390
+ exports.UnreadConversationSchema = zod_1.z.object({
391
+ conversationId: zod_1.z.string(),
392
+ objIndex: zod_1.z.number(),
393
+ directMention: zod_1.z.boolean(),
394
+ });
395
+ // SearchResult entity from API.
396
+ exports.SEARCH_RESULT_TYPES = ['thread', 'comment', 'message', 'conversation'];
397
+ exports.SearchResultSchema = zod_1.z.object({
398
+ id: zod_1.z.string(),
399
+ type: zod_1.z.enum(exports.SEARCH_RESULT_TYPES),
400
+ snippet: zod_1.z.string(),
401
+ snippetCreatorId: zod_1.z.number(),
402
+ snippetLastUpdated: zod_1.z.date(),
403
+ threadId: zod_1.z.string().nullable().optional(),
404
+ conversationId: zod_1.z.string().nullable().optional(),
405
+ commentId: zod_1.z.string().nullable().optional(),
406
+ channelId: zod_1.z.string().nullable().optional(),
407
+ channelName: zod_1.z.string().nullable().optional(),
408
+ channelColor: zod_1.z.number().nullable().optional(),
409
+ title: zod_1.z.string().nullable().optional(),
410
+ closed: zod_1.z.boolean().nullable().optional(),
411
+ });
@@ -0,0 +1,37 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.NOTIFY_AUDIENCE_GROUP_IDS = exports.NOTIFY_AUDIENCES = exports.WORKSPACE_PLANS = exports.USER_TYPES = exports.GROUP_ID_MARKERS = exports.EVERYONE_IN_THREAD = exports.EVERYONE = void 0;
4
+ /**
5
+ * Marker constants for the two "broadcast" group recipients. These appear
6
+ * in group-bearing fields (`Thread.groups`, `Comment.groups`,
7
+ * `Channel.defaultGroups`, `directGroupMentions`, etc.) in place of a
8
+ * real group ID and tell the backend to notify "everyone in the channel"
9
+ * or "everyone in the thread" respectively. Input and output are
10
+ * symmetric. Defined here (and not in `./entities`) so that `enums`
11
+ * stays leaf-level — `entities` imports from `enums`, never the reverse.
12
+ */
13
+ exports.EVERYONE = 'EVERYONE';
14
+ exports.EVERYONE_IN_THREAD = 'EVERYONE_IN_THREAD';
15
+ /** Union of the two broadcast group markers. */
16
+ exports.GROUP_ID_MARKERS = [exports.EVERYONE, exports.EVERYONE_IN_THREAD];
17
+ // User types for workspace users
18
+ exports.USER_TYPES = ['USER', 'GUEST', 'ADMIN'];
19
+ // Workspace plans. The known values today are `'free'`, `'unlimited'`,
20
+ // and `'business'`, but the backend can introduce new plan names without
21
+ // coordinating a SDK release — so the schema accepts any string and the
22
+ // const array stays as a hint for autocomplete only.
23
+ exports.WORKSPACE_PLANS = ['free', 'unlimited', 'business'];
24
+ // Audiences that comment-creating endpoints can target alongside (or instead
25
+ // of) individual `recipients` / custom `groups`.
26
+ exports.NOTIFY_AUDIENCES = ['channel', 'thread'];
27
+ /**
28
+ * Internal mapping from {@link NotifyAudience} to the broadcast marker IDs
29
+ * (`EVERYONE` / `EVERYONE_IN_THREAD`) that comment- and thread-creation
30
+ * endpoints use on the wire. SDK consumers should use {@link NotifyAudience}
31
+ * via `notifyAudience` on the request args rather than passing these IDs
32
+ * directly.
33
+ */
34
+ exports.NOTIFY_AUDIENCE_GROUP_IDS = {
35
+ channel: exports.EVERYONE,
36
+ thread: exports.EVERYONE_IN_THREAD,
37
+ };
@@ -0,0 +1,12 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.CommsRequestError = void 0;
4
+ const ts_custom_error_1 = require("ts-custom-error");
5
+ class CommsRequestError extends ts_custom_error_1.CustomError {
6
+ constructor(message, httpStatusCode, responseData) {
7
+ super(message);
8
+ this.httpStatusCode = httpStatusCode;
9
+ this.responseData = responseData;
10
+ }
11
+ }
12
+ exports.CommsRequestError = CommsRequestError;
@@ -0,0 +1,4 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.HTTP_METHODS = void 0;
4
+ exports.HTTP_METHODS = ['POST', 'GET', 'PUT', 'PATCH', 'DELETE'];
@@ -0,0 +1,22 @@
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("./api-version"), exports);
18
+ __exportStar(require("./entities"), exports);
19
+ __exportStar(require("./enums"), exports);
20
+ __exportStar(require("./errors"), exports);
21
+ __exportStar(require("./http"), exports);
22
+ __exportStar(require("./requests"), exports);
@@ -0,0 +1,116 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.THREAD_ACTIONS = 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
+ });
46
+ exports.UpdateThreadArgsSchema = zod_1.z.object({
47
+ id: zod_1.z.string(),
48
+ title: zod_1.z.string().nullable().optional(),
49
+ content: zod_1.z.string().nullable().optional(),
50
+ });
51
+ exports.CreateCommentArgsSchema = zod_1.z.object({
52
+ threadId: zod_1.z.string(),
53
+ content: zod_1.z.string(),
54
+ id: zod_1.z.string().optional(),
55
+ attachments: zod_1.z.array(entities_1.AttachmentSchema).nullable().optional(),
56
+ actions: zod_1.z.unknown().nullable().optional(),
57
+ recipients: zod_1.z.array(zod_1.z.number()).nullable().optional(),
58
+ groups: zod_1.z.array(zod_1.z.string()).nullable().optional(),
59
+ directMentions: zod_1.z.array(zod_1.z.number()).nullable().optional(),
60
+ directGroupMentions: zod_1.z.array(zod_1.z.string()).nullable().optional(),
61
+ notifyAudience: zod_1.z.enum(enums_1.NOTIFY_AUDIENCES).nullable().optional(),
62
+ });
63
+ exports.UpdateCommentArgsSchema = zod_1.z.object({
64
+ id: zod_1.z.string(),
65
+ content: zod_1.z.string(),
66
+ });
67
+ exports.CreateConversationArgsSchema = zod_1.z.object({
68
+ workspaceId: zod_1.z.number(),
69
+ recipients: zod_1.z.array(zod_1.z.number()),
70
+ id: zod_1.z.string().optional(),
71
+ title: zod_1.z.string().nullable().optional(),
72
+ });
73
+ exports.CreateMessageArgsSchema = zod_1.z
74
+ .object({
75
+ conversationId: zod_1.z.string().nullable().optional(),
76
+ threadId: zod_1.z.string().nullable().optional(),
77
+ content: zod_1.z.string(),
78
+ id: zod_1.z.string().optional(),
79
+ attachments: zod_1.z.array(entities_1.AttachmentSchema).nullable().optional(),
80
+ })
81
+ .refine((data) => {
82
+ return ((data.conversationId && !data.threadId) || (!data.conversationId && data.threadId));
83
+ }, {
84
+ message: 'Exactly one of conversationId or threadId must be provided',
85
+ });
86
+ exports.GetChannelsArgsSchema = zod_1.z.object({
87
+ workspaceId: zod_1.z.number(),
88
+ archived: zod_1.z.boolean().nullable().optional(),
89
+ });
90
+ exports.GetThreadsArgsSchema = zod_1.z.object({
91
+ workspaceId: zod_1.z.number(),
92
+ channelId: zod_1.z.string().nullable().optional(),
93
+ archived: zod_1.z.boolean().nullable().optional(),
94
+ newerThan: zod_1.z.date().nullable().optional(),
95
+ olderThan: zod_1.z.date().nullable().optional(),
96
+ limit: zod_1.z.number().nullable().optional(),
97
+ });
98
+ exports.GetCommentsArgsSchema = zod_1.z.object({
99
+ threadId: zod_1.z.string(),
100
+ newerThan: zod_1.z.date().nullable().optional(),
101
+ olderThan: zod_1.z.date().nullable().optional(),
102
+ limit: zod_1.z.number().nullable().optional(),
103
+ });
104
+ exports.GetConversationsArgsSchema = zod_1.z.object({
105
+ workspaceId: zod_1.z.number(),
106
+ archived: zod_1.z.boolean().nullable().optional(),
107
+ });
108
+ exports.GetOrCreateConversationArgsSchema = zod_1.z.object({
109
+ workspaceId: zod_1.z.number(),
110
+ userIds: zod_1.z.array(zod_1.z.number()),
111
+ id: zod_1.z.string().optional(),
112
+ });
113
+ // Inbox
114
+ exports.ARCHIVE_FILTER_VALUES = ['active', 'archived', 'all'];
115
+ // Threads
116
+ exports.THREAD_ACTIONS = ['close', 'reopen'];
@@ -0,0 +1,54 @@
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
+ }
@@ -0,0 +1,19 @@
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);