@webex/contact-center 3.9.0-next.2 → 3.9.0-next.21

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 (106) hide show
  1. package/dist/cc.js +195 -46
  2. package/dist/cc.js.map +1 -1
  3. package/dist/constants.js +1 -0
  4. package/dist/constants.js.map +1 -1
  5. package/dist/index.js +9 -0
  6. package/dist/index.js.map +1 -1
  7. package/dist/logger-proxy.js +24 -1
  8. package/dist/logger-proxy.js.map +1 -1
  9. package/dist/metrics/MetricsManager.js +1 -1
  10. package/dist/metrics/MetricsManager.js.map +1 -1
  11. package/dist/metrics/behavioral-events.js +89 -0
  12. package/dist/metrics/behavioral-events.js.map +1 -1
  13. package/dist/metrics/constants.js +32 -2
  14. package/dist/metrics/constants.js.map +1 -1
  15. package/dist/services/AddressBook.js +271 -0
  16. package/dist/services/AddressBook.js.map +1 -0
  17. package/dist/services/EntryPoint.js +227 -0
  18. package/dist/services/EntryPoint.js.map +1 -0
  19. package/dist/services/Queue.js +261 -0
  20. package/dist/services/Queue.js.map +1 -0
  21. package/dist/services/config/constants.js +36 -2
  22. package/dist/services/config/constants.js.map +1 -1
  23. package/dist/services/config/index.js +29 -21
  24. package/dist/services/config/index.js.map +1 -1
  25. package/dist/services/config/types.js +33 -1
  26. package/dist/services/config/types.js.map +1 -1
  27. package/dist/services/core/GlobalTypes.js.map +1 -1
  28. package/dist/services/core/Utils.js +162 -2
  29. package/dist/services/core/Utils.js.map +1 -1
  30. package/dist/services/core/aqm-reqs.js +0 -4
  31. package/dist/services/core/aqm-reqs.js.map +1 -1
  32. package/dist/services/core/websocket/WebSocketManager.js +0 -4
  33. package/dist/services/core/websocket/WebSocketManager.js.map +1 -1
  34. package/dist/services/task/TaskManager.js +74 -2
  35. package/dist/services/task/TaskManager.js.map +1 -1
  36. package/dist/services/task/constants.js +7 -1
  37. package/dist/services/task/constants.js.map +1 -1
  38. package/dist/services/task/contact.js +86 -0
  39. package/dist/services/task/contact.js.map +1 -1
  40. package/dist/services/task/index.js +384 -72
  41. package/dist/services/task/index.js.map +1 -1
  42. package/dist/services/task/types.js +14 -0
  43. package/dist/services/task/types.js.map +1 -1
  44. package/dist/types/cc.d.ts +115 -35
  45. package/dist/types/constants.d.ts +1 -0
  46. package/dist/types/index.d.ts +3 -2
  47. package/dist/types/metrics/constants.d.ts +25 -1
  48. package/dist/types/services/AddressBook.d.ts +74 -0
  49. package/dist/types/services/EntryPoint.d.ts +67 -0
  50. package/dist/types/services/Queue.d.ts +76 -0
  51. package/dist/types/services/config/constants.d.ts +35 -1
  52. package/dist/types/services/config/index.d.ts +6 -9
  53. package/dist/types/services/config/types.d.ts +79 -58
  54. package/dist/types/services/core/GlobalTypes.d.ts +25 -0
  55. package/dist/types/services/core/Utils.d.ts +40 -1
  56. package/dist/types/services/task/constants.d.ts +6 -0
  57. package/dist/types/services/task/contact.d.ts +10 -0
  58. package/dist/types/services/task/index.d.ts +44 -2
  59. package/dist/types/services/task/types.d.ts +125 -1
  60. package/dist/types/types.d.ts +162 -0
  61. package/dist/types/utils/PageCache.d.ts +173 -0
  62. package/dist/types.js +17 -0
  63. package/dist/types.js.map +1 -1
  64. package/dist/utils/PageCache.js +192 -0
  65. package/dist/utils/PageCache.js.map +1 -0
  66. package/dist/webex.js +1 -1
  67. package/package.json +9 -8
  68. package/src/cc.ts +220 -51
  69. package/src/constants.ts +1 -0
  70. package/src/index.ts +16 -2
  71. package/src/logger-proxy.ts +24 -1
  72. package/src/metrics/MetricsManager.ts +1 -1
  73. package/src/metrics/behavioral-events.ts +94 -0
  74. package/src/metrics/constants.ts +37 -1
  75. package/src/services/AddressBook.ts +291 -0
  76. package/src/services/EntryPoint.ts +241 -0
  77. package/src/services/Queue.ts +277 -0
  78. package/src/services/config/constants.ts +42 -2
  79. package/src/services/config/index.ts +30 -30
  80. package/src/services/config/types.ts +59 -58
  81. package/src/services/core/GlobalTypes.ts +27 -0
  82. package/src/services/core/Utils.ts +199 -1
  83. package/src/services/core/aqm-reqs.ts +0 -5
  84. package/src/services/core/websocket/WebSocketManager.ts +0 -4
  85. package/src/services/task/TaskManager.ts +79 -3
  86. package/src/services/task/constants.ts +6 -0
  87. package/src/services/task/contact.ts +80 -0
  88. package/src/services/task/index.ts +457 -57
  89. package/src/services/task/types.ts +135 -0
  90. package/src/types.ts +180 -0
  91. package/src/utils/PageCache.ts +252 -0
  92. package/test/unit/spec/cc.ts +282 -85
  93. package/test/unit/spec/metrics/MetricsManager.ts +0 -1
  94. package/test/unit/spec/metrics/behavioral-events.ts +42 -0
  95. package/test/unit/spec/services/AddressBook.ts +332 -0
  96. package/test/unit/spec/services/EntryPoint.ts +259 -0
  97. package/test/unit/spec/services/Queue.ts +323 -0
  98. package/test/unit/spec/services/config/index.ts +279 -65
  99. package/test/unit/spec/services/core/Utils.ts +50 -0
  100. package/test/unit/spec/services/core/aqm-reqs.ts +1 -3
  101. package/test/unit/spec/services/core/websocket/WebSocketManager.ts +0 -4
  102. package/test/unit/spec/services/task/TaskManager.ts +145 -1
  103. package/test/unit/spec/services/task/contact.ts +31 -1
  104. package/test/unit/spec/services/task/index.ts +410 -123
  105. package/umd/contact-center.min.js +2 -2
  106. package/umd/contact-center.min.js.map +1 -1
@@ -37,7 +37,6 @@ type Enum<T extends Record<string, unknown>> = T[keyof T];
37
37
  * @property {string} TASK_HOLD_FAILED - Event name for failed task hold.
38
38
  * @property {string} TASK_RESUME_SUCCESS - Event name for successful task resume.
39
39
  * @property {string} TASK_RESUME_FAILED - Event name for failed task resume.
40
- *
41
40
  * @property {string} TASK_CONSULT_START_SUCCESS - Event name for successful consult start.
42
41
  * @property {string} TASK_CONSULT_START_FAILED - Event name for failed consult start.
43
42
  * @property {string} TASK_CONSULT_END_SUCCESS - Event name for successful consult end.
@@ -51,6 +50,13 @@ type Enum<T extends Record<string, unknown>> = T[keyof T];
51
50
  * @property {string} TASK_ACCEPT_CONSULT_SUCCESS - Event name for successful consult acceptance.
52
51
  * @property {string} TASK_ACCEPT_CONSULT_FAILED - Event name for failed consult acceptance.
53
52
  *
53
+ * @property {string} TASK_CONFERENCE_START_SUCCESS - Event name for successful conference start.
54
+ * @property {string} TASK_CONFERENCE_START_FAILED - Event name for failed conference start.
55
+ * @property {string} TASK_CONFERENCE_END_SUCCESS - Event name for successful conference end.
56
+ * @property {string} TASK_CONFERENCE_END_FAILED - Event name for failed conference end.
57
+ * @property {string} TASK_CONFERENCE_TRANSFER_SUCCESS - Event name for successful conference transfer.
58
+ * @property {string} TASK_CONFERENCE_TRANSFER_FAILED - Event name for failed conference transfer.
59
+ *
54
60
  * @property {string} TASK_OUTDIAL_SUCCESS - Event name for successful outdial task.
55
61
  * @property {string} TASK_OUTDIAL_FAILED - Event name for failed outdial task.
56
62
  *
@@ -62,6 +68,9 @@ type Enum<T extends Record<string, unknown>> = T[keyof T];
62
68
  * @property {string} AGENT_DEVICE_TYPE_UPDATE_SUCCESS - Event name for successful agent device type update.
63
69
  * @property {string} AGENT_DEVICE_TYPE_UPDATE_FAILED - Event name for failed agent device type update.
64
70
  *
71
+ * @property {string} OUTDIAL_ANI_EP_FETCH_SUCCESS - Event name for successful outdial ANI entries fetch.
72
+ * @property {string} OUTDIAL_ANI_EP_FETCH_FAILED - Event name for failed outdial ANI entries fetch.
73
+ *
65
74
  * @readonly
66
75
  */
67
76
  export const METRIC_EVENT_NAMES = {
@@ -109,6 +118,14 @@ export const METRIC_EVENT_NAMES = {
109
118
  TASK_ACCEPT_CONSULT_SUCCESS: 'Task Accept Consult Success',
110
119
  TASK_ACCEPT_CONSULT_FAILED: 'Task Accept Consult Failed',
111
120
 
121
+ // Conference Tasks
122
+ TASK_CONFERENCE_START_SUCCESS: 'Task Conference Start Success',
123
+ TASK_CONFERENCE_START_FAILED: 'Task Conference Start Failed',
124
+ TASK_CONFERENCE_END_SUCCESS: 'Task Conference End Success',
125
+ TASK_CONFERENCE_END_FAILED: 'Task Conference End Failed',
126
+ TASK_CONFERENCE_TRANSFER_SUCCESS: 'Task Conference Transfer Success',
127
+ TASK_CONFERENCE_TRANSFER_FAILED: 'Task Conference Transfer Failed',
128
+
112
129
  TASK_OUTDIAL_SUCCESS: 'Task Outdial Success',
113
130
  TASK_OUTDIAL_FAILED: 'Task Outdial Failed',
114
131
 
@@ -117,8 +134,27 @@ export const METRIC_EVENT_NAMES = {
117
134
  WEBSOCKET_DEREGISTER_SUCCESS: 'Websocket Deregister Success',
118
135
  WEBSOCKET_DEREGISTER_FAIL: 'Websocket Deregister Failed',
119
136
 
137
+ // WebSocket message events
138
+ WEBSOCKET_EVENT_RECEIVED: 'Websocket Event Received',
139
+
120
140
  AGENT_DEVICE_TYPE_UPDATE_SUCCESS: 'Agent Device Type Update Success',
121
141
  AGENT_DEVICE_TYPE_UPDATE_FAILED: 'Agent Device Type Update Failed',
142
+
143
+ // EntryPoint API Events
144
+ ENTRYPOINT_FETCH_SUCCESS: 'Entrypoint Fetch Success',
145
+ ENTRYPOINT_FETCH_FAILED: 'Entrypoint Fetch Failed',
146
+
147
+ // AddressBook API Events
148
+ ADDRESSBOOK_FETCH_SUCCESS: 'AddressBook Fetch Success',
149
+ ADDRESSBOOK_FETCH_FAILED: 'AddressBook Fetch Failed',
150
+
151
+ // Queue API Events
152
+ QUEUE_FETCH_SUCCESS: 'Queue Fetch Success',
153
+ QUEUE_FETCH_FAILED: 'Queue Fetch Failed',
154
+
155
+ // Outdial ANI Entries API Events
156
+ OUTDIAL_ANI_EP_FETCH_SUCCESS: 'Outdial ANI Entries Fetch Success',
157
+ OUTDIAL_ANI_EP_FETCH_FAILED: 'Outdial ANI Entries Fetch Failed',
122
158
  } as const;
123
159
 
124
160
  /**
@@ -0,0 +1,291 @@
1
+ import {HTTP_METHODS, WebexSDK} from '../types';
2
+ import type {
3
+ AddressBookEntry,
4
+ AddressBookEntriesResponse,
5
+ AddressBookEntrySearchParams,
6
+ } from '../types';
7
+ import LoggerProxy from '../logger-proxy';
8
+ import WebexRequest from './core/WebexRequest';
9
+ import PageCache, {PAGINATION_DEFAULTS} from '../utils/PageCache';
10
+ import MetricsManager from '../metrics/MetricsManager';
11
+ import {WCC_API_GATEWAY} from './constants';
12
+ import {endPointMap} from './config/constants';
13
+ import {METRIC_EVENT_NAMES} from '../metrics/constants';
14
+
15
+ /**
16
+ * AddressBook API class for managing Webex Contact Center address book entries.
17
+ * Provides functionality to fetch address book entries using the entry API.
18
+ *
19
+ * @class AddressBook
20
+ * @public
21
+ * @example
22
+ * ```typescript
23
+ * import Webex from 'webex';
24
+ *
25
+ * const webex = new Webex({ credentials: 'YOUR_ACCESS_TOKEN' });
26
+ * const cc = webex.cc;
27
+ *
28
+ * // Register and login first
29
+ * await cc.register();
30
+ * await cc.stationLogin({ teamId: 'team123', loginOption: 'BROWSER' });
31
+ *
32
+ * // Get AddressBook API instance from ContactCenter
33
+ * const addressBookAPI = cc.addressBook;
34
+ *
35
+ * // Get entries from agent's default address book
36
+ * const entries = await addressBookAPI.getEntries();
37
+ *
38
+ * // Get entries from a specific address book with pagination
39
+ * const entries = await addressBookAPI.getEntries({
40
+ * addressBookId: 'addressBookId123',
41
+ * page: 0,
42
+ * pageSize: 50
43
+ * });
44
+ *
45
+ * // Search for specific entries
46
+ * const searchResults = await addressBook.getEntries({
47
+ * search: 'john',
48
+ * filter: 'name=="John Doe"'
49
+ * });
50
+ * ```
51
+ */
52
+ export class AddressBook {
53
+ private webexRequest: WebexRequest;
54
+ private webex: WebexSDK;
55
+ private getAddressBookId: () => string;
56
+ private metricsManager: MetricsManager;
57
+
58
+ // Page cache using the common utility
59
+ private pageCache: PageCache<AddressBookEntry>;
60
+
61
+ /**
62
+ * Creates an instance of AddressBook
63
+ * @param {WebexSDK} webex - The Webex SDK instance
64
+ * @param {() => string} getAddressBookId - Function to get the addressBookId from agent profile
65
+ * @public
66
+ */
67
+ constructor(webex: WebexSDK, getAddressBookId: () => string) {
68
+ this.webex = webex;
69
+ this.webexRequest = WebexRequest.getInstance({webex});
70
+ this.getAddressBookId = getAddressBookId;
71
+ this.pageCache = new PageCache<AddressBookEntry>('AddressBook');
72
+ this.metricsManager = MetricsManager.getInstance({webex});
73
+ }
74
+
75
+ /**
76
+ * Fetches address book entries for a specific address book using the entry API
77
+ * @param {AddressBookEntrySearchParams} [params] - Search and pagination parameters including addressBookId
78
+ * @returns {Promise<AddressBookEntriesResponse>} Promise resolving to address book entries
79
+ * @throws {Error} If the API call fails
80
+ * @public
81
+ * @example
82
+ * ```typescript
83
+ * // Get entries from agent's default address book
84
+ * const response = await addressBookAPI.getEntries();
85
+ *
86
+ * // Get entries from a specific address book with pagination
87
+ * const response = await addressBookAPI.getEntries({
88
+ * addressBookId: 'addressBookId123',
89
+ * page: 0,
90
+ * pageSize: 25
91
+ * });
92
+ * ```
93
+ */
94
+ public async getEntries(
95
+ params: AddressBookEntrySearchParams = {}
96
+ ): Promise<AddressBookEntriesResponse> {
97
+ const startTime = Date.now();
98
+ const {
99
+ addressBookId,
100
+ page = PAGINATION_DEFAULTS.PAGE,
101
+ pageSize = PAGINATION_DEFAULTS.PAGE_SIZE,
102
+ search,
103
+ filter,
104
+ attributes,
105
+ } = params;
106
+
107
+ // Use provided addressBookId or fall back to agent's address book
108
+ const bookId = addressBookId || this.getAddressBookId();
109
+ const orgId = this.webex.credentials.getOrgId();
110
+ const isSearchRequest = !!(search || filter || attributes);
111
+
112
+ LoggerProxy.info('Fetching address book entries', {
113
+ module: 'AddressBook',
114
+ method: 'getEntries',
115
+ data: {
116
+ orgId,
117
+ bookId,
118
+ page,
119
+ pageSize,
120
+ isSearchRequest,
121
+ },
122
+ });
123
+
124
+ // Check if we can use cache for simple pagination (no search/filter/attributes)
125
+ if (this.pageCache.canUseCache({search, filter, attributes})) {
126
+ const cacheKey = this.pageCache.buildCacheKey(bookId, page, pageSize);
127
+ const cachedPage = this.pageCache.getCachedPage(cacheKey);
128
+
129
+ if (cachedPage) {
130
+ const duration = Date.now() - startTime;
131
+
132
+ LoggerProxy.info(`Returning page ${page} from cache`, {
133
+ module: 'AddressBook',
134
+ method: 'getEntries',
135
+ data: {
136
+ cacheHit: true,
137
+ duration,
138
+ recordCount: cachedPage.data.length,
139
+ page,
140
+ pageSize,
141
+ },
142
+ });
143
+
144
+ return {
145
+ data: cachedPage.data,
146
+ meta: {
147
+ page,
148
+ pageSize,
149
+ totalPages: cachedPage.totalMeta?.totalPages,
150
+ totalRecords: cachedPage.totalMeta?.totalRecords,
151
+ },
152
+ };
153
+ }
154
+ }
155
+
156
+ // Start timing for the operation
157
+ this.metricsManager.timeEvent(METRIC_EVENT_NAMES.ADDRESSBOOK_FETCH_SUCCESS);
158
+
159
+ // Validate address book id early to avoid bad requests
160
+ if (!bookId) {
161
+ const errorData = {
162
+ orgId,
163
+ bookId,
164
+ isSearchRequest,
165
+ page,
166
+ pageSize,
167
+ error: 'Missing addressBookId for agent. Ensure agent profile contains addressBookId.',
168
+ };
169
+ LoggerProxy.error('AddressBook called without a valid addressBookId', {
170
+ module: 'AddressBook',
171
+ method: 'getEntries',
172
+ data: errorData,
173
+ });
174
+
175
+ this.metricsManager.trackEvent(METRIC_EVENT_NAMES.ADDRESSBOOK_FETCH_FAILED, errorData, [
176
+ 'behavioral',
177
+ 'operational',
178
+ ]);
179
+
180
+ throw new Error('AddressBook: addressBookId is not available for the current agent.');
181
+ }
182
+
183
+ try {
184
+ // Build query parameters according to spec
185
+ const queryParams = new URLSearchParams({
186
+ page: page.toString(),
187
+ pageSize: pageSize.toString(),
188
+ });
189
+
190
+ if (filter) queryParams.append('filter', filter);
191
+ if (attributes) queryParams.append('attributes', attributes);
192
+ if (search) queryParams.append('search', search);
193
+
194
+ const resource = endPointMap.addressBookEntries(orgId, bookId, queryParams.toString());
195
+
196
+ LoggerProxy.info('Making API request to fetch address book entries', {
197
+ module: 'AddressBook',
198
+ method: 'getEntries',
199
+ data: {
200
+ resource,
201
+ service: WCC_API_GATEWAY,
202
+ },
203
+ });
204
+
205
+ const response = await this.webexRequest.request({
206
+ service: WCC_API_GATEWAY,
207
+ resource,
208
+ method: HTTP_METHODS.GET,
209
+ });
210
+
211
+ const duration = Date.now() - startTime;
212
+
213
+ const recordCount = response.body?.data?.length || 0;
214
+ const totalRecords = response.body?.meta?.totalRecords;
215
+
216
+ LoggerProxy.info(`Successfully retrieved ${recordCount} address book entries`, {
217
+ module: 'AddressBook',
218
+ method: 'getEntries',
219
+ data: {
220
+ statusCode: response.statusCode,
221
+ duration,
222
+ recordCount,
223
+ totalRecords,
224
+ isSearchRequest,
225
+ page,
226
+ pageSize,
227
+ },
228
+ });
229
+
230
+ // Only track metrics for search requests or first page loads to reduce metric volume
231
+ if (isSearchRequest || page === 0) {
232
+ this.metricsManager.trackEvent(
233
+ METRIC_EVENT_NAMES.ADDRESSBOOK_FETCH_SUCCESS,
234
+ {
235
+ orgId,
236
+ bookId,
237
+ statusCode: response.statusCode,
238
+ recordCount,
239
+ totalRecords,
240
+ isSearchRequest,
241
+ isFirstPage: page === 0,
242
+ },
243
+ ['behavioral', 'operational']
244
+ );
245
+ }
246
+
247
+ // Cache the page data for simple pagination (no search/filter/attributes)
248
+ if (this.pageCache.canUseCache({search, filter, attributes}) && response.body?.data) {
249
+ const cacheKey = this.pageCache.buildCacheKey(bookId, page, pageSize);
250
+ this.pageCache.cachePage(cacheKey, response.body.data, response.body.meta);
251
+
252
+ LoggerProxy.info('Cached address book entries for future requests', {
253
+ module: 'AddressBook',
254
+ method: 'getEntries',
255
+ data: {
256
+ cacheKey,
257
+ recordCount,
258
+ },
259
+ });
260
+ }
261
+
262
+ return response.body;
263
+ } catch (error) {
264
+ const errorData = {
265
+ orgId,
266
+ bookId,
267
+ error: error instanceof Error ? error.message : String(error),
268
+ isSearchRequest,
269
+ page,
270
+ pageSize,
271
+ };
272
+
273
+ LoggerProxy.error('Failed to fetch address book entries', {
274
+ module: 'AddressBook',
275
+ method: 'getEntries',
276
+ data: errorData,
277
+ error,
278
+ });
279
+
280
+ // Track all failures for troubleshooting
281
+ this.metricsManager.trackEvent(METRIC_EVENT_NAMES.ADDRESSBOOK_FETCH_FAILED, errorData, [
282
+ 'behavioral',
283
+ 'operational',
284
+ ]);
285
+
286
+ throw error;
287
+ }
288
+ }
289
+ }
290
+
291
+ export default AddressBook;
@@ -0,0 +1,241 @@
1
+ import {HTTP_METHODS, WebexSDK} from '../types';
2
+ import type {EntryPointRecord, EntryPointListResponse, EntryPointSearchParams} from '../types';
3
+ import LoggerProxy from '../logger-proxy';
4
+ import WebexRequest from './core/WebexRequest';
5
+ import PageCache, {PAGINATION_DEFAULTS} from '../utils/PageCache';
6
+ import MetricsManager from '../metrics/MetricsManager';
7
+ import {WCC_API_GATEWAY} from './constants';
8
+ import {endPointMap} from './config/constants';
9
+ import {METRIC_EVENT_NAMES} from '../metrics/constants';
10
+
11
+ /**
12
+ * EntryPoint class for managing Webex Contact Center entry points.
13
+ * Provides functionality to fetch, search, and paginate through entry points.
14
+ *
15
+ * @class EntryPoint
16
+ * @public
17
+ * @example
18
+ * ```typescript
19
+ * import Webex from 'webex';
20
+ *
21
+ * const webex = new Webex({ credentials: 'YOUR_ACCESS_TOKEN' });
22
+ * const cc = webex.cc;
23
+ *
24
+ * // Register and login first
25
+ * await cc.register();
26
+ * await cc.stationLogin({ teamId: 'team123', loginOption: 'BROWSER' });
27
+ *
28
+ * // Get EntryPoint API instance from ContactCenter
29
+ * const entryPointAPI = cc.entryPoint;
30
+ *
31
+ * // Get all entry points with pagination
32
+ * const response = await entryPointAPI.getEntryPoints({
33
+ * page: 0,
34
+ * pageSize: 50
35
+ * });
36
+ *
37
+ * // Search for specific entry points
38
+ * const searchResults = await entryPointAPI.searchEntryPoints({
39
+ * search: 'support',
40
+ * filter: 'type=="voice"'
41
+ * });
42
+ * ```
43
+ */
44
+ export class EntryPoint {
45
+ private webexRequest: WebexRequest;
46
+ private webex: WebexSDK;
47
+ private metricsManager: MetricsManager;
48
+
49
+ // Page cache using the common utility
50
+ private pageCache: PageCache<EntryPointRecord>;
51
+
52
+ /**
53
+ * Creates an instance of EntryPoint
54
+ * @param {WebexSDK} webex - The Webex SDK instance
55
+ * @public
56
+ */
57
+ constructor(webex: WebexSDK) {
58
+ this.webex = webex;
59
+ this.webexRequest = WebexRequest.getInstance({webex});
60
+ this.pageCache = new PageCache<EntryPointRecord>('EntryPoint');
61
+ this.metricsManager = MetricsManager.getInstance({webex});
62
+ }
63
+
64
+ /**
65
+ * Fetches entry points for the organization with pagination support
66
+ * @param {EntryPointSearchParams} [params] - Search and pagination parameters
67
+ * @returns {Promise<EntryPointListResponse>} Promise resolving to paginated entry points
68
+ * @throws {Error} If the API call fails
69
+ * @public
70
+ * @example
71
+ * ```typescript
72
+ * // Get first page of entry points
73
+ * const response = await entryPointAPI.getEntryPoints();
74
+ *
75
+ * // Get specific page with custom page size
76
+ * const response = await entryPointAPI.getEntryPoints({
77
+ * page: 2,
78
+ * pageSize: 25
79
+ * });
80
+ * ```
81
+ */
82
+ public async getEntryPoints(
83
+ params: EntryPointSearchParams = {}
84
+ ): Promise<EntryPointListResponse> {
85
+ const startTime = Date.now();
86
+ const {
87
+ page = PAGINATION_DEFAULTS.PAGE,
88
+ pageSize = PAGINATION_DEFAULTS.PAGE_SIZE,
89
+ search,
90
+ filter,
91
+ attributes,
92
+ sortBy,
93
+ sortOrder = 'asc',
94
+ } = params;
95
+
96
+ const orgId = this.webex.credentials.getOrgId();
97
+ const isSearchRequest = !!(search || filter || attributes || sortBy);
98
+
99
+ LoggerProxy.info(
100
+ `Fetching entry points - orgId: ${orgId}, page: ${page}, pageSize: ${pageSize}, isSearchRequest: ${isSearchRequest}`,
101
+ {
102
+ module: 'EntryPoint',
103
+ method: 'getEntryPoints',
104
+ }
105
+ );
106
+
107
+ // Check if we can use cache for simple pagination (no search/filter/attributes/sort)
108
+ if (this.pageCache.canUseCache({search, filter, attributes, sortBy})) {
109
+ const cacheKey = this.pageCache.buildCacheKey(orgId, page, pageSize);
110
+ const cachedPage = this.pageCache.getCachedPage(cacheKey);
111
+
112
+ if (cachedPage) {
113
+ const duration = Date.now() - startTime;
114
+
115
+ LoggerProxy.log(
116
+ `Returning page ${page} from cache - cacheHit: true, duration: ${duration}ms, recordCount: ${cachedPage.data.length}, pageSize: ${pageSize}`,
117
+ {
118
+ module: 'EntryPoint',
119
+ method: 'getEntryPoints',
120
+ }
121
+ );
122
+
123
+ return {
124
+ data: cachedPage.data,
125
+ meta: {
126
+ page,
127
+ pageSize,
128
+ totalPages: cachedPage.totalMeta?.totalPages,
129
+ totalRecords: cachedPage.totalMeta?.totalRecords,
130
+ },
131
+ };
132
+ }
133
+ }
134
+
135
+ // Start timing only for actual API calls (not cache hits)
136
+ this.metricsManager.timeEvent(METRIC_EVENT_NAMES.ENTRYPOINT_FETCH_SUCCESS);
137
+
138
+ try {
139
+ // Build query parameters
140
+ const queryParams = new URLSearchParams({
141
+ page: page.toString(),
142
+ pageSize: pageSize.toString(),
143
+ sortOrder,
144
+ });
145
+
146
+ if (search) queryParams.append('search', search);
147
+ if (filter) queryParams.append('filter', filter);
148
+ if (attributes) queryParams.append('attributes', attributes);
149
+ if (sortBy) queryParams.append('sortBy', sortBy);
150
+
151
+ const resource = endPointMap.entryPointList(orgId, queryParams.toString());
152
+
153
+ LoggerProxy.log(
154
+ `Making API request to fetch entry points - resource: ${resource}, service: ${WCC_API_GATEWAY}`,
155
+ {
156
+ module: 'EntryPoint',
157
+ method: 'getEntryPoints',
158
+ }
159
+ );
160
+
161
+ const response = await this.webexRequest.request({
162
+ service: WCC_API_GATEWAY,
163
+ resource,
164
+ method: HTTP_METHODS.GET,
165
+ });
166
+
167
+ const duration = Date.now() - startTime;
168
+
169
+ const recordCount = response.body?.data?.length || 0;
170
+ const totalRecords = response.body?.meta?.totalRecords;
171
+
172
+ LoggerProxy.log(`Successfully retrieved ${recordCount} entry points`, {
173
+ module: 'EntryPoint',
174
+ method: 'getEntryPoints',
175
+ data: {
176
+ statusCode: response.statusCode,
177
+ duration,
178
+ recordCount,
179
+ totalRecords,
180
+ isSearchRequest,
181
+ page,
182
+ pageSize,
183
+ },
184
+ });
185
+
186
+ // Only track metrics for search requests or first page loads to reduce metric volume
187
+ if (isSearchRequest || page === 0) {
188
+ this.metricsManager.trackEvent(
189
+ METRIC_EVENT_NAMES.ENTRYPOINT_FETCH_SUCCESS,
190
+ {
191
+ orgId,
192
+ statusCode: response.statusCode,
193
+ recordCount,
194
+ totalRecords,
195
+ isSearchRequest,
196
+ isFirstPage: page === 0,
197
+ },
198
+ ['behavioral']
199
+ );
200
+ }
201
+
202
+ // Cache the page data for simple pagination (no search/filter/attributes/sort)
203
+ if (this.pageCache.canUseCache({search, filter, attributes, sortBy}) && response.body?.data) {
204
+ const cacheKey = this.pageCache.buildCacheKey(orgId, page, pageSize);
205
+ this.pageCache.cachePage(cacheKey, response.body.data, response.body.meta);
206
+
207
+ LoggerProxy.log('Cached entry points data for future requests', {
208
+ module: 'EntryPoint',
209
+ method: 'getEntryPoints',
210
+ data: {cacheKey, recordCount},
211
+ });
212
+ }
213
+
214
+ return response.body;
215
+ } catch (error) {
216
+ const errorData = {
217
+ orgId,
218
+ error: error instanceof Error ? error.message : String(error),
219
+ isSearchRequest,
220
+ page,
221
+ pageSize,
222
+ };
223
+
224
+ LoggerProxy.error(`Failed to fetch entry points`, {
225
+ module: 'EntryPoint',
226
+ method: 'getEntryPoints',
227
+ data: errorData,
228
+ error,
229
+ });
230
+
231
+ // Track all failures for troubleshooting
232
+ this.metricsManager.trackEvent(METRIC_EVENT_NAMES.ENTRYPOINT_FETCH_FAILED, errorData, [
233
+ 'behavioral',
234
+ ]);
235
+
236
+ throw error;
237
+ }
238
+ }
239
+ }
240
+
241
+ export default EntryPoint;