@webex/contact-center 0.0.0-next.1

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 (177) hide show
  1. package/README.md +81 -0
  2. package/__mocks__/workerMock.js +15 -0
  3. package/babel.config.js +15 -0
  4. package/dist/cc.js +1416 -0
  5. package/dist/cc.js.map +1 -0
  6. package/dist/config.js +72 -0
  7. package/dist/config.js.map +1 -0
  8. package/dist/constants.js +58 -0
  9. package/dist/constants.js.map +1 -0
  10. package/dist/index.js +142 -0
  11. package/dist/index.js.map +1 -0
  12. package/dist/logger-proxy.js +115 -0
  13. package/dist/logger-proxy.js.map +1 -0
  14. package/dist/metrics/MetricsManager.js +474 -0
  15. package/dist/metrics/MetricsManager.js.map +1 -0
  16. package/dist/metrics/behavioral-events.js +322 -0
  17. package/dist/metrics/behavioral-events.js.map +1 -0
  18. package/dist/metrics/constants.js +134 -0
  19. package/dist/metrics/constants.js.map +1 -0
  20. package/dist/services/WebCallingService.js +323 -0
  21. package/dist/services/WebCallingService.js.map +1 -0
  22. package/dist/services/agent/index.js +177 -0
  23. package/dist/services/agent/index.js.map +1 -0
  24. package/dist/services/agent/types.js +137 -0
  25. package/dist/services/agent/types.js.map +1 -0
  26. package/dist/services/config/Util.js +203 -0
  27. package/dist/services/config/Util.js.map +1 -0
  28. package/dist/services/config/constants.js +221 -0
  29. package/dist/services/config/constants.js.map +1 -0
  30. package/dist/services/config/index.js +607 -0
  31. package/dist/services/config/index.js.map +1 -0
  32. package/dist/services/config/types.js +334 -0
  33. package/dist/services/config/types.js.map +1 -0
  34. package/dist/services/constants.js +117 -0
  35. package/dist/services/constants.js.map +1 -0
  36. package/dist/services/core/Err.js +43 -0
  37. package/dist/services/core/Err.js.map +1 -0
  38. package/dist/services/core/GlobalTypes.js +6 -0
  39. package/dist/services/core/GlobalTypes.js.map +1 -0
  40. package/dist/services/core/Utils.js +126 -0
  41. package/dist/services/core/Utils.js.map +1 -0
  42. package/dist/services/core/WebexRequest.js +96 -0
  43. package/dist/services/core/WebexRequest.js.map +1 -0
  44. package/dist/services/core/aqm-reqs.js +246 -0
  45. package/dist/services/core/aqm-reqs.js.map +1 -0
  46. package/dist/services/core/constants.js +109 -0
  47. package/dist/services/core/constants.js.map +1 -0
  48. package/dist/services/core/types.js +6 -0
  49. package/dist/services/core/types.js.map +1 -0
  50. package/dist/services/core/websocket/WebSocketManager.js +187 -0
  51. package/dist/services/core/websocket/WebSocketManager.js.map +1 -0
  52. package/dist/services/core/websocket/connection-service.js +111 -0
  53. package/dist/services/core/websocket/connection-service.js.map +1 -0
  54. package/dist/services/core/websocket/keepalive.worker.js +94 -0
  55. package/dist/services/core/websocket/keepalive.worker.js.map +1 -0
  56. package/dist/services/core/websocket/types.js +6 -0
  57. package/dist/services/core/websocket/types.js.map +1 -0
  58. package/dist/services/index.js +78 -0
  59. package/dist/services/index.js.map +1 -0
  60. package/dist/services/task/AutoWrapup.js +88 -0
  61. package/dist/services/task/AutoWrapup.js.map +1 -0
  62. package/dist/services/task/TaskManager.js +369 -0
  63. package/dist/services/task/TaskManager.js.map +1 -0
  64. package/dist/services/task/constants.js +58 -0
  65. package/dist/services/task/constants.js.map +1 -0
  66. package/dist/services/task/contact.js +464 -0
  67. package/dist/services/task/contact.js.map +1 -0
  68. package/dist/services/task/dialer.js +60 -0
  69. package/dist/services/task/dialer.js.map +1 -0
  70. package/dist/services/task/index.js +1188 -0
  71. package/dist/services/task/index.js.map +1 -0
  72. package/dist/services/task/types.js +214 -0
  73. package/dist/services/task/types.js.map +1 -0
  74. package/dist/types/cc.d.ts +676 -0
  75. package/dist/types/config.d.ts +66 -0
  76. package/dist/types/constants.d.ts +45 -0
  77. package/dist/types/index.d.ts +178 -0
  78. package/dist/types/logger-proxy.d.ts +71 -0
  79. package/dist/types/metrics/MetricsManager.d.ts +223 -0
  80. package/dist/types/metrics/behavioral-events.d.ts +29 -0
  81. package/dist/types/metrics/constants.d.ts +127 -0
  82. package/dist/types/services/WebCallingService.d.ts +1 -0
  83. package/dist/types/services/agent/index.d.ts +46 -0
  84. package/dist/types/services/agent/types.d.ts +413 -0
  85. package/dist/types/services/config/Util.d.ts +19 -0
  86. package/dist/types/services/config/constants.d.ts +203 -0
  87. package/dist/types/services/config/index.d.ts +171 -0
  88. package/dist/types/services/config/types.d.ts +1113 -0
  89. package/dist/types/services/constants.d.ts +97 -0
  90. package/dist/types/services/core/Err.d.ts +119 -0
  91. package/dist/types/services/core/GlobalTypes.d.ts +33 -0
  92. package/dist/types/services/core/Utils.d.ts +36 -0
  93. package/dist/types/services/core/WebexRequest.d.ts +22 -0
  94. package/dist/types/services/core/aqm-reqs.d.ts +16 -0
  95. package/dist/types/services/core/constants.d.ts +85 -0
  96. package/dist/types/services/core/types.d.ts +47 -0
  97. package/dist/types/services/core/websocket/WebSocketManager.d.ts +34 -0
  98. package/dist/types/services/core/websocket/connection-service.d.ts +27 -0
  99. package/dist/types/services/core/websocket/keepalive.worker.d.ts +2 -0
  100. package/dist/types/services/core/websocket/types.d.ts +37 -0
  101. package/dist/types/services/index.d.ts +52 -0
  102. package/dist/types/services/task/AutoWrapup.d.ts +40 -0
  103. package/dist/types/services/task/TaskManager.d.ts +1 -0
  104. package/dist/types/services/task/constants.d.ts +46 -0
  105. package/dist/types/services/task/contact.d.ts +59 -0
  106. package/dist/types/services/task/dialer.d.ts +28 -0
  107. package/dist/types/services/task/index.d.ts +569 -0
  108. package/dist/types/services/task/types.d.ts +1041 -0
  109. package/dist/types/types.d.ts +452 -0
  110. package/dist/types/webex-config.d.ts +53 -0
  111. package/dist/types/webex.d.ts +7 -0
  112. package/dist/types.js +292 -0
  113. package/dist/types.js.map +1 -0
  114. package/dist/webex-config.js +60 -0
  115. package/dist/webex-config.js.map +1 -0
  116. package/dist/webex.js +99 -0
  117. package/dist/webex.js.map +1 -0
  118. package/jest.config.js +45 -0
  119. package/package.json +83 -0
  120. package/src/cc.ts +1618 -0
  121. package/src/config.ts +65 -0
  122. package/src/constants.ts +51 -0
  123. package/src/index.ts +220 -0
  124. package/src/logger-proxy.ts +110 -0
  125. package/src/metrics/MetricsManager.ts +512 -0
  126. package/src/metrics/behavioral-events.ts +332 -0
  127. package/src/metrics/constants.ts +135 -0
  128. package/src/services/WebCallingService.ts +351 -0
  129. package/src/services/agent/index.ts +149 -0
  130. package/src/services/agent/types.ts +440 -0
  131. package/src/services/config/Util.ts +261 -0
  132. package/src/services/config/constants.ts +249 -0
  133. package/src/services/config/index.ts +743 -0
  134. package/src/services/config/types.ts +1117 -0
  135. package/src/services/constants.ts +111 -0
  136. package/src/services/core/Err.ts +126 -0
  137. package/src/services/core/GlobalTypes.ts +34 -0
  138. package/src/services/core/Utils.ts +132 -0
  139. package/src/services/core/WebexRequest.ts +103 -0
  140. package/src/services/core/aqm-reqs.ts +272 -0
  141. package/src/services/core/constants.ts +106 -0
  142. package/src/services/core/types.ts +48 -0
  143. package/src/services/core/websocket/WebSocketManager.ts +196 -0
  144. package/src/services/core/websocket/connection-service.ts +142 -0
  145. package/src/services/core/websocket/keepalive.worker.js +88 -0
  146. package/src/services/core/websocket/types.ts +40 -0
  147. package/src/services/index.ts +71 -0
  148. package/src/services/task/AutoWrapup.ts +86 -0
  149. package/src/services/task/TaskManager.ts +420 -0
  150. package/src/services/task/constants.ts +52 -0
  151. package/src/services/task/contact.ts +429 -0
  152. package/src/services/task/dialer.ts +52 -0
  153. package/src/services/task/index.ts +1375 -0
  154. package/src/services/task/types.ts +1113 -0
  155. package/src/types.ts +639 -0
  156. package/src/webex-config.ts +54 -0
  157. package/src/webex.js +96 -0
  158. package/test/unit/spec/cc.ts +1985 -0
  159. package/test/unit/spec/metrics/MetricsManager.ts +491 -0
  160. package/test/unit/spec/metrics/behavioral-events.ts +102 -0
  161. package/test/unit/spec/services/WebCallingService.ts +416 -0
  162. package/test/unit/spec/services/agent/index.ts +65 -0
  163. package/test/unit/spec/services/config/index.ts +1035 -0
  164. package/test/unit/spec/services/core/Utils.ts +279 -0
  165. package/test/unit/spec/services/core/WebexRequest.ts +144 -0
  166. package/test/unit/spec/services/core/aqm-reqs.ts +570 -0
  167. package/test/unit/spec/services/core/websocket/WebSocketManager.ts +378 -0
  168. package/test/unit/spec/services/core/websocket/connection-service.ts +178 -0
  169. package/test/unit/spec/services/task/TaskManager.ts +1351 -0
  170. package/test/unit/spec/services/task/contact.ts +204 -0
  171. package/test/unit/spec/services/task/dialer.ts +157 -0
  172. package/test/unit/spec/services/task/index.ts +1474 -0
  173. package/tsconfig.json +6 -0
  174. package/typedoc.json +37 -0
  175. package/typedoc.md +240 -0
  176. package/umd/contact-center.min.js +3 -0
  177. package/umd/contact-center.min.js.map +1 -0
@@ -0,0 +1,142 @@
1
+ import {EventEmitter} from 'events';
2
+ import {WebSocketManager} from './WebSocketManager';
3
+ import LoggerProxy from '../../../logger-proxy';
4
+ import {ConnectionServiceOptions, ConnectionLostDetails, ConnectionProp} from './types';
5
+ import {
6
+ LOST_CONNECTION_RECOVERY_TIMEOUT,
7
+ WS_DISCONNECT_ALLOWED,
8
+ CONNECTIVITY_CHECK_INTERVAL,
9
+ METHODS,
10
+ } from '../constants';
11
+ import {CONNECTION_SERVICE_FILE} from '../../../constants';
12
+ import {SubscribeRequest} from '../../../types';
13
+
14
+ export class ConnectionService extends EventEmitter {
15
+ private connectionProp: ConnectionProp = {
16
+ lostConnectionRecoveryTimeout: LOST_CONNECTION_RECOVERY_TIMEOUT,
17
+ };
18
+
19
+ private wsDisconnectAllowed = WS_DISCONNECT_ALLOWED;
20
+ private reconnectingTimer: ReturnType<typeof setTimeout>;
21
+ private restoreTimer: ReturnType<typeof setTimeout>;
22
+ private isConnectionLost: boolean;
23
+ private isRestoreFailed: boolean;
24
+ private isSocketReconnected: boolean;
25
+ private isKeepAlive: boolean;
26
+ private reconnectInterval: ReturnType<typeof setInterval>;
27
+ private webSocketManager: WebSocketManager;
28
+ private subscribeRequest: SubscribeRequest;
29
+
30
+ constructor(options: ConnectionServiceOptions) {
31
+ super();
32
+ this.webSocketManager = options.webSocketManager;
33
+ this.subscribeRequest = options.subscribeRequest;
34
+
35
+ this.isConnectionLost = false;
36
+ this.isRestoreFailed = false;
37
+ this.isSocketReconnected = false;
38
+ this.isKeepAlive = false;
39
+
40
+ this.setupEventListeners();
41
+ }
42
+
43
+ private setupEventListeners() {
44
+ this.webSocketManager.on('message', this.onPing.bind(this));
45
+ this.webSocketManager.on('socketClose', this.onSocketClose.bind(this));
46
+ }
47
+
48
+ private dispatchConnectionEvent(socketReconnected = false): void {
49
+ const event: ConnectionLostDetails = {
50
+ isConnectionLost: this.isConnectionLost,
51
+ isRestoreFailed: this.isRestoreFailed,
52
+ isSocketReconnected:
53
+ !this.webSocketManager.isSocketClosed && (socketReconnected || this.isSocketReconnected),
54
+ isKeepAlive: this.isKeepAlive,
55
+ };
56
+ this.webSocketManager.handleConnectionLost(event);
57
+ LoggerProxy.info(`Dispatching connection event`, {
58
+ module: CONNECTION_SERVICE_FILE,
59
+ method: METHODS.DISPATCH_CONNECTION_EVENT,
60
+ });
61
+ this.emit('connectionLost', event);
62
+ }
63
+
64
+ private handleConnectionLost = (): void => {
65
+ this.isConnectionLost = true;
66
+ this.dispatchConnectionEvent();
67
+ };
68
+
69
+ private clearTimerOnRestoreFailed = async () => {
70
+ if (this.reconnectInterval) {
71
+ clearInterval(this.reconnectInterval);
72
+ }
73
+ };
74
+
75
+ private handleRestoreFailed = async () => {
76
+ this.isRestoreFailed = true;
77
+ this.webSocketManager.shouldReconnect = false;
78
+ this.dispatchConnectionEvent();
79
+ await this.clearTimerOnRestoreFailed();
80
+ };
81
+
82
+ private updateConnectionData = (): void => {
83
+ this.isRestoreFailed = false;
84
+ this.isConnectionLost = false;
85
+ this.isSocketReconnected = false;
86
+ };
87
+
88
+ public setConnectionProp(prop: ConnectionProp): void {
89
+ this.connectionProp = prop;
90
+ }
91
+
92
+ private onPing = (event: any): void => {
93
+ const parsedEvent = JSON.parse(event);
94
+ if (this.reconnectingTimer) {
95
+ clearTimeout(this.reconnectingTimer);
96
+ }
97
+ if (this.restoreTimer) {
98
+ clearTimeout(this.restoreTimer);
99
+ }
100
+ this.isKeepAlive = parsedEvent.keepalive === 'true';
101
+
102
+ if (
103
+ ((this.isConnectionLost && !this.isRestoreFailed) || this.isKeepAlive) &&
104
+ !this.isSocketReconnected
105
+ ) {
106
+ this.updateConnectionData();
107
+ this.dispatchConnectionEvent();
108
+ } else if (this.isSocketReconnected && this.isKeepAlive) {
109
+ this.updateConnectionData();
110
+ this.dispatchConnectionEvent(true);
111
+ }
112
+
113
+ this.reconnectingTimer = setTimeout(this.handleConnectionLost, this.wsDisconnectAllowed);
114
+ this.restoreTimer = setTimeout(
115
+ this.handleRestoreFailed,
116
+ this.connectionProp && this.connectionProp.lostConnectionRecoveryTimeout
117
+ );
118
+ };
119
+
120
+ private handleSocketClose = async (): Promise<void> => {
121
+ LoggerProxy.info(`event=socketConnectionRetry | Trying to reconnect to websocket`, {
122
+ module: CONNECTION_SERVICE_FILE,
123
+ method: METHODS.HANDLE_SOCKET_CLOSE,
124
+ });
125
+ const onlineStatus = navigator.onLine;
126
+ if (onlineStatus) {
127
+ await this.webSocketManager.initWebSocket({body: this.subscribeRequest});
128
+ await this.clearTimerOnRestoreFailed();
129
+ this.isSocketReconnected = true;
130
+ } else {
131
+ throw new Error('event=socketConnectionRetry | browser network not available');
132
+ }
133
+ };
134
+
135
+ private onSocketClose = (): void => {
136
+ this.clearTimerOnRestoreFailed();
137
+
138
+ this.reconnectInterval = setInterval(async () => {
139
+ await this.handleSocketClose();
140
+ }, CONNECTIVITY_CHECK_INTERVAL);
141
+ };
142
+ }
@@ -0,0 +1,88 @@
1
+ // TODO: Try to find alternative to using Blob and script here
2
+ const workerScript = `
3
+ console.log("*** Keepalive Worker Thread ***");
4
+ let intervalId, intervalDuration, timeOutId, isSocketClosed, closeSocketTimeout;
5
+ let initialised = false;
6
+ let initiateWebSocketClosure = false;
7
+
8
+ const resetOfflineHandler = function () {
9
+ if (timeOutId) {
10
+ initialised = false;
11
+ clearTimeout(timeOutId);
12
+ timeOutId = null;
13
+ }
14
+ };
15
+
16
+ const checkOnlineStatus = function () {
17
+ const onlineStatus = navigator.onLine;
18
+ console.log(
19
+ \`[WebSocketStatus] event=checkOnlineStatus | online status=\`,
20
+ onlineStatus
21
+ );
22
+ return onlineStatus;
23
+ };
24
+
25
+ // Checks network status and if it's offline then force closes WebSocket
26
+ const checkNetworkStatus = function () {
27
+ const onlineStatus = checkOnlineStatus();
28
+ postMessage({ type: "keepalive", onlineStatus });
29
+ if (!onlineStatus && !initialised) {
30
+ initialised = true;
31
+ // Sets a timeout of 16s, checks if socket didn't close then it closes forcefully
32
+ timeOutId = setTimeout(() => {
33
+ if (!isSocketClosed) {
34
+ initiateWebSocketClosure = true;
35
+ postMessage({ type: "closeSocket" });
36
+ }
37
+ }, closeSocketTimeout);
38
+ }
39
+
40
+ if (onlineStatus && initialised) {
41
+ initialised = false;
42
+ }
43
+
44
+ if (initiateWebSocketClosure) {
45
+ initiateWebSocketClosure = false;
46
+ clearTimeout(timeOutId);
47
+ timeOutId = null;
48
+ }
49
+ };
50
+
51
+ addEventListener("message", (event) => {
52
+ if (event.data?.type === "start") {
53
+ intervalDuration = event.data?.intervalDuration || 4000;
54
+ closeSocketTimeout = event.data?.closeSocketTimeout || 5000;
55
+ console.log("event=Websocket startWorker | keepalive Worker started");
56
+ intervalId = setInterval(
57
+ (checkIfSocketClosed) => {
58
+ checkNetworkStatus();
59
+ isSocketClosed = checkIfSocketClosed;
60
+ },
61
+ intervalDuration,
62
+ event.data?.isSocketClosed
63
+ );
64
+
65
+ resetOfflineHandler();
66
+ }
67
+
68
+ if (event.data?.type === "terminate" && intervalId) {
69
+ console.log("event=Websocket terminateWorker | keepalive Worker stopped");
70
+ clearInterval(intervalId);
71
+ intervalId = null;
72
+ resetOfflineHandler();
73
+ }
74
+ });
75
+
76
+ // Listen for online and offline events
77
+ self.addEventListener('online', () => {
78
+ console.log('Network status: online');
79
+ checkNetworkStatus();
80
+ });
81
+
82
+ self.addEventListener('offline', () => {
83
+ console.log('Network status: offline');
84
+ checkNetworkStatus();
85
+ });
86
+ `;
87
+
88
+ export default workerScript;
@@ -0,0 +1,40 @@
1
+ import {SubscribeRequest} from '../../../types';
2
+ import {WebSocketManager} from './WebSocketManager';
3
+
4
+ /**
5
+ * Options for initializing a connection service.
6
+ * @typedef ConnectionServiceOptions
7
+ * @property {WebSocketManager} webSocketManager - The WebSocket manager instance.
8
+ * @property {SubscribeRequest} subscribeRequest - The subscribe request payload.
9
+ * @ignore
10
+ */
11
+ export type ConnectionServiceOptions = {
12
+ webSocketManager: WebSocketManager;
13
+ subscribeRequest: SubscribeRequest;
14
+ };
15
+
16
+ /**
17
+ * Details about the state of a lost connection and recovery attempts.
18
+ * @typedef ConnectionLostDetails
19
+ * @property {boolean} isConnectionLost - Indicates if the connection is currently lost.
20
+ * @property {boolean} isRestoreFailed - Indicates if restoring the connection has failed.
21
+ * @property {boolean} isSocketReconnected - Indicates if the socket has been reconnected.
22
+ * @property {boolean} isKeepAlive - Indicates if the keep-alive mechanism is active.
23
+ * @ignore
24
+ */
25
+ export type ConnectionLostDetails = {
26
+ isConnectionLost: boolean;
27
+ isRestoreFailed: boolean;
28
+ isSocketReconnected: boolean;
29
+ isKeepAlive: boolean;
30
+ };
31
+
32
+ /**
33
+ * Properties for connection configuration.
34
+ * @typedef ConnectionProp
35
+ * @property {number} lostConnectionRecoveryTimeout - Timeout in milliseconds for lost connection recovery.
36
+ * @ignore
37
+ */
38
+ export type ConnectionProp = {
39
+ lostConnectionRecoveryTimeout: number;
40
+ };
@@ -0,0 +1,71 @@
1
+ import routingAgent from './agent';
2
+ import routingContact from './task/contact';
3
+ import AgentConfigService from './config';
4
+ import AqmReqs from './core/aqm-reqs';
5
+ import {WebSocketManager} from './core/websocket/WebSocketManager';
6
+ import {ConnectionService} from './core/websocket/connection-service';
7
+ import {WebexSDK, SubscribeRequest} from '../types';
8
+ import aqmDialer from './task/dialer';
9
+
10
+ /**
11
+ * Services class provides centralized access to all contact center plugin services
12
+ * using a singleton pattern to ensure a single instance throughout the application.
13
+ * @private
14
+ * @ignore
15
+ * @class
16
+ */
17
+ export default class Services {
18
+ /** Agent services for managing agent state and capabilities */
19
+ public readonly agent: ReturnType<typeof routingAgent>;
20
+ /** Configuration services for agent settings */
21
+ public readonly config: AgentConfigService;
22
+ /** Contact services for managing customer interactions */
23
+ public readonly contact: ReturnType<typeof routingContact>;
24
+ /** Dialer services for outbound calling features */
25
+ public readonly dialer: ReturnType<typeof aqmDialer>;
26
+ /** WebSocket manager for handling real-time communications */
27
+ public readonly webSocketManager: WebSocketManager;
28
+ /** Connection service for managing websocket connections */
29
+ public readonly connectionService: ConnectionService;
30
+ /** Singleton instance of the Services class */
31
+ private static instance: Services;
32
+
33
+ /**
34
+ * Creates a new Services instance
35
+ * @param options - Configuration options
36
+ * @param options.webex - WebexSDK instance
37
+ * @param options.connectionConfig - Subscription configuration for websocket connection
38
+ */
39
+ constructor(options: {webex: WebexSDK; connectionConfig: SubscribeRequest}) {
40
+ const {webex, connectionConfig} = options;
41
+ this.webSocketManager = new WebSocketManager({webex});
42
+ const aqmReq = new AqmReqs(this.webSocketManager);
43
+ this.config = new AgentConfigService();
44
+ this.agent = routingAgent(aqmReq);
45
+ this.contact = routingContact(aqmReq);
46
+ this.dialer = aqmDialer(aqmReq);
47
+ this.connectionService = new ConnectionService({
48
+ webSocketManager: this.webSocketManager,
49
+ subscribeRequest: connectionConfig,
50
+ });
51
+ }
52
+
53
+ /**
54
+ * Gets singleton instance of Services class
55
+ * Creates a new instance if one doesn't exist
56
+ * @param options - Configuration options
57
+ * @param options.webex - WebexSDK instance
58
+ * @param options.connectionConfig - Subscription configuration for websocket connection
59
+ * @returns The singleton Services instance
60
+ */
61
+ public static getInstance(options: {
62
+ webex: WebexSDK;
63
+ connectionConfig: SubscribeRequest;
64
+ }): Services {
65
+ if (!this.instance) {
66
+ this.instance = new Services(options);
67
+ }
68
+
69
+ return this.instance;
70
+ }
71
+ }
@@ -0,0 +1,86 @@
1
+ import LoggerProxy from '../../logger-proxy';
2
+
3
+ /**
4
+ * AutoWrapup class implements a timer for automatic wrap-up functionality.
5
+ * It handles timing the wrap-up period and executing a callback when the timer completes.
6
+ */
7
+ export default class AutoWrapup {
8
+ private timer: ReturnType<typeof setTimeout> | null = null;
9
+ private startTime = 0;
10
+ private readonly interval: number;
11
+ public allowCancelAutoWrapup = false;
12
+
13
+ /**
14
+ * Creates a new AutoWrapup timer
15
+ * @param interval - Time in milliseconds before auto wrap-up executes
16
+ * @param allowCancelAutoWrapup - Whether to allow canceling the auto wrap-up
17
+ */
18
+ constructor(interval: number, allowCancelAutoWrapup = false) {
19
+ this.interval = interval;
20
+ this.allowCancelAutoWrapup = allowCancelAutoWrapup;
21
+ }
22
+
23
+ /**
24
+ * Starts the auto wrap-up timer
25
+ * @param onComplete - Callback function to execute when timer completes
26
+ */
27
+ public start(onComplete: () => void): void {
28
+ LoggerProxy.info('AutoWrapup: clear called', {
29
+ module: 'AutoWrapup',
30
+ method: 'clear',
31
+ });
32
+
33
+ if (this.timer) {
34
+ this.clear();
35
+ }
36
+
37
+ this.startTime = Date.now();
38
+
39
+ this.timer = setTimeout(() => {
40
+ onComplete();
41
+ this.timer = null;
42
+ }, this.interval);
43
+ }
44
+
45
+ /**
46
+ * Clears the auto wrap-up timer if it's running
47
+ */
48
+ public clear(): void {
49
+ LoggerProxy.info('AutoWrapup: clear called', {
50
+ module: 'AutoWrapup',
51
+ method: 'clear',
52
+ });
53
+
54
+ if (this.timer) {
55
+ clearTimeout(this.timer);
56
+ this.timer = null;
57
+ this.startTime = 0;
58
+ }
59
+ }
60
+
61
+ /**
62
+ * Gets the remaining time in milliseconds
63
+ * @returns Time left in milliseconds
64
+ */
65
+ public getTimeLeft(): number {
66
+ const elapsed = Date.now() - this.startTime;
67
+
68
+ return Math.max(0, this.interval - elapsed);
69
+ }
70
+
71
+ /**
72
+ * Checks if the timer is currently running
73
+ * @returns True if the timer is running, false otherwise
74
+ */
75
+ public isRunning(): boolean {
76
+ return this.timer !== null;
77
+ }
78
+
79
+ /**
80
+ * Gets the remaining time in seconds (rounded)
81
+ * @returns Time left in seconds
82
+ */
83
+ public getTimeLeftSeconds(): number {
84
+ return Math.ceil(this.getTimeLeft() / 1000);
85
+ }
86
+ }