@doist/comms-sdk 0.7.1 → 0.8.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 +2 -32
- package/dist/cjs/clients/notify-audience.js +45 -0
- package/dist/cjs/clients/threads-client.js +9 -1
- package/dist/cjs/types/requests.js +1 -0
- package/dist/esm/clients/add-comment-helper.js +1 -31
- package/dist/esm/clients/notify-audience.js +42 -0
- package/dist/esm/clients/threads-client.js +9 -1
- package/dist/esm/types/requests.js +1 -0
- package/dist/types/clients/notify-audience.d.ts +22 -0
- package/dist/types/clients/threads-client.d.ts +6 -0
- package/dist/types/types/requests.d.ts +4 -0
- package/package.json +1 -1
|
@@ -3,38 +3,8 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.addCommentRequest = addCommentRequest;
|
|
4
4
|
const endpoints_1 = require("../consts/endpoints");
|
|
5
5
|
const http_client_1 = require("../transport/http-client");
|
|
6
|
-
const enums_1 = require("../types/enums");
|
|
7
6
|
const uuidv7_1 = require("../utils/uuidv7");
|
|
8
|
-
const
|
|
9
|
-
function isNotifyAudience(value) {
|
|
10
|
-
return typeof value === 'string' && enums_1.NOTIFY_AUDIENCES.includes(value);
|
|
11
|
-
}
|
|
12
|
-
function collectMarkerOffenses(field, values) {
|
|
13
|
-
if (!values)
|
|
14
|
-
return null;
|
|
15
|
-
const offending = values.filter((id) => SENTINEL_GROUP_IDS.has(id));
|
|
16
|
-
return offending.length > 0 ? { field, offending } : null;
|
|
17
|
-
}
|
|
18
|
-
function applyNotifyAudience(params) {
|
|
19
|
-
const offenses = [
|
|
20
|
-
collectMarkerOffenses('groups', params.groups ?? undefined),
|
|
21
|
-
collectMarkerOffenses('directGroupMentions', params.directGroupMentions ?? undefined),
|
|
22
|
-
].filter((o) => o !== null);
|
|
23
|
-
if (offenses.length > 0) {
|
|
24
|
-
const details = offenses
|
|
25
|
-
.map(({ field, offending }) => `\`${field}\` contains ${offending.join(', ')}`)
|
|
26
|
-
.join('; ');
|
|
27
|
-
throw new Error(`Reserved broadcast marker IDs found: ${details}. Pass these via \`notifyAudience\` on createComment / closeThread / reopenThread (e.g. \`notifyAudience: 'channel'\` for EVERYONE) instead of populating \`groups\` / \`directGroupMentions\` directly.`);
|
|
28
|
-
}
|
|
29
|
-
if (params.notifyAudience == null)
|
|
30
|
-
return params;
|
|
31
|
-
if (!isNotifyAudience(params.notifyAudience)) {
|
|
32
|
-
throw new Error(`Invalid \`notifyAudience\` value "${String(params.notifyAudience)}". Expected one of: ${enums_1.NOTIFY_AUDIENCES.join(', ')}.`);
|
|
33
|
-
}
|
|
34
|
-
const sentinel = enums_1.NOTIFY_AUDIENCE_GROUP_IDS[params.notifyAudience];
|
|
35
|
-
const { notifyAudience: _stripped, groups, ...rest } = params;
|
|
36
|
-
return { ...rest, groups: [...(groups ?? []), sentinel] };
|
|
37
|
-
}
|
|
7
|
+
const notify_audience_1 = require("./notify-audience");
|
|
38
8
|
/**
|
|
39
9
|
* Internal helper that powers `comments.createComment`,
|
|
40
10
|
* `threads.closeThread`, and `threads.reopenThread`.
|
|
@@ -53,7 +23,7 @@ function applyNotifyAudience(params) {
|
|
|
53
23
|
* @returns The parsed {@link Comment} returned by the API.
|
|
54
24
|
*/
|
|
55
25
|
function addCommentRequest(context, params, options) {
|
|
56
|
-
const normalized = applyNotifyAudience(params);
|
|
26
|
+
const normalized = (0, notify_audience_1.applyNotifyAudience)(params);
|
|
57
27
|
const withId = { ...normalized, id: (0, uuidv7_1.resolveCreateId)(normalized.id) };
|
|
58
28
|
const payload = options?.threadAction
|
|
59
29
|
? { ...withId, threadAction: options.threadAction }
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.applyNotifyAudience = applyNotifyAudience;
|
|
4
|
+
const enums_1 = require("../types/enums");
|
|
5
|
+
const SENTINEL_GROUP_IDS = new Set(Object.values(enums_1.NOTIFY_AUDIENCE_GROUP_IDS));
|
|
6
|
+
function isNotifyAudience(value) {
|
|
7
|
+
return typeof value === 'string' && enums_1.NOTIFY_AUDIENCES.includes(value);
|
|
8
|
+
}
|
|
9
|
+
function collectMarkerOffenses(field, values) {
|
|
10
|
+
if (!values)
|
|
11
|
+
return null;
|
|
12
|
+
const offending = values.filter((id) => SENTINEL_GROUP_IDS.has(id));
|
|
13
|
+
return offending.length > 0 ? { field, offending } : null;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Normalizes a `notifyAudience` flag into a sentinel `groups` entry
|
|
17
|
+
* (`EVERYONE` / `EVERYONE_IN_THREAD`) and rejects callers who put those
|
|
18
|
+
* reserved markers directly into `groups` / `directGroupMentions`.
|
|
19
|
+
*
|
|
20
|
+
* When `notifyAudience` is set it is stripped and its sentinel is appended to
|
|
21
|
+
* `groups`; the backend only understands the marker in `groups`. When it is
|
|
22
|
+
* unset the params are returned unchanged, preserving any explicit
|
|
23
|
+
* `groups` / `directGroupMentions` (including a `null`) on the wire.
|
|
24
|
+
*/
|
|
25
|
+
function applyNotifyAudience(params) {
|
|
26
|
+
const offenses = [
|
|
27
|
+
collectMarkerOffenses('groups', params.groups ?? undefined),
|
|
28
|
+
collectMarkerOffenses('directGroupMentions', params.directGroupMentions ?? undefined),
|
|
29
|
+
].filter((o) => o !== null);
|
|
30
|
+
if (offenses.length > 0) {
|
|
31
|
+
const details = offenses
|
|
32
|
+
.map(({ field, offending }) => `\`${field}\` contains ${offending.join(', ')}`)
|
|
33
|
+
.join('; ');
|
|
34
|
+
throw new Error(`Reserved broadcast marker IDs found: ${details}. Pass these via \`notifyAudience\` (e.g. \`notifyAudience: 'channel'\` for EVERYONE) instead of populating \`groups\` / \`directGroupMentions\` directly.`);
|
|
35
|
+
}
|
|
36
|
+
if (params.notifyAudience == null) {
|
|
37
|
+
return params;
|
|
38
|
+
}
|
|
39
|
+
if (!isNotifyAudience(params.notifyAudience)) {
|
|
40
|
+
throw new Error(`Invalid \`notifyAudience\` value "${String(params.notifyAudience)}". Expected one of: ${enums_1.NOTIFY_AUDIENCES.join(', ')}.`);
|
|
41
|
+
}
|
|
42
|
+
const sentinel = enums_1.NOTIFY_AUDIENCE_GROUP_IDS[params.notifyAudience];
|
|
43
|
+
const { notifyAudience: _stripped, groups, ...rest } = params;
|
|
44
|
+
return { ...rest, groups: [...(groups ?? []), sentinel] };
|
|
45
|
+
}
|
|
@@ -8,6 +8,7 @@ const entities_1 = require("../types/entities");
|
|
|
8
8
|
const uuidv7_1 = require("../utils/uuidv7");
|
|
9
9
|
const add_comment_helper_1 = require("./add-comment-helper");
|
|
10
10
|
const base_client_1 = require("./base-client");
|
|
11
|
+
const notify_audience_1 = require("./notify-audience");
|
|
11
12
|
exports.ThreadListSchema = zod_1.z.array(entities_1.ThreadSchema);
|
|
12
13
|
const GetUnreadResponseSchema = zod_1.z.object({
|
|
13
14
|
data: zod_1.z.array(entities_1.UnreadThreadSchema),
|
|
@@ -95,6 +96,11 @@ class ThreadsClient extends base_client_1.BaseClient {
|
|
|
95
96
|
* @param args.content - The thread content.
|
|
96
97
|
* @param args.recipients - Optional array of user IDs to notify.
|
|
97
98
|
* @param args.groups - Optional array of custom group IDs to notify.
|
|
99
|
+
* @param args.notifyAudience - Optional broader audience to notify in addition to
|
|
100
|
+
* `recipients` and `groups`. `'channel'` notifies everyone in the channel;
|
|
101
|
+
* `'thread'` notifies everyone who has interacted with the thread — but a
|
|
102
|
+
* brand-new thread has no interactions yet, so the backend discards
|
|
103
|
+
* `'thread'` at create time. It is only meaningful on replies (`createComment`).
|
|
98
104
|
* @param args.attachments - Optional array of {@link Attachment}s (from `attachments.upload`).
|
|
99
105
|
* @returns The created thread object.
|
|
100
106
|
*
|
|
@@ -104,11 +110,13 @@ class ThreadsClient extends base_client_1.BaseClient {
|
|
|
104
110
|
* channelId: '7YpL3oZ4kZ9vP7Q1tR2sX44',
|
|
105
111
|
* title: 'New Feature Discussion',
|
|
106
112
|
* content: 'Let\'s discuss the new feature...',
|
|
113
|
+
* notifyAudience: 'channel', // tag "Everyone in channel"
|
|
107
114
|
* })
|
|
108
115
|
* ```
|
|
109
116
|
*/
|
|
110
117
|
createThread(args) {
|
|
111
|
-
|
|
118
|
+
const normalized = (0, notify_audience_1.applyNotifyAudience)(args);
|
|
119
|
+
return this.simple('POST', 'add', { ...normalized, id: (0, uuidv7_1.resolveCreateId)(args.id) }, this.threadSchema);
|
|
112
120
|
}
|
|
113
121
|
/**
|
|
114
122
|
* Partial update of an existing thread.
|
|
@@ -42,6 +42,7 @@ exports.CreateThreadArgsSchema = zod_1.z.object({
|
|
|
42
42
|
id: zod_1.z.string().optional(),
|
|
43
43
|
recipients: zod_1.z.array(zod_1.z.number()).nullable().optional(),
|
|
44
44
|
groups: zod_1.z.array(zod_1.z.string()).nullable().optional(),
|
|
45
|
+
notifyAudience: zod_1.z.enum(enums_1.NOTIFY_AUDIENCES).nullable().optional(),
|
|
45
46
|
attachments: zod_1.z.array(entities_1.RequestAttachmentSchema).nullable().optional(),
|
|
46
47
|
});
|
|
47
48
|
exports.UpdateThreadArgsSchema = zod_1.z.object({
|
|
@@ -1,37 +1,7 @@
|
|
|
1
1
|
import { ENDPOINT_COMMENTS } from '../consts/endpoints.js';
|
|
2
2
|
import { request } from '../transport/http-client.js';
|
|
3
|
-
import { NOTIFY_AUDIENCE_GROUP_IDS, NOTIFY_AUDIENCES } from '../types/enums.js';
|
|
4
3
|
import { resolveCreateId } from '../utils/uuidv7.js';
|
|
5
|
-
|
|
6
|
-
function isNotifyAudience(value) {
|
|
7
|
-
return typeof value === 'string' && NOTIFY_AUDIENCES.includes(value);
|
|
8
|
-
}
|
|
9
|
-
function collectMarkerOffenses(field, values) {
|
|
10
|
-
if (!values)
|
|
11
|
-
return null;
|
|
12
|
-
const offending = values.filter((id) => SENTINEL_GROUP_IDS.has(id));
|
|
13
|
-
return offending.length > 0 ? { field, offending } : null;
|
|
14
|
-
}
|
|
15
|
-
function applyNotifyAudience(params) {
|
|
16
|
-
const offenses = [
|
|
17
|
-
collectMarkerOffenses('groups', params.groups ?? undefined),
|
|
18
|
-
collectMarkerOffenses('directGroupMentions', params.directGroupMentions ?? undefined),
|
|
19
|
-
].filter((o) => o !== null);
|
|
20
|
-
if (offenses.length > 0) {
|
|
21
|
-
const details = offenses
|
|
22
|
-
.map(({ field, offending }) => `\`${field}\` contains ${offending.join(', ')}`)
|
|
23
|
-
.join('; ');
|
|
24
|
-
throw new Error(`Reserved broadcast marker IDs found: ${details}. Pass these via \`notifyAudience\` on createComment / closeThread / reopenThread (e.g. \`notifyAudience: 'channel'\` for EVERYONE) instead of populating \`groups\` / \`directGroupMentions\` directly.`);
|
|
25
|
-
}
|
|
26
|
-
if (params.notifyAudience == null)
|
|
27
|
-
return params;
|
|
28
|
-
if (!isNotifyAudience(params.notifyAudience)) {
|
|
29
|
-
throw new Error(`Invalid \`notifyAudience\` value "${String(params.notifyAudience)}". Expected one of: ${NOTIFY_AUDIENCES.join(', ')}.`);
|
|
30
|
-
}
|
|
31
|
-
const sentinel = NOTIFY_AUDIENCE_GROUP_IDS[params.notifyAudience];
|
|
32
|
-
const { notifyAudience: _stripped, groups, ...rest } = params;
|
|
33
|
-
return { ...rest, groups: [...(groups ?? []), sentinel] };
|
|
34
|
-
}
|
|
4
|
+
import { applyNotifyAudience } from './notify-audience.js';
|
|
35
5
|
/**
|
|
36
6
|
* Internal helper that powers `comments.createComment`,
|
|
37
7
|
* `threads.closeThread`, and `threads.reopenThread`.
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { NOTIFY_AUDIENCE_GROUP_IDS, NOTIFY_AUDIENCES } from '../types/enums.js';
|
|
2
|
+
const SENTINEL_GROUP_IDS = new Set(Object.values(NOTIFY_AUDIENCE_GROUP_IDS));
|
|
3
|
+
function isNotifyAudience(value) {
|
|
4
|
+
return typeof value === 'string' && NOTIFY_AUDIENCES.includes(value);
|
|
5
|
+
}
|
|
6
|
+
function collectMarkerOffenses(field, values) {
|
|
7
|
+
if (!values)
|
|
8
|
+
return null;
|
|
9
|
+
const offending = values.filter((id) => SENTINEL_GROUP_IDS.has(id));
|
|
10
|
+
return offending.length > 0 ? { field, offending } : null;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Normalizes a `notifyAudience` flag into a sentinel `groups` entry
|
|
14
|
+
* (`EVERYONE` / `EVERYONE_IN_THREAD`) and rejects callers who put those
|
|
15
|
+
* reserved markers directly into `groups` / `directGroupMentions`.
|
|
16
|
+
*
|
|
17
|
+
* When `notifyAudience` is set it is stripped and its sentinel is appended to
|
|
18
|
+
* `groups`; the backend only understands the marker in `groups`. When it is
|
|
19
|
+
* unset the params are returned unchanged, preserving any explicit
|
|
20
|
+
* `groups` / `directGroupMentions` (including a `null`) on the wire.
|
|
21
|
+
*/
|
|
22
|
+
export function applyNotifyAudience(params) {
|
|
23
|
+
const offenses = [
|
|
24
|
+
collectMarkerOffenses('groups', params.groups ?? undefined),
|
|
25
|
+
collectMarkerOffenses('directGroupMentions', params.directGroupMentions ?? undefined),
|
|
26
|
+
].filter((o) => o !== null);
|
|
27
|
+
if (offenses.length > 0) {
|
|
28
|
+
const details = offenses
|
|
29
|
+
.map(({ field, offending }) => `\`${field}\` contains ${offending.join(', ')}`)
|
|
30
|
+
.join('; ');
|
|
31
|
+
throw new Error(`Reserved broadcast marker IDs found: ${details}. Pass these via \`notifyAudience\` (e.g. \`notifyAudience: 'channel'\` for EVERYONE) instead of populating \`groups\` / \`directGroupMentions\` directly.`);
|
|
32
|
+
}
|
|
33
|
+
if (params.notifyAudience == null) {
|
|
34
|
+
return params;
|
|
35
|
+
}
|
|
36
|
+
if (!isNotifyAudience(params.notifyAudience)) {
|
|
37
|
+
throw new Error(`Invalid \`notifyAudience\` value "${String(params.notifyAudience)}". Expected one of: ${NOTIFY_AUDIENCES.join(', ')}.`);
|
|
38
|
+
}
|
|
39
|
+
const sentinel = NOTIFY_AUDIENCE_GROUP_IDS[params.notifyAudience];
|
|
40
|
+
const { notifyAudience: _stripped, groups, ...rest } = params;
|
|
41
|
+
return { ...rest, groups: [...(groups ?? []), sentinel] };
|
|
42
|
+
}
|
|
@@ -5,6 +5,7 @@ import { CommentSchema, createCommentSchema, createThreadSchema, StatusOkSchema,
|
|
|
5
5
|
import { resolveCreateId } from '../utils/uuidv7.js';
|
|
6
6
|
import { addCommentRequest } from './add-comment-helper.js';
|
|
7
7
|
import { BaseClient } from './base-client.js';
|
|
8
|
+
import { applyNotifyAudience } from './notify-audience.js';
|
|
8
9
|
export const ThreadListSchema = z.array(ThreadSchema);
|
|
9
10
|
const GetUnreadResponseSchema = z.object({
|
|
10
11
|
data: z.array(UnreadThreadSchema),
|
|
@@ -92,6 +93,11 @@ export class ThreadsClient extends BaseClient {
|
|
|
92
93
|
* @param args.content - The thread content.
|
|
93
94
|
* @param args.recipients - Optional array of user IDs to notify.
|
|
94
95
|
* @param args.groups - Optional array of custom group IDs to notify.
|
|
96
|
+
* @param args.notifyAudience - Optional broader audience to notify in addition to
|
|
97
|
+
* `recipients` and `groups`. `'channel'` notifies everyone in the channel;
|
|
98
|
+
* `'thread'` notifies everyone who has interacted with the thread — but a
|
|
99
|
+
* brand-new thread has no interactions yet, so the backend discards
|
|
100
|
+
* `'thread'` at create time. It is only meaningful on replies (`createComment`).
|
|
95
101
|
* @param args.attachments - Optional array of {@link Attachment}s (from `attachments.upload`).
|
|
96
102
|
* @returns The created thread object.
|
|
97
103
|
*
|
|
@@ -101,11 +107,13 @@ export class ThreadsClient extends BaseClient {
|
|
|
101
107
|
* channelId: '7YpL3oZ4kZ9vP7Q1tR2sX44',
|
|
102
108
|
* title: 'New Feature Discussion',
|
|
103
109
|
* content: 'Let\'s discuss the new feature...',
|
|
110
|
+
* notifyAudience: 'channel', // tag "Everyone in channel"
|
|
104
111
|
* })
|
|
105
112
|
* ```
|
|
106
113
|
*/
|
|
107
114
|
createThread(args) {
|
|
108
|
-
|
|
115
|
+
const normalized = applyNotifyAudience(args);
|
|
116
|
+
return this.simple('POST', 'add', { ...normalized, id: resolveCreateId(args.id) }, this.threadSchema);
|
|
109
117
|
}
|
|
110
118
|
/**
|
|
111
119
|
* Partial update of an existing thread.
|
|
@@ -39,6 +39,7 @@ export const CreateThreadArgsSchema = z.object({
|
|
|
39
39
|
id: z.string().optional(),
|
|
40
40
|
recipients: z.array(z.number()).nullable().optional(),
|
|
41
41
|
groups: z.array(z.string()).nullable().optional(),
|
|
42
|
+
notifyAudience: z.enum(NOTIFY_AUDIENCES).nullable().optional(),
|
|
42
43
|
attachments: z.array(RequestAttachmentSchema).nullable().optional(),
|
|
43
44
|
});
|
|
44
45
|
export const UpdateThreadArgsSchema = z.object({
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { type NotifyAudience } from '../types/enums.js';
|
|
2
|
+
/**
|
|
3
|
+
* Params bearing the group-targeting fields that can carry a `notifyAudience`.
|
|
4
|
+
* Shared by the comment-creating endpoints and thread creation.
|
|
5
|
+
*/
|
|
6
|
+
type NotifyAudienceParams = {
|
|
7
|
+
groups?: string[] | null;
|
|
8
|
+
directGroupMentions?: string[] | null;
|
|
9
|
+
notifyAudience?: NotifyAudience | null;
|
|
10
|
+
};
|
|
11
|
+
/**
|
|
12
|
+
* Normalizes a `notifyAudience` flag into a sentinel `groups` entry
|
|
13
|
+
* (`EVERYONE` / `EVERYONE_IN_THREAD`) and rejects callers who put those
|
|
14
|
+
* reserved markers directly into `groups` / `directGroupMentions`.
|
|
15
|
+
*
|
|
16
|
+
* When `notifyAudience` is set it is stripped and its sentinel is appended to
|
|
17
|
+
* `groups`; the backend only understands the marker in `groups`. When it is
|
|
18
|
+
* unset the params are returned unchanged, preserving any explicit
|
|
19
|
+
* `groups` / `directGroupMentions` (including a `null`) on the wire.
|
|
20
|
+
*/
|
|
21
|
+
export declare function applyNotifyAudience<T extends NotifyAudienceParams>(params: T): Omit<T, 'notifyAudience'>;
|
|
22
|
+
export {};
|
|
@@ -336,6 +336,11 @@ export declare class ThreadsClient extends BaseClient {
|
|
|
336
336
|
* @param args.content - The thread content.
|
|
337
337
|
* @param args.recipients - Optional array of user IDs to notify.
|
|
338
338
|
* @param args.groups - Optional array of custom group IDs to notify.
|
|
339
|
+
* @param args.notifyAudience - Optional broader audience to notify in addition to
|
|
340
|
+
* `recipients` and `groups`. `'channel'` notifies everyone in the channel;
|
|
341
|
+
* `'thread'` notifies everyone who has interacted with the thread — but a
|
|
342
|
+
* brand-new thread has no interactions yet, so the backend discards
|
|
343
|
+
* `'thread'` at create time. It is only meaningful on replies (`createComment`).
|
|
339
344
|
* @param args.attachments - Optional array of {@link Attachment}s (from `attachments.upload`).
|
|
340
345
|
* @returns The created thread object.
|
|
341
346
|
*
|
|
@@ -345,6 +350,7 @@ export declare class ThreadsClient extends BaseClient {
|
|
|
345
350
|
* channelId: '7YpL3oZ4kZ9vP7Q1tR2sX44',
|
|
346
351
|
* title: 'New Feature Discussion',
|
|
347
352
|
* content: 'Let\'s discuss the new feature...',
|
|
353
|
+
* notifyAudience: 'channel', // tag "Everyone in channel"
|
|
348
354
|
* })
|
|
349
355
|
* ```
|
|
350
356
|
*/
|
|
@@ -40,6 +40,10 @@ export declare const CreateThreadArgsSchema: z.ZodObject<{
|
|
|
40
40
|
id: z.ZodOptional<z.ZodString>;
|
|
41
41
|
recipients: z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodNumber>>>;
|
|
42
42
|
groups: z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodString>>>;
|
|
43
|
+
notifyAudience: z.ZodOptional<z.ZodNullable<z.ZodEnum<{
|
|
44
|
+
channel: "channel";
|
|
45
|
+
thread: "thread";
|
|
46
|
+
}>>>;
|
|
43
47
|
attachments: z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodObject<{
|
|
44
48
|
attachmentId: z.ZodString;
|
|
45
49
|
urlType: z.ZodString;
|