genesys-cloud-streaming-client 19.3.1 → 19.4.0-release.2
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/README.md +3 -0
- package/dist/cjs/client.js +1 -1
- package/dist/cjs/index.d.ts +1 -1
- package/dist/cjs/index.js +2 -1
- package/dist/cjs/notifications.d.ts +26 -7
- package/dist/cjs/notifications.js +60 -9
- package/dist/cjs/types/genesys-cloud-media-session.js +2 -1
- package/dist/cjs/types/interfaces.d.ts +2 -0
- package/dist/cjs/utils.d.ts +6 -0
- package/dist/cjs/utils.js +10 -1
- package/dist/deploy-info.json +3 -3
- package/dist/es/client.js +1 -1
- package/dist/es/index.bundle.js +87 -28
- package/dist/es/index.d.ts +1 -1
- package/dist/es/index.js +1 -1
- package/dist/es/notifications.d.ts +26 -7
- package/dist/es/notifications.js +76 -24
- package/dist/es/types/genesys-cloud-media-session.js +2 -1
- package/dist/es/types/interfaces.d.ts +2 -0
- package/dist/es/utils.d.ts +6 -0
- package/dist/es/utils.js +8 -0
- package/dist/manifest.json +3 -3
- package/dist/npm/CHANGELOG.md +9 -1
- package/dist/npm/client.js +1 -1
- package/dist/npm/index.d.ts +1 -1
- package/dist/npm/index.js +2 -1
- package/dist/npm/module.js +1 -1
- package/dist/npm/notifications.d.ts +26 -7
- package/dist/npm/notifications.js +60 -9
- package/dist/npm/types/genesys-cloud-media-session.js +2 -1
- package/dist/npm/types/interfaces.d.ts +2 -0
- package/dist/npm/utils.d.ts +6 -0
- package/dist/npm/utils.js +10 -1
- package/dist/streaming-client.browser.js +6 -6
- package/dist/v19/streaming-client.browser.js +6 -6
- package/dist/v19.4.0/streaming-client.browser.js +19 -0
- package/package.json +3 -1
- package/dist/v19.3.1/streaming-client.browser.js +0 -19
package/README.md
CHANGED
|
@@ -2,6 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
This project is a Bitbucket repository that contains the pipeline infrastructure for the open source [Genesys Cloud Streaming Client](https://github.com/purecloudlabs/genesys-cloud-streaming-client) hosted on GitHub.
|
|
4
4
|
|
|
5
|
+
### Playbook
|
|
6
|
+
See [docs/playbook.md](docs/playbook.md).
|
|
7
|
+
|
|
5
8
|
### What is this repository for?
|
|
6
9
|
|
|
7
10
|
Current guidance from security and the CI/CD teams is to not have the pipeline infrastructure available in open source repositories. This repository is used to host the pipeline infrastructure for the Genesys Cloud Streaming Client so that we may retain access to the CDN and ability to publish to NPM.
|
package/dist/cjs/client.js
CHANGED
package/dist/cjs/index.d.ts
CHANGED
|
@@ -6,5 +6,5 @@ export * from './types/media-session';
|
|
|
6
6
|
export * from './types/interfaces';
|
|
7
7
|
export * from './messenger';
|
|
8
8
|
export { HttpClient } from './http-client';
|
|
9
|
-
export { StreamingClientError, parseJwt } from './utils';
|
|
9
|
+
export { StreamingClientError, StreamingSubscriptionError, parseJwt } from './utils';
|
|
10
10
|
export default Client;
|
package/dist/cjs/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.parseJwt = exports.StreamingClientError = exports.HttpClient = void 0;
|
|
3
|
+
exports.parseJwt = exports.StreamingSubscriptionError = exports.StreamingClientError = exports.HttpClient = void 0;
|
|
4
4
|
const tslib_1 = require("tslib");
|
|
5
5
|
/// <reference path="types/libs.ts" />
|
|
6
6
|
const client_1 = require("./client");
|
|
@@ -13,5 +13,6 @@ var http_client_1 = require("./http-client");
|
|
|
13
13
|
Object.defineProperty(exports, "HttpClient", { enumerable: true, get: function () { return http_client_1.HttpClient; } });
|
|
14
14
|
var utils_1 = require("./utils");
|
|
15
15
|
Object.defineProperty(exports, "StreamingClientError", { enumerable: true, get: function () { return utils_1.StreamingClientError; } });
|
|
16
|
+
Object.defineProperty(exports, "StreamingSubscriptionError", { enumerable: true, get: function () { return utils_1.StreamingSubscriptionError; } });
|
|
16
17
|
Object.defineProperty(exports, "parseJwt", { enumerable: true, get: function () { return utils_1.parseJwt; } });
|
|
17
18
|
exports.default = client_1.Client;
|
|
@@ -1,15 +1,17 @@
|
|
|
1
1
|
import { PubsubEvent, PubsubSubscription, PubsubSubscriptionWithOptions } from 'stanza/protocol';
|
|
2
2
|
import { Client } from './client';
|
|
3
|
-
import { StreamingClientExtension } from './types/interfaces';
|
|
3
|
+
import { IClientOptions, StreamingClientExtension } from './types/interfaces';
|
|
4
4
|
import { NamedAgent } from './types/named-agent';
|
|
5
|
+
import { AxiosResponse } from 'axios';
|
|
5
6
|
export declare class Notifications implements StreamingClientExtension {
|
|
6
7
|
client: Client;
|
|
7
8
|
stanzaInstance?: NamedAgent;
|
|
8
9
|
subscriptions: any;
|
|
9
10
|
bulkSubscriptions: any;
|
|
10
11
|
topicPriorities: any;
|
|
11
|
-
debouncedResubscribe:
|
|
12
|
-
|
|
12
|
+
debouncedResubscribe: () => Promise<BulkSubscribeResult>;
|
|
13
|
+
enablePartialBulkResubscribe: boolean;
|
|
14
|
+
constructor(client: any, options?: IClientOptions);
|
|
13
15
|
get pubsubHost(): string;
|
|
14
16
|
handleStanzaInstanceChange(stanza: NamedAgent): void;
|
|
15
17
|
topicHandlers(topic: string): Array<(obj?: any) => void>;
|
|
@@ -32,23 +34,23 @@ export declare class Notifications implements StreamingClientExtension {
|
|
|
32
34
|
}>): Array<{
|
|
33
35
|
id: string;
|
|
34
36
|
}>;
|
|
35
|
-
makeBulkSubscribeRequest(topics: string[], options: any): Promise<
|
|
37
|
+
makeBulkSubscribeRequest(topics: string[], options: any): Promise<AxiosResponse<ChannelTopicsEntityListing>>;
|
|
36
38
|
createSubscription(topic: string, handler: (obj?: any) => void): void;
|
|
37
39
|
removeSubscription(topic: string, handler: (obj?: any) => void): void;
|
|
38
40
|
removeTopicPriority(topic: string): void;
|
|
39
41
|
getActiveIndividualTopics(): string[];
|
|
40
|
-
resubscribe(): Promise<
|
|
42
|
+
resubscribe(): Promise<BulkSubscribeResult>;
|
|
41
43
|
subscriptionsKeepAlive(): void;
|
|
42
44
|
getTopicParts(topic: string): {
|
|
43
45
|
prefix: string;
|
|
44
46
|
postfixes: string[];
|
|
45
47
|
};
|
|
46
48
|
setTopicPriorities(priorities?: {}): void;
|
|
47
|
-
subscribe(topic: string, handler?: (..._: any[]) => void, immediate?: boolean, priority?: number): Promise<
|
|
49
|
+
subscribe(topic: string, handler?: (..._: any[]) => void, immediate?: boolean, priority?: number): Promise<TopicSubscribeResult>;
|
|
48
50
|
unsubscribe(topic: string, handler?: (..._: any[]) => void, immediate?: boolean): Promise<any>;
|
|
49
51
|
bulkSubscribe(topics: string[], options?: BulkSubscribeOpts, priorities?: {
|
|
50
52
|
[topicName: string]: number;
|
|
51
|
-
}): Promise<
|
|
53
|
+
}): Promise<BulkSubscribeResult>;
|
|
52
54
|
get expose(): NotificationsAPI;
|
|
53
55
|
}
|
|
54
56
|
export interface NotificationsAPI {
|
|
@@ -62,3 +64,20 @@ export interface BulkSubscribeOpts {
|
|
|
62
64
|
replace?: boolean;
|
|
63
65
|
force?: boolean;
|
|
64
66
|
}
|
|
67
|
+
export interface BulkSubscribeResult {
|
|
68
|
+
[topic: string]: TopicSubscribeResult;
|
|
69
|
+
}
|
|
70
|
+
export interface TopicSubscribeResult {
|
|
71
|
+
topic: string;
|
|
72
|
+
state: 'Permitted' | 'Rejected' | 'Unknown';
|
|
73
|
+
rejectionReason?: string;
|
|
74
|
+
}
|
|
75
|
+
export interface ChannelTopicResponseEntity {
|
|
76
|
+
id: string;
|
|
77
|
+
state: 'Permitted' | 'Rejected';
|
|
78
|
+
rejectionReason?: string;
|
|
79
|
+
selfUri?: string;
|
|
80
|
+
}
|
|
81
|
+
export interface ChannelTopicsEntityListing {
|
|
82
|
+
entities: ChannelTopicResponseEntity[];
|
|
83
|
+
}
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.Notifications = void 0;
|
|
4
|
-
const
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
5
|
+
const debounce_promise_1 = tslib_1.__importDefault(require("debounce-promise"));
|
|
5
6
|
const utils_1 = require("./utils");
|
|
7
|
+
const _1 = require("./");
|
|
6
8
|
const PUBSUB_HOST_DEFAULT = 'notifications.mypurecloud.com';
|
|
7
9
|
const MAX_SUBSCRIBABLE_TOPICS = 1000;
|
|
8
10
|
const DROPPED_TOPICS_DISPLAY_COUNT = 20;
|
|
@@ -11,14 +13,16 @@ function mergeAndDedup(arr1, arr2) {
|
|
|
11
13
|
return [...arr1, ...arr2].filter((t, i, arr) => arr.indexOf(t) === i);
|
|
12
14
|
}
|
|
13
15
|
class Notifications {
|
|
14
|
-
constructor(client) {
|
|
16
|
+
constructor(client, options) {
|
|
17
|
+
var _a;
|
|
15
18
|
this.subscriptions = {};
|
|
16
19
|
this.bulkSubscriptions = {};
|
|
17
20
|
this.topicPriorities = {};
|
|
18
21
|
this.client = client;
|
|
22
|
+
this.enablePartialBulkResubscribe = (_a = options === null || options === void 0 ? void 0 : options.enablePartialBulkResubscribe) !== null && _a !== void 0 ? _a : false;
|
|
19
23
|
client.on('pubsub:event', this.pubsubEvent.bind(this));
|
|
20
24
|
client.on('connected', this.subscriptionsKeepAlive.bind(this));
|
|
21
|
-
this.debouncedResubscribe =
|
|
25
|
+
this.debouncedResubscribe = debounce_promise_1.default(this.resubscribe.bind(this), 100);
|
|
22
26
|
}
|
|
23
27
|
get pubsubHost() {
|
|
24
28
|
try {
|
|
@@ -37,7 +41,7 @@ class Notifications {
|
|
|
37
41
|
this.stanzaInstance = stanza;
|
|
38
42
|
if (needsToResub) {
|
|
39
43
|
this.client.logger.info('resubscribing due to hard reconnect');
|
|
40
|
-
this.debouncedResubscribe();
|
|
44
|
+
void this.debouncedResubscribe();
|
|
41
45
|
}
|
|
42
46
|
}
|
|
43
47
|
topicHandlers(topic) {
|
|
@@ -178,7 +182,11 @@ class Notifications {
|
|
|
178
182
|
logger: this.client.logger
|
|
179
183
|
};
|
|
180
184
|
const channelId = this.stanzaInstance.channelId;
|
|
181
|
-
|
|
185
|
+
let path = `notifications/channels/${channelId}/subscriptions`;
|
|
186
|
+
if (this.enablePartialBulkResubscribe) {
|
|
187
|
+
path += '?ignoreErrors=true';
|
|
188
|
+
}
|
|
189
|
+
return this.client.http.requestApi(path, requestOptions);
|
|
182
190
|
}
|
|
183
191
|
createSubscription(topic, handler) {
|
|
184
192
|
const topics = utils_1.splitIntoIndividualTopics(topic);
|
|
@@ -234,7 +242,7 @@ class Notifications {
|
|
|
234
242
|
/* if we don't have bulk or individual subs, we don't need to resubscribe */
|
|
235
243
|
const noTopics = bulkSubs.length + this.getActiveIndividualTopics().length === 0;
|
|
236
244
|
if (noTopics) {
|
|
237
|
-
return Promise.resolve();
|
|
245
|
+
return Promise.resolve({});
|
|
238
246
|
}
|
|
239
247
|
/* only pass in bulk subs with the replace flag – bulkSubscribe() will handle merging our individual topics (see PCM-1846) */
|
|
240
248
|
return this.bulkSubscribe(bulkSubs, { replace: true });
|
|
@@ -289,7 +297,7 @@ class Notifications {
|
|
|
289
297
|
}
|
|
290
298
|
});
|
|
291
299
|
}
|
|
292
|
-
subscribe(topic, handler, immediate, priority) {
|
|
300
|
+
async subscribe(topic, handler, immediate, priority) {
|
|
293
301
|
if (priority) {
|
|
294
302
|
this.setTopicPriorities({ [topic]: priority });
|
|
295
303
|
}
|
|
@@ -307,7 +315,19 @@ class Notifications {
|
|
|
307
315
|
else {
|
|
308
316
|
this.bulkSubscriptions[topic] = true;
|
|
309
317
|
}
|
|
310
|
-
|
|
318
|
+
const result = await promise;
|
|
319
|
+
// Assume topic subscription succeeded if promise is resolved...
|
|
320
|
+
let topicResult = { topic, state: 'Permitted' };
|
|
321
|
+
// ... but if partial bulk resubscribe is enabled, use topic's individual result from the API response.
|
|
322
|
+
if (this.enablePartialBulkResubscribe && result && typeof result === 'object' && isTopicSubscribeResult(result[topic])) {
|
|
323
|
+
topicResult = result[topic];
|
|
324
|
+
}
|
|
325
|
+
// Topic result other than state=Permitted becomes a StreamingSubscriptionError promise rejection.
|
|
326
|
+
if (topicResult.state !== 'Permitted') {
|
|
327
|
+
const message = topicResult.rejectionReason || `Failed to subscribe topic ${topic}`;
|
|
328
|
+
throw new _1.StreamingSubscriptionError(message, topic, 'subscribe');
|
|
329
|
+
}
|
|
330
|
+
return topicResult;
|
|
311
331
|
}
|
|
312
332
|
unsubscribe(topic, handler, immediate) {
|
|
313
333
|
if (handler) {
|
|
@@ -335,13 +355,35 @@ class Notifications {
|
|
|
335
355
|
// if it's a forcible bulk subscribe, wipe out individual subscriptions
|
|
336
356
|
this.subscriptions = {};
|
|
337
357
|
}
|
|
338
|
-
await this.makeBulkSubscribeRequest(toSubscribe, options);
|
|
358
|
+
const response = await this.makeBulkSubscribeRequest(toSubscribe, options);
|
|
359
|
+
let topicResponseEntities = [];
|
|
360
|
+
if (response && response.data && 'entities' in response.data && Array.isArray(response.data.entities)) {
|
|
361
|
+
topicResponseEntities = response.data.entities;
|
|
362
|
+
}
|
|
363
|
+
const topicResponsesById = {};
|
|
364
|
+
for (const topicEntity of topicResponseEntities) {
|
|
365
|
+
topicResponsesById[topicEntity.id] = topicEntity;
|
|
366
|
+
}
|
|
367
|
+
const result = {};
|
|
339
368
|
if (options.replace) {
|
|
340
369
|
this.bulkSubscriptions = {};
|
|
341
370
|
}
|
|
342
371
|
topics.forEach(topic => {
|
|
343
372
|
this.bulkSubscriptions[topic] = true;
|
|
373
|
+
if (this.enablePartialBulkResubscribe) {
|
|
374
|
+
if (topic in topicResponsesById) {
|
|
375
|
+
const { state, rejectionReason } = topicResponsesById[topic];
|
|
376
|
+
result[topic] = { topic, state, rejectionReason };
|
|
377
|
+
}
|
|
378
|
+
else {
|
|
379
|
+
result[topic] = { topic, state: 'Unknown' };
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
else {
|
|
383
|
+
result[topic] = { topic, state: 'Permitted' };
|
|
384
|
+
}
|
|
344
385
|
});
|
|
386
|
+
return result;
|
|
345
387
|
}
|
|
346
388
|
get expose() {
|
|
347
389
|
return {
|
|
@@ -352,3 +394,12 @@ class Notifications {
|
|
|
352
394
|
}
|
|
353
395
|
}
|
|
354
396
|
exports.Notifications = Notifications;
|
|
397
|
+
function isTopicSubscribeResult(value) {
|
|
398
|
+
let hasTopic = false;
|
|
399
|
+
let hasValidState = false;
|
|
400
|
+
if (value && typeof value === 'object') {
|
|
401
|
+
hasTopic = 'topic' in value && typeof value.topic === 'string';
|
|
402
|
+
hasValidState = 'state' in value && ['Permitted', 'Rejected', 'Unknown'].includes(value.state);
|
|
403
|
+
}
|
|
404
|
+
return hasTopic && hasValidState;
|
|
405
|
+
}
|
|
@@ -295,7 +295,8 @@ class GenesysCloudMediaSession {
|
|
|
295
295
|
sdp: answer.sdp,
|
|
296
296
|
sessionId: this.id
|
|
297
297
|
};
|
|
298
|
-
|
|
298
|
+
// Do not log the SDP payload to avoid logging sensitive information.
|
|
299
|
+
this.logger.info('sending sdp answer', { sessionId: this.id, conversationId: this.conversationId });
|
|
299
300
|
return this.sendGenesysWebrtc({
|
|
300
301
|
jsonrpc: '2.0',
|
|
301
302
|
method: 'answer',
|
|
@@ -22,6 +22,8 @@ export interface IClientOptions {
|
|
|
22
22
|
appVersion?: string;
|
|
23
23
|
appId?: string;
|
|
24
24
|
customHeaders?: ICustomHeader;
|
|
25
|
+
/** Allow bulk topic resubscribe to succeed or fail per-topic rather than all or nothing */
|
|
26
|
+
enablePartialBulkResubscribe?: boolean;
|
|
25
27
|
}
|
|
26
28
|
export interface ICustomHeader {
|
|
27
29
|
[header: string]: string;
|
package/dist/cjs/utils.d.ts
CHANGED
|
@@ -4,6 +4,12 @@ export declare class StreamingClientError extends Error {
|
|
|
4
4
|
details?: unknown;
|
|
5
5
|
constructor(type: StreamingClientErrorTypes | null, messageOrError: string | Error, details?: unknown);
|
|
6
6
|
}
|
|
7
|
+
export declare class StreamingSubscriptionError extends Error {
|
|
8
|
+
readonly topic?: string | undefined;
|
|
9
|
+
readonly operation?: "subscribe" | "unsubscribe" | undefined;
|
|
10
|
+
name: string;
|
|
11
|
+
constructor(message: string, topic?: string | undefined, operation?: "subscribe" | "unsubscribe" | undefined);
|
|
12
|
+
}
|
|
7
13
|
export declare function timeoutPromise(fn: Function, timeoutMs: number, msg: string, details?: any): Promise<any>;
|
|
8
14
|
export declare function delay(ms: number): Promise<void>;
|
|
9
15
|
export declare function splitIntoIndividualTopics(topicString: string): string[];
|
package/dist/cjs/utils.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.iceIsDifferent = exports.getIcePwdFromSdp = exports.getUfragFromSdp = exports.calculatePayloadSize = exports.parseJwt = exports.retryPromise = exports.isVideoJid = exports.isSoftphoneJid = exports.isScreenRecordingJid = exports.isAcdJid = exports.splitIntoIndividualTopics = exports.delay = exports.timeoutPromise = exports.StreamingClientError = void 0;
|
|
3
|
+
exports.iceIsDifferent = exports.getIcePwdFromSdp = exports.getUfragFromSdp = exports.calculatePayloadSize = exports.parseJwt = exports.retryPromise = exports.isVideoJid = exports.isSoftphoneJid = exports.isScreenRecordingJid = exports.isAcdJid = exports.splitIntoIndividualTopics = exports.delay = exports.timeoutPromise = exports.StreamingSubscriptionError = exports.StreamingClientError = void 0;
|
|
4
4
|
const uuid_1 = require("uuid");
|
|
5
5
|
const timeout_error_1 = require("./types/timeout-error");
|
|
6
6
|
const interfaces_1 = require("./types/interfaces");
|
|
@@ -22,6 +22,15 @@ class StreamingClientError extends Error {
|
|
|
22
22
|
}
|
|
23
23
|
}
|
|
24
24
|
exports.StreamingClientError = StreamingClientError;
|
|
25
|
+
class StreamingSubscriptionError extends Error {
|
|
26
|
+
constructor(message, topic, operation) {
|
|
27
|
+
super(message);
|
|
28
|
+
this.topic = topic;
|
|
29
|
+
this.operation = operation;
|
|
30
|
+
this.name = 'StreamingSubscriptionError';
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
exports.StreamingSubscriptionError = StreamingSubscriptionError;
|
|
25
34
|
/* istanbul ignore next */
|
|
26
35
|
function timeoutPromise(fn, timeoutMs, msg, details) {
|
|
27
36
|
return new Promise(function (resolve, reject) {
|
package/dist/deploy-info.json
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "
|
|
2
|
+
"version": "release/v19.4.0",
|
|
3
3
|
"build": "2",
|
|
4
|
-
"buildDate": "2025-
|
|
4
|
+
"buildDate": "2025-09-19T03:18:00.531Z",
|
|
5
5
|
"indexFiles": [
|
|
6
6
|
{
|
|
7
|
-
"file": "v19.
|
|
7
|
+
"file": "v19.4.0/streaming-client.browser.js"
|
|
8
8
|
},
|
|
9
9
|
{
|
|
10
10
|
"file": "v19/streaming-client.browser.js"
|
package/dist/es/client.js
CHANGED
package/dist/es/index.bundle.js
CHANGED
|
@@ -8234,6 +8234,14 @@ class StreamingClientError extends Error {
|
|
|
8234
8234
|
this.details = details;
|
|
8235
8235
|
}
|
|
8236
8236
|
}
|
|
8237
|
+
class StreamingSubscriptionError extends Error {
|
|
8238
|
+
constructor(message, topic, operation) {
|
|
8239
|
+
super(message);
|
|
8240
|
+
this.topic = topic;
|
|
8241
|
+
this.operation = operation;
|
|
8242
|
+
this.name = 'StreamingSubscriptionError';
|
|
8243
|
+
}
|
|
8244
|
+
}
|
|
8237
8245
|
/* istanbul ignore next */
|
|
8238
8246
|
function timeoutPromise$1(fn, timeoutMs, msg, details) {
|
|
8239
8247
|
return new Promise(function (resolve, reject) {
|
|
@@ -8387,7 +8395,6 @@ function iceIsDifferent(sdp1, sdp2) {
|
|
|
8387
8395
|
// return destination;
|
|
8388
8396
|
// }
|
|
8389
8397
|
|
|
8390
|
-
const debounce$1 = dist$1;
|
|
8391
8398
|
const PUBSUB_HOST_DEFAULT = 'notifications.mypurecloud.com';
|
|
8392
8399
|
const MAX_SUBSCRIBABLE_TOPICS = 1000;
|
|
8393
8400
|
const DROPPED_TOPICS_DISPLAY_COUNT = 20;
|
|
@@ -8396,14 +8403,16 @@ function mergeAndDedup(arr1, arr2) {
|
|
|
8396
8403
|
return [...arr1, ...arr2].filter((t, i, arr) => arr.indexOf(t) === i);
|
|
8397
8404
|
}
|
|
8398
8405
|
class Notifications {
|
|
8399
|
-
constructor(client) {
|
|
8406
|
+
constructor(client, options) {
|
|
8407
|
+
var _a;
|
|
8400
8408
|
this.subscriptions = {};
|
|
8401
8409
|
this.bulkSubscriptions = {};
|
|
8402
8410
|
this.topicPriorities = {};
|
|
8403
8411
|
this.client = client;
|
|
8412
|
+
this.enablePartialBulkResubscribe = (_a = options === null || options === void 0 ? void 0 : options.enablePartialBulkResubscribe) !== null && _a !== void 0 ? _a : false;
|
|
8404
8413
|
client.on('pubsub:event', this.pubsubEvent.bind(this));
|
|
8405
8414
|
client.on('connected', this.subscriptionsKeepAlive.bind(this));
|
|
8406
|
-
this.debouncedResubscribe =
|
|
8415
|
+
this.debouncedResubscribe = dist$1(this.resubscribe.bind(this), 100);
|
|
8407
8416
|
}
|
|
8408
8417
|
get pubsubHost() {
|
|
8409
8418
|
try {
|
|
@@ -8422,7 +8431,7 @@ class Notifications {
|
|
|
8422
8431
|
this.stanzaInstance = stanza;
|
|
8423
8432
|
if (needsToResub) {
|
|
8424
8433
|
this.client.logger.info('resubscribing due to hard reconnect');
|
|
8425
|
-
this.debouncedResubscribe();
|
|
8434
|
+
void this.debouncedResubscribe();
|
|
8426
8435
|
}
|
|
8427
8436
|
}
|
|
8428
8437
|
topicHandlers(topic) {
|
|
@@ -8565,7 +8574,11 @@ class Notifications {
|
|
|
8565
8574
|
logger: this.client.logger
|
|
8566
8575
|
};
|
|
8567
8576
|
const channelId = this.stanzaInstance.channelId;
|
|
8568
|
-
|
|
8577
|
+
let path = `notifications/channels/${channelId}/subscriptions`;
|
|
8578
|
+
if (this.enablePartialBulkResubscribe) {
|
|
8579
|
+
path += '?ignoreErrors=true';
|
|
8580
|
+
}
|
|
8581
|
+
return this.client.http.requestApi(path, requestOptions);
|
|
8569
8582
|
}
|
|
8570
8583
|
createSubscription(topic, handler) {
|
|
8571
8584
|
const topics = splitIntoIndividualTopics(topic);
|
|
@@ -8621,7 +8634,7 @@ class Notifications {
|
|
|
8621
8634
|
/* if we don't have bulk or individual subs, we don't need to resubscribe */
|
|
8622
8635
|
const noTopics = bulkSubs.length + this.getActiveIndividualTopics().length === 0;
|
|
8623
8636
|
if (noTopics) {
|
|
8624
|
-
return Promise.resolve();
|
|
8637
|
+
return Promise.resolve({});
|
|
8625
8638
|
}
|
|
8626
8639
|
/* only pass in bulk subs with the replace flag – bulkSubscribe() will handle merging our individual topics (see PCM-1846) */
|
|
8627
8640
|
return this.bulkSubscribe(bulkSubs, { replace: true });
|
|
@@ -8677,24 +8690,38 @@ class Notifications {
|
|
|
8677
8690
|
});
|
|
8678
8691
|
}
|
|
8679
8692
|
subscribe(topic, handler, immediate, priority) {
|
|
8680
|
-
|
|
8681
|
-
|
|
8682
|
-
|
|
8683
|
-
|
|
8684
|
-
|
|
8685
|
-
|
|
8686
|
-
|
|
8687
|
-
|
|
8688
|
-
|
|
8689
|
-
|
|
8690
|
-
|
|
8691
|
-
|
|
8692
|
-
|
|
8693
|
-
|
|
8694
|
-
|
|
8695
|
-
|
|
8696
|
-
|
|
8697
|
-
|
|
8693
|
+
return __awaiter$5(this, void 0, void 0, function* () {
|
|
8694
|
+
if (priority) {
|
|
8695
|
+
this.setTopicPriorities({ [topic]: priority });
|
|
8696
|
+
}
|
|
8697
|
+
let promise;
|
|
8698
|
+
if (!immediate) {
|
|
8699
|
+
// let this and any other subscribe/unsubscribe calls roll in, then trigger a whole resubscribe
|
|
8700
|
+
promise = this.debouncedResubscribe();
|
|
8701
|
+
}
|
|
8702
|
+
else {
|
|
8703
|
+
promise = this.xmppSubscribe(topic);
|
|
8704
|
+
}
|
|
8705
|
+
if (handler) {
|
|
8706
|
+
this.createSubscription(topic, handler);
|
|
8707
|
+
}
|
|
8708
|
+
else {
|
|
8709
|
+
this.bulkSubscriptions[topic] = true;
|
|
8710
|
+
}
|
|
8711
|
+
const result = yield promise;
|
|
8712
|
+
// Assume topic subscription succeeded if promise is resolved...
|
|
8713
|
+
let topicResult = { topic, state: 'Permitted' };
|
|
8714
|
+
// ... but if partial bulk resubscribe is enabled, use topic's individual result from the API response.
|
|
8715
|
+
if (this.enablePartialBulkResubscribe && result && typeof result === 'object' && isTopicSubscribeResult(result[topic])) {
|
|
8716
|
+
topicResult = result[topic];
|
|
8717
|
+
}
|
|
8718
|
+
// Topic result other than state=Permitted becomes a StreamingSubscriptionError promise rejection.
|
|
8719
|
+
if (topicResult.state !== 'Permitted') {
|
|
8720
|
+
const message = topicResult.rejectionReason || `Failed to subscribe topic ${topic}`;
|
|
8721
|
+
throw new StreamingSubscriptionError(message, topic, 'subscribe');
|
|
8722
|
+
}
|
|
8723
|
+
return topicResult;
|
|
8724
|
+
});
|
|
8698
8725
|
}
|
|
8699
8726
|
unsubscribe(topic, handler, immediate) {
|
|
8700
8727
|
if (handler) {
|
|
@@ -8723,13 +8750,35 @@ class Notifications {
|
|
|
8723
8750
|
// if it's a forcible bulk subscribe, wipe out individual subscriptions
|
|
8724
8751
|
this.subscriptions = {};
|
|
8725
8752
|
}
|
|
8726
|
-
yield this.makeBulkSubscribeRequest(toSubscribe, options);
|
|
8753
|
+
const response = yield this.makeBulkSubscribeRequest(toSubscribe, options);
|
|
8754
|
+
let topicResponseEntities = [];
|
|
8755
|
+
if (response && response.data && 'entities' in response.data && Array.isArray(response.data.entities)) {
|
|
8756
|
+
topicResponseEntities = response.data.entities;
|
|
8757
|
+
}
|
|
8758
|
+
const topicResponsesById = {};
|
|
8759
|
+
for (const topicEntity of topicResponseEntities) {
|
|
8760
|
+
topicResponsesById[topicEntity.id] = topicEntity;
|
|
8761
|
+
}
|
|
8762
|
+
const result = {};
|
|
8727
8763
|
if (options.replace) {
|
|
8728
8764
|
this.bulkSubscriptions = {};
|
|
8729
8765
|
}
|
|
8730
8766
|
topics.forEach(topic => {
|
|
8731
8767
|
this.bulkSubscriptions[topic] = true;
|
|
8768
|
+
if (this.enablePartialBulkResubscribe) {
|
|
8769
|
+
if (topic in topicResponsesById) {
|
|
8770
|
+
const { state, rejectionReason } = topicResponsesById[topic];
|
|
8771
|
+
result[topic] = { topic, state, rejectionReason };
|
|
8772
|
+
}
|
|
8773
|
+
else {
|
|
8774
|
+
result[topic] = { topic, state: 'Unknown' };
|
|
8775
|
+
}
|
|
8776
|
+
}
|
|
8777
|
+
else {
|
|
8778
|
+
result[topic] = { topic, state: 'Permitted' };
|
|
8779
|
+
}
|
|
8732
8780
|
});
|
|
8781
|
+
return result;
|
|
8733
8782
|
});
|
|
8734
8783
|
}
|
|
8735
8784
|
get expose() {
|
|
@@ -8740,6 +8789,15 @@ class Notifications {
|
|
|
8740
8789
|
};
|
|
8741
8790
|
}
|
|
8742
8791
|
}
|
|
8792
|
+
function isTopicSubscribeResult(value) {
|
|
8793
|
+
let hasTopic = false;
|
|
8794
|
+
let hasValidState = false;
|
|
8795
|
+
if (value && typeof value === 'object') {
|
|
8796
|
+
hasTopic = 'topic' in value && typeof value.topic === 'string';
|
|
8797
|
+
hasValidState = 'state' in value && ['Permitted', 'Rejected', 'Unknown'].includes(value.state);
|
|
8798
|
+
}
|
|
8799
|
+
return hasTopic && hasValidState;
|
|
8800
|
+
}
|
|
8743
8801
|
|
|
8744
8802
|
var JID$8 = {};
|
|
8745
8803
|
|
|
@@ -31737,7 +31795,8 @@ class GenesysCloudMediaSession {
|
|
|
31737
31795
|
sdp: answer.sdp,
|
|
31738
31796
|
sessionId: this.id
|
|
31739
31797
|
};
|
|
31740
|
-
|
|
31798
|
+
// Do not log the SDP payload to avoid logging sensitive information.
|
|
31799
|
+
this.logger.info('sending sdp answer', { sessionId: this.id, conversationId: this.conversationId });
|
|
31741
31800
|
return this.sendGenesysWebrtc({
|
|
31742
31801
|
jsonrpc: '2.0',
|
|
31743
31802
|
method: 'answer',
|
|
@@ -43584,10 +43643,10 @@ class Client extends EventEmitter {
|
|
|
43584
43643
|
return Client.version;
|
|
43585
43644
|
}
|
|
43586
43645
|
static get version() {
|
|
43587
|
-
return '19.
|
|
43646
|
+
return '19.4.0';
|
|
43588
43647
|
}
|
|
43589
43648
|
}
|
|
43590
43649
|
|
|
43591
43650
|
/// <reference path="types/libs.ts" />
|
|
43592
43651
|
|
|
43593
|
-
export { GenesysCloudMediaSession, HttpClient, MessengerExtension, SessionTypes, StanzaMediaSession, StreamingClientError, StreamingClientErrorTypes, Client as default, parseJwt };
|
|
43652
|
+
export { GenesysCloudMediaSession, HttpClient, MessengerExtension, SessionTypes, StanzaMediaSession, StreamingClientError, StreamingClientErrorTypes, StreamingSubscriptionError, Client as default, parseJwt };
|
package/dist/es/index.d.ts
CHANGED
|
@@ -6,5 +6,5 @@ export * from './types/media-session';
|
|
|
6
6
|
export * from './types/interfaces';
|
|
7
7
|
export * from './messenger';
|
|
8
8
|
export { HttpClient } from './http-client';
|
|
9
|
-
export { StreamingClientError, parseJwt } from './utils';
|
|
9
|
+
export { StreamingClientError, StreamingSubscriptionError, parseJwt } from './utils';
|
|
10
10
|
export default Client;
|
package/dist/es/index.js
CHANGED
|
@@ -6,5 +6,5 @@ export * from './types/media-session';
|
|
|
6
6
|
export * from './types/interfaces';
|
|
7
7
|
export * from './messenger';
|
|
8
8
|
export { HttpClient } from './http-client';
|
|
9
|
-
export { StreamingClientError, parseJwt } from './utils';
|
|
9
|
+
export { StreamingClientError, StreamingSubscriptionError, parseJwt } from './utils';
|
|
10
10
|
export default Client;
|
|
@@ -1,15 +1,17 @@
|
|
|
1
1
|
import { PubsubEvent, PubsubSubscription, PubsubSubscriptionWithOptions } from 'stanza/protocol';
|
|
2
2
|
import { Client } from './client';
|
|
3
|
-
import { StreamingClientExtension } from './types/interfaces';
|
|
3
|
+
import { IClientOptions, StreamingClientExtension } from './types/interfaces';
|
|
4
4
|
import { NamedAgent } from './types/named-agent';
|
|
5
|
+
import { AxiosResponse } from 'axios';
|
|
5
6
|
export declare class Notifications implements StreamingClientExtension {
|
|
6
7
|
client: Client;
|
|
7
8
|
stanzaInstance?: NamedAgent;
|
|
8
9
|
subscriptions: any;
|
|
9
10
|
bulkSubscriptions: any;
|
|
10
11
|
topicPriorities: any;
|
|
11
|
-
debouncedResubscribe:
|
|
12
|
-
|
|
12
|
+
debouncedResubscribe: () => Promise<BulkSubscribeResult>;
|
|
13
|
+
enablePartialBulkResubscribe: boolean;
|
|
14
|
+
constructor(client: any, options?: IClientOptions);
|
|
13
15
|
get pubsubHost(): string;
|
|
14
16
|
handleStanzaInstanceChange(stanza: NamedAgent): void;
|
|
15
17
|
topicHandlers(topic: string): Array<(obj?: any) => void>;
|
|
@@ -32,23 +34,23 @@ export declare class Notifications implements StreamingClientExtension {
|
|
|
32
34
|
}>): Array<{
|
|
33
35
|
id: string;
|
|
34
36
|
}>;
|
|
35
|
-
makeBulkSubscribeRequest(topics: string[], options: any): Promise<
|
|
37
|
+
makeBulkSubscribeRequest(topics: string[], options: any): Promise<AxiosResponse<ChannelTopicsEntityListing>>;
|
|
36
38
|
createSubscription(topic: string, handler: (obj?: any) => void): void;
|
|
37
39
|
removeSubscription(topic: string, handler: (obj?: any) => void): void;
|
|
38
40
|
removeTopicPriority(topic: string): void;
|
|
39
41
|
getActiveIndividualTopics(): string[];
|
|
40
|
-
resubscribe(): Promise<
|
|
42
|
+
resubscribe(): Promise<BulkSubscribeResult>;
|
|
41
43
|
subscriptionsKeepAlive(): void;
|
|
42
44
|
getTopicParts(topic: string): {
|
|
43
45
|
prefix: string;
|
|
44
46
|
postfixes: string[];
|
|
45
47
|
};
|
|
46
48
|
setTopicPriorities(priorities?: {}): void;
|
|
47
|
-
subscribe(topic: string, handler?: (..._: any[]) => void, immediate?: boolean, priority?: number): Promise<
|
|
49
|
+
subscribe(topic: string, handler?: (..._: any[]) => void, immediate?: boolean, priority?: number): Promise<TopicSubscribeResult>;
|
|
48
50
|
unsubscribe(topic: string, handler?: (..._: any[]) => void, immediate?: boolean): Promise<any>;
|
|
49
51
|
bulkSubscribe(topics: string[], options?: BulkSubscribeOpts, priorities?: {
|
|
50
52
|
[topicName: string]: number;
|
|
51
|
-
}): Promise<
|
|
53
|
+
}): Promise<BulkSubscribeResult>;
|
|
52
54
|
get expose(): NotificationsAPI;
|
|
53
55
|
}
|
|
54
56
|
export interface NotificationsAPI {
|
|
@@ -62,3 +64,20 @@ export interface BulkSubscribeOpts {
|
|
|
62
64
|
replace?: boolean;
|
|
63
65
|
force?: boolean;
|
|
64
66
|
}
|
|
67
|
+
export interface BulkSubscribeResult {
|
|
68
|
+
[topic: string]: TopicSubscribeResult;
|
|
69
|
+
}
|
|
70
|
+
export interface TopicSubscribeResult {
|
|
71
|
+
topic: string;
|
|
72
|
+
state: 'Permitted' | 'Rejected' | 'Unknown';
|
|
73
|
+
rejectionReason?: string;
|
|
74
|
+
}
|
|
75
|
+
export interface ChannelTopicResponseEntity {
|
|
76
|
+
id: string;
|
|
77
|
+
state: 'Permitted' | 'Rejected';
|
|
78
|
+
rejectionReason?: string;
|
|
79
|
+
selfUri?: string;
|
|
80
|
+
}
|
|
81
|
+
export interface ChannelTopicsEntityListing {
|
|
82
|
+
entities: ChannelTopicResponseEntity[];
|
|
83
|
+
}
|