genesys-cloud-streaming-client 19.6.0 → 19.6.1-develop.17

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.
@@ -1,14 +1,26 @@
1
- import { IClientOptions, StreamingClientExtension } from './types/interfaces';
1
+ /// <reference types="node" />
2
+ import { IClientOptions, ILeaderStatus, StreamingClientExtension } from './types/interfaces';
2
3
  import { Client } from './client';
4
+ import { EventEmitter } from 'events';
3
5
  import { NamedAgent } from './types/named-agent';
4
- export declare class AlertingLeaderExtension implements StreamingClientExtension {
6
+ export declare class AlertingLeaderExtension extends EventEmitter implements StreamingClientExtension {
5
7
  private client;
6
8
  private connectionId?;
7
9
  private alertableInteractionTypes;
10
+ private abortController?;
11
+ private leaderStatus;
8
12
  constructor(client: Client, options: IClientOptions);
9
13
  handleStanzaInstanceChange(stanzaInstance: NamedAgent): void;
14
+ private setupAlertingLeader;
15
+ private subscribeToAlertingLeader;
10
16
  private markAsAlertable;
17
+ private getAlertingLeader;
18
+ private claimAlertingLeader;
11
19
  get expose(): AlertingLeaderApi;
12
20
  }
13
21
  export interface AlertingLeaderApi {
22
+ on: (event: string, handler: (...args: any) => void) => void;
23
+ off: (event: string, handler: (...args: any) => void) => void;
24
+ claimAlertingLeader(): Promise<void>;
25
+ leaderStatus: ILeaderStatus;
14
26
  }
@@ -1,20 +1,58 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.AlertingLeaderExtension = void 0;
4
+ const tslib_1 = require("tslib");
5
+ const axios_1 = tslib_1.__importDefault(require("axios"));
6
+ const interfaces_1 = require("./types/interfaces");
7
+ const events_1 = require("events");
4
8
  const utils_1 = require("./utils");
5
- class AlertingLeaderExtension {
9
+ class AlertingLeaderExtension extends events_1.EventEmitter {
6
10
  constructor(client, options) {
7
11
  var _a;
12
+ super();
8
13
  this.client = client;
14
+ this.leaderStatus = {};
9
15
  this.alertableInteractionTypes = (_a = options.alertableInteractionTypes) !== null && _a !== void 0 ? _a : [];
10
16
  }
11
17
  handleStanzaInstanceChange(stanzaInstance) {
12
18
  var _a, _b;
13
19
  this.connectionId = (_b = (_a = stanzaInstance.transport) === null || _a === void 0 ? void 0 : _a.stream) === null || _b === void 0 ? void 0 : _b.id;
20
+ this.setupAlertingLeader();
21
+ }
22
+ async setupAlertingLeader() {
14
23
  if (this.alertableInteractionTypes.length !== 0) {
15
- this.markAsAlertable();
24
+ try {
25
+ await this.subscribeToAlertingLeader();
26
+ await this.markAsAlertable();
27
+ await this.getAlertingLeader();
28
+ }
29
+ catch (err) {
30
+ this.client.logger.warn('Failed to setup alerting leader; falling back to the default of acting as the alerting leader');
31
+ // Fail 'open' so users don't miss calls
32
+ this.leaderStatus = { voice: { alerting: true, configured: false } };
33
+ this.emit('alertingLeaderChanged', this.leaderStatus);
34
+ }
16
35
  }
17
36
  }
37
+ async subscribeToAlertingLeader() {
38
+ const topic = `v2.users.${this.client.config.userId}.alertingleader`;
39
+ this.client.on(`notify:${topic}`, (event) => {
40
+ var _a, _b;
41
+ (_a = this.abortController) === null || _a === void 0 ? void 0 : _a.abort();
42
+ if ((_b = event.eventBody) === null || _b === void 0 ? void 0 : _b.connectionId) {
43
+ // We should alert if our connection is the alerting leader connection
44
+ const alerting = event.eventBody.connectionId === this.connectionId;
45
+ const clientType = event.eventBody.clientType;
46
+ let voice = { alerting, configured: true };
47
+ if (clientType) {
48
+ voice = { ...voice, clientType };
49
+ }
50
+ this.leaderStatus = { voice };
51
+ this.emit('alertingLeaderChanged', this.leaderStatus);
52
+ }
53
+ });
54
+ return this.client._notifications._subscribeInternal(topic);
55
+ }
18
56
  async markAsAlertable() {
19
57
  const userId = this.client.config.userId;
20
58
  const connectionsRequestOptions = {
@@ -44,8 +82,61 @@ class AlertingLeaderExtension {
44
82
  this.client.logger.warn('Could not mark this connection as alertable; this client may not alert for incoming interactions');
45
83
  });
46
84
  }
85
+ async getAlertingLeader() {
86
+ this.abortController = new AbortController();
87
+ const leaderRequestOptions = {
88
+ method: 'get',
89
+ host: this.client.config.apiHost,
90
+ authToken: this.client.config.authToken,
91
+ logger: this.client.logger,
92
+ signal: this.abortController.signal
93
+ };
94
+ try {
95
+ const currentLeader = await this.client.http.requestApi('users/alertingleader', leaderRequestOptions);
96
+ // We should alert if our connection is the alerting leader connection
97
+ const alerting = currentLeader.data.connectionId === this.connectionId;
98
+ const clientType = currentLeader.data.clientType;
99
+ let voice = { alerting, configured: true };
100
+ if (clientType) {
101
+ voice = { ...voice, clientType };
102
+ }
103
+ this.leaderStatus = { voice };
104
+ this.emit('alertingLeaderChanged', this.leaderStatus);
105
+ }
106
+ catch (err) {
107
+ if (axios_1.default.isCancel(err)) {
108
+ return;
109
+ }
110
+ throw err;
111
+ }
112
+ }
113
+ async claimAlertingLeader() {
114
+ if (this.alertableInteractionTypes.length === 0) {
115
+ this.client.logger.info('This client is not configured for any alertable interactions and will not attempt to claim alerting leader');
116
+ throw new utils_1.StreamingClientError(interfaces_1.StreamingClientErrorTypes.generic, 'Unable to claim alerting leader; this client is not configured for any alertable interactions');
117
+ }
118
+ const leaderRequestOptions = {
119
+ method: 'put',
120
+ host: this.client.config.apiHost,
121
+ authToken: this.client.config.authToken,
122
+ logger: this.client.logger,
123
+ data: {
124
+ connectionId: this.connectionId
125
+ }
126
+ };
127
+ return this.client.http.requestApi('users/alertingleader', leaderRequestOptions)
128
+ .catch((err) => {
129
+ this.client.logger.warn('Unable to claim alerting leader; this client may not alert for incoming interactions');
130
+ throw new utils_1.StreamingClientError(interfaces_1.StreamingClientErrorTypes.generic, 'Unable to claim alerting leader', err);
131
+ });
132
+ }
47
133
  get expose() {
48
- return {};
134
+ return {
135
+ on: this.on.bind(this),
136
+ off: this.off.bind(this),
137
+ claimAlertingLeader: this.claimAlertingLeader.bind(this),
138
+ leaderStatus: this.leaderStatus
139
+ };
49
140
  }
50
141
  }
51
142
  exports.AlertingLeaderExtension = AlertingLeaderExtension;
@@ -670,7 +670,7 @@ class Client extends events_1.default {
670
670
  return Client.version;
671
671
  }
672
672
  static get version() {
673
- return '19.6.0';
673
+ return '19.6.1';
674
674
  }
675
675
  }
676
676
  exports.Client = Client;
@@ -64,7 +64,8 @@ class HttpClient {
64
64
  data: opts.data,
65
65
  responseType: opts.responseType,
66
66
  timeout: opts.requestTimeout || 30000,
67
- headers
67
+ headers,
68
+ signal: opts.signal
68
69
  };
69
70
  // default to include auth header
70
71
  if (!opts.noAuthHeader) {
@@ -33,6 +33,27 @@ export interface ICustomHeader {
33
33
  export declare enum AlertableInteractionTypes {
34
34
  voice = "voice"
35
35
  }
36
+ /** The alerting status for an interaction type */
37
+ export interface IAlertingStatus {
38
+ /**
39
+ * Indicates whether this client should be alerting. This can be because this client is the alerting
40
+ * leader for this interaction type, alerting leader functionality is not configured by an admin,
41
+ * or because setup for alerting leader failed and we fallback to `alerting: true` so interactions
42
+ * don't go unnoticed.
43
+ */
44
+ alerting: boolean;
45
+ /**
46
+ * Indicates if alerting leader functionality is configured by an admin. This will also be `false`
47
+ * if setup for alerting leader failed.
48
+ */
49
+ configured: boolean;
50
+ /** A string representing the client type of the alerting leader, based on OAuth client ID. */
51
+ clientType?: string;
52
+ }
53
+ /** The alerting leader status for this client. Currently only `voice` interactions are supported. */
54
+ export interface ILeaderStatus {
55
+ voice?: IAlertingStatus;
56
+ }
36
57
  export interface IClientConfig {
37
58
  host: string;
38
59
  apiHost: string;
@@ -67,6 +88,7 @@ export declare type RequestApiOptions = {
67
88
  requestTimeout?: number;
68
89
  customHeaders?: ICustomHeader;
69
90
  maxAttempts?: number;
91
+ signal?: AbortSignal;
70
92
  };
71
93
  export interface IAxiosResponseError extends AxiosError {
72
94
  text: string;
@@ -1,13 +1,13 @@
1
1
  {
2
- "version": "19.6.0",
3
- "build": "7",
4
- "buildDate": "2026-04-17T16:20:47.432Z",
2
+ "version": "19.6.1-develop",
3
+ "build": "17",
4
+ "buildDate": "2026-04-29T14:55:47.312Z",
5
5
  "indexFiles": [
6
6
  {
7
- "file": "v19.6.0/streaming-client.browser.js"
7
+ "file": "v19.6.1/streaming-client.browser.js"
8
8
  },
9
9
  {
10
- "file": "v19.6.0/streaming-client.browser.js.LICENSE.txt"
10
+ "file": "v19.6.1/streaming-client.browser.js.LICENSE.txt"
11
11
  },
12
12
  {
13
13
  "file": "v19/streaming-client.browser.js"
@@ -1,14 +1,26 @@
1
- import { IClientOptions, StreamingClientExtension } from './types/interfaces';
1
+ /// <reference types="node" />
2
+ import { IClientOptions, ILeaderStatus, StreamingClientExtension } from './types/interfaces';
2
3
  import { Client } from './client';
4
+ import { EventEmitter } from 'events';
3
5
  import { NamedAgent } from './types/named-agent';
4
- export declare class AlertingLeaderExtension implements StreamingClientExtension {
6
+ export declare class AlertingLeaderExtension extends EventEmitter implements StreamingClientExtension {
5
7
  private client;
6
8
  private connectionId?;
7
9
  private alertableInteractionTypes;
10
+ private abortController?;
11
+ private leaderStatus;
8
12
  constructor(client: Client, options: IClientOptions);
9
13
  handleStanzaInstanceChange(stanzaInstance: NamedAgent): void;
14
+ private setupAlertingLeader;
15
+ private subscribeToAlertingLeader;
10
16
  private markAsAlertable;
17
+ private getAlertingLeader;
18
+ private claimAlertingLeader;
11
19
  get expose(): AlertingLeaderApi;
12
20
  }
13
21
  export interface AlertingLeaderApi {
22
+ on: (event: string, handler: (...args: any) => void) => void;
23
+ off: (event: string, handler: (...args: any) => void) => void;
24
+ claimAlertingLeader(): Promise<void>;
25
+ leaderStatus: ILeaderStatus;
14
26
  }
@@ -1,17 +1,58 @@
1
1
  import { __awaiter } from "tslib";
2
- import { retryPromise } from './utils';
3
- export class AlertingLeaderExtension {
2
+ import axios from 'axios';
3
+ import { StreamingClientErrorTypes } from './types/interfaces';
4
+ import { EventEmitter } from 'events';
5
+ import { StreamingClientError, retryPromise } from './utils';
6
+ export class AlertingLeaderExtension extends EventEmitter {
4
7
  constructor(client, options) {
5
8
  var _a;
9
+ super();
6
10
  this.client = client;
11
+ this.leaderStatus = {};
7
12
  this.alertableInteractionTypes = (_a = options.alertableInteractionTypes) !== null && _a !== void 0 ? _a : [];
8
13
  }
9
14
  handleStanzaInstanceChange(stanzaInstance) {
10
15
  var _a, _b;
11
16
  this.connectionId = (_b = (_a = stanzaInstance.transport) === null || _a === void 0 ? void 0 : _a.stream) === null || _b === void 0 ? void 0 : _b.id;
12
- if (this.alertableInteractionTypes.length !== 0) {
13
- this.markAsAlertable();
14
- }
17
+ this.setupAlertingLeader();
18
+ }
19
+ setupAlertingLeader() {
20
+ return __awaiter(this, void 0, void 0, function* () {
21
+ if (this.alertableInteractionTypes.length !== 0) {
22
+ try {
23
+ yield this.subscribeToAlertingLeader();
24
+ yield this.markAsAlertable();
25
+ yield this.getAlertingLeader();
26
+ }
27
+ catch (err) {
28
+ this.client.logger.warn('Failed to setup alerting leader; falling back to the default of acting as the alerting leader');
29
+ // Fail 'open' so users don't miss calls
30
+ this.leaderStatus = { voice: { alerting: true, configured: false } };
31
+ this.emit('alertingLeaderChanged', this.leaderStatus);
32
+ }
33
+ }
34
+ });
35
+ }
36
+ subscribeToAlertingLeader() {
37
+ return __awaiter(this, void 0, void 0, function* () {
38
+ const topic = `v2.users.${this.client.config.userId}.alertingleader`;
39
+ this.client.on(`notify:${topic}`, (event) => {
40
+ var _a, _b;
41
+ (_a = this.abortController) === null || _a === void 0 ? void 0 : _a.abort();
42
+ if ((_b = event.eventBody) === null || _b === void 0 ? void 0 : _b.connectionId) {
43
+ // We should alert if our connection is the alerting leader connection
44
+ const alerting = event.eventBody.connectionId === this.connectionId;
45
+ const clientType = event.eventBody.clientType;
46
+ let voice = { alerting, configured: true };
47
+ if (clientType) {
48
+ voice = Object.assign(Object.assign({}, voice), { clientType });
49
+ }
50
+ this.leaderStatus = { voice };
51
+ this.emit('alertingLeaderChanged', this.leaderStatus);
52
+ }
53
+ });
54
+ return this.client._notifications._subscribeInternal(topic);
55
+ });
15
56
  }
16
57
  markAsAlertable() {
17
58
  return __awaiter(this, void 0, void 0, function* () {
@@ -44,7 +85,64 @@ export class AlertingLeaderExtension {
44
85
  });
45
86
  });
46
87
  }
88
+ getAlertingLeader() {
89
+ return __awaiter(this, void 0, void 0, function* () {
90
+ this.abortController = new AbortController();
91
+ const leaderRequestOptions = {
92
+ method: 'get',
93
+ host: this.client.config.apiHost,
94
+ authToken: this.client.config.authToken,
95
+ logger: this.client.logger,
96
+ signal: this.abortController.signal
97
+ };
98
+ try {
99
+ const currentLeader = yield this.client.http.requestApi('users/alertingleader', leaderRequestOptions);
100
+ // We should alert if our connection is the alerting leader connection
101
+ const alerting = currentLeader.data.connectionId === this.connectionId;
102
+ const clientType = currentLeader.data.clientType;
103
+ let voice = { alerting, configured: true };
104
+ if (clientType) {
105
+ voice = Object.assign(Object.assign({}, voice), { clientType });
106
+ }
107
+ this.leaderStatus = { voice };
108
+ this.emit('alertingLeaderChanged', this.leaderStatus);
109
+ }
110
+ catch (err) {
111
+ if (axios.isCancel(err)) {
112
+ return;
113
+ }
114
+ throw err;
115
+ }
116
+ });
117
+ }
118
+ claimAlertingLeader() {
119
+ return __awaiter(this, void 0, void 0, function* () {
120
+ if (this.alertableInteractionTypes.length === 0) {
121
+ this.client.logger.info('This client is not configured for any alertable interactions and will not attempt to claim alerting leader');
122
+ throw new StreamingClientError(StreamingClientErrorTypes.generic, 'Unable to claim alerting leader; this client is not configured for any alertable interactions');
123
+ }
124
+ const leaderRequestOptions = {
125
+ method: 'put',
126
+ host: this.client.config.apiHost,
127
+ authToken: this.client.config.authToken,
128
+ logger: this.client.logger,
129
+ data: {
130
+ connectionId: this.connectionId
131
+ }
132
+ };
133
+ return this.client.http.requestApi('users/alertingleader', leaderRequestOptions)
134
+ .catch((err) => {
135
+ this.client.logger.warn('Unable to claim alerting leader; this client may not alert for incoming interactions');
136
+ throw new StreamingClientError(StreamingClientErrorTypes.generic, 'Unable to claim alerting leader', err);
137
+ });
138
+ });
139
+ }
47
140
  get expose() {
48
- return {};
141
+ return {
142
+ on: this.on.bind(this),
143
+ off: this.off.bind(this),
144
+ claimAlertingLeader: this.claimAlertingLeader.bind(this),
145
+ leaderStatus: this.leaderStatus
146
+ };
49
147
  }
50
148
  }
package/dist/es/client.js CHANGED
@@ -684,6 +684,6 @@ export class Client extends EventEmitter {
684
684
  return Client.version;
685
685
  }
686
686
  static get version() {
687
- return '19.6.0';
687
+ return '19.6.1';
688
688
  }
689
689
  }
@@ -54,7 +54,8 @@ export class HttpClient {
54
54
  data: opts.data,
55
55
  responseType: opts.responseType,
56
56
  timeout: opts.requestTimeout || 30000,
57
- headers
57
+ headers,
58
+ signal: opts.signal
58
59
  };
59
60
  // default to include auth header
60
61
  if (!opts.noAuthHeader) {