@voicenter-team/events-sdk 0.0.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 (60) hide show
  1. package/.eslintrc.cjs +15 -0
  2. package/.github/workflows/main.yml +16 -0
  3. package/.idea/VoicenterEventsSDK.iml +12 -0
  4. package/.idea/git_toolbox_prj.xml +15 -0
  5. package/.idea/inspectionProfiles/Project_Default.xml +6 -0
  6. package/.idea/jsLibraryMappings.xml +6 -0
  7. package/.idea/jsLinters/eslint.xml +7 -0
  8. package/.idea/modules.xml +8 -0
  9. package/.idea/vcs.xml +6 -0
  10. package/.nvmrc +1 -0
  11. package/TODELETE_TEMP/events.json +69122 -0
  12. package/TODELETE_TEMP/temphelper.cjs +101 -0
  13. package/dist/voicenter-events-sdk.cjs.js +48 -0
  14. package/dist/voicenter-events-sdk.cjs.js.map +1 -0
  15. package/dist/voicenter-events-sdk.d.ts +510 -0
  16. package/dist/voicenter-events-sdk.es.js +6350 -0
  17. package/dist/voicenter-events-sdk.es.js.map +1 -0
  18. package/dist/voicenter-events-sdk.iife.js +48 -0
  19. package/dist/voicenter-events-sdk.iife.js.map +1 -0
  20. package/dist/voicenter-events-sdk.umd.js +48 -0
  21. package/dist/voicenter-events-sdk.umd.js.map +1 -0
  22. package/docs/package-lock.json +3820 -0
  23. package/docs/package.json +25 -0
  24. package/docs/src/.vuepress/client.js +8 -0
  25. package/docs/src/.vuepress/components/Demo.vue +181 -0
  26. package/docs/src/.vuepress/config.js +60 -0
  27. package/docs/src/.vuepress/public/favicon.ico +0 -0
  28. package/docs/src/.vuepress/public/images/logo.png +0 -0
  29. package/docs/src/.vuepress/styles/index.scss +0 -0
  30. package/docs/src/.vuepress/styles/index.styl +8 -0
  31. package/docs/src/.vuepress/styles/palette.styl +10 -0
  32. package/docs/src/demo.md +7 -0
  33. package/docs/src/index.md +4 -0
  34. package/jest.config.js +11 -0
  35. package/package.json +54 -0
  36. package/src/classes/auth/auth.class.ts +196 -0
  37. package/src/classes/auth/auth.test.ts +14 -0
  38. package/src/classes/events-sdk/events-sdk-default-options.ts +52 -0
  39. package/src/classes/events-sdk/events-sdk.class.ts +237 -0
  40. package/src/classes/events-sdk/events-sdk.test.ts +9 -0
  41. package/src/classes/events-sdk/events-sdk.types.ts +77 -0
  42. package/src/classes/socket-io/socket-io.class.ts +166 -0
  43. package/src/classes/socket-io/socket-io.d.ts +10 -0
  44. package/src/classes/socket-io/versions/index.ts +52 -0
  45. package/src/classes/socket-io/versions/v1_3_7.js +2083 -0
  46. package/src/enum/events.enum.ts +96 -0
  47. package/src/index.ts +3 -0
  48. package/src/types/auth.d.ts +18 -0
  49. package/src/types/events.common.d.ts +110 -0
  50. package/src/types/events.d.ts +160 -0
  51. package/src/types/listeners.d.ts +37 -0
  52. package/src/types/public-api.d.ts +39 -0
  53. package/src/types/socket.d.ts +5 -0
  54. package/swagger/generated/Swagger.json +1 -0
  55. package/swagger/index.js +60 -0
  56. package/swagger/package.json +21 -0
  57. package/swagger/scripts/update-swagger-json.js +53 -0
  58. package/swagger/yarn.lock +2100 -0
  59. package/tsconfig.json +50 -0
  60. package/vite.config.ts +41 -0
@@ -0,0 +1,237 @@
1
+ import AuthClass from '@/classes/auth/auth.class'
2
+ import { debounce } from 'lodash'
3
+ import { eventsSdkDefaultOptions } from '@/classes/events-sdk/events-sdk-default-options'
4
+ import { SocketIoClass } from '@/classes/socket-io/socket-io.class'
5
+ import { EventsSdkOptions, ReconnectOptions, Server, ServerParameter } from '@/classes/events-sdk/events-sdk.types'
6
+ import { SocketTyped } from '@/types/socket'
7
+ import {
8
+ GenericEventWrapper,
9
+ EventSpecificCallback,
10
+ EventCallbackListenersMap,
11
+ EventTypeData,
12
+ EventTypeNames,
13
+ } from '@/types/events'
14
+ import { EventsEnum } from '@/enum/events.enum'
15
+
16
+ class EventsSdkClass{
17
+ constructor (options: EventsSdkOptions) {
18
+ this.options = {
19
+ ...eventsSdkDefaultOptions,
20
+ ...options
21
+ }
22
+
23
+ this.server = this.options.fallbackServer
24
+
25
+ this.argumentOptions = {
26
+ ...options
27
+ }
28
+ }
29
+
30
+ private argumentOptions: EventsSdkOptions
31
+ public readonly options: EventsSdkOptions = {
32
+ ...eventsSdkDefaultOptions
33
+ }
34
+ public servers: Server[] = []
35
+ public server: Server
36
+ public socket: SocketTyped | undefined
37
+
38
+ public authClass = new AuthClass(this)
39
+ public socketIoClass = new SocketIoClass(this)
40
+
41
+ public reconnectOptions: ReconnectOptions = {
42
+ retryCount: 1,
43
+ maxReconnectAttempts: this.options.maxReconnectAttempts,
44
+ reconnectionDelay: this.options.reconnectionDelay, // 10 seconds. After each re-connection attempt this number will increase (minReconnectionDelay * attempts) => 10, 20, 30, 40 seconds ... up to 5min
45
+ minReconnectionDelay: this.options.reconnectionDelay, // 10 seconds
46
+ maxReconnectionDelay: 60000 * 5 // 5 minutes
47
+ }
48
+
49
+ public retryConnection = debounce(this.connect.bind(this), this.reconnectOptions.reconnectionDelay, {
50
+ leading: true,
51
+ trailing: false
52
+ })
53
+
54
+ private listeners: EventCallbackListenersMap = {
55
+ [EventsEnum.ALL_EXTENSION_STATUS]: [],
56
+ [EventsEnum.ALL_DIALER_STATUS]: [],
57
+ [EventsEnum.ALL_USERS_STATUS]: [],
58
+ [EventsEnum.QUEUE_EVENT]: [],
59
+ [EventsEnum.EXTENSION_EVENT]: [],
60
+ [EventsEnum.LOGIN_SUCCESS]: [],
61
+ [EventsEnum.LOGIN_STATUS]: [],
62
+ [EventsEnum.KEEP_ALIVE_RESPONSE]: [],
63
+ [EventsEnum.ONLINE_STATUS_EVENT]: []
64
+ }
65
+ private allListeners: Array<(data: GenericEventWrapper) => void> = []
66
+
67
+ public on<T extends EventTypeNames> (event: T, callback: EventSpecificCallback<T>): void
68
+ public on (event: '*', callback: (data: GenericEventWrapper) => void): void
69
+ public on (event: unknown, callback: unknown) {
70
+ if (event === '*') {
71
+ this.allListeners.push(callback as (data: GenericEventWrapper) => void)
72
+ } else {
73
+ // Handle specific event type with strong typing
74
+ this.listeners[event as EventTypeNames].push(callback as EventSpecificCallback<EventTypeNames>)
75
+ }
76
+ }
77
+
78
+ public off<T extends EventTypeNames> (event: T, callback: EventSpecificCallback<T>): void
79
+ public off (event: '*', callback: (data: GenericEventWrapper) => void): void
80
+ public off (event: unknown, callback: unknown) {
81
+ if (event === '*') {
82
+ this.allListeners = this.allListeners.filter(item => item !== callback)
83
+ } else {
84
+ const data = this.listeners[event as EventTypeNames] as Array<EventSpecificCallback<EventTypeNames>>
85
+ const filtered = data.filter(item => item !== callback)
86
+
87
+ this.listeners = {
88
+ ...this.listeners,
89
+ [event as EventTypeNames]: filtered
90
+ }
91
+ }
92
+ }
93
+
94
+ public emit <T extends EventTypeNames> (event: T, data: EventTypeData<T>) {
95
+ this.socketIoClass.lastEventTimestamp = new Date().getTime()
96
+
97
+ this.listeners[event].forEach(callback => callback({
98
+ name: event,
99
+ data
100
+ }))
101
+
102
+ const allEventData: GenericEventWrapper = {
103
+ name: event,
104
+ data: data as any
105
+ }
106
+
107
+ this.allListeners.forEach((callback) => callback(allEventData))
108
+ }
109
+
110
+ public connect (server: ServerParameter = ServerParameter.DEFAULT, skipLogin = false) {
111
+ let serverToConnect: Server | undefined
112
+
113
+ if (server === ServerParameter.DEFAULT) {
114
+ serverToConnect = this.findCurrentServer()
115
+ }
116
+
117
+ if (server === ServerParameter.NEXT) {
118
+ serverToConnect = this.findNextAvailableServer()
119
+ }
120
+
121
+ if (server === ServerParameter.PREVIOUS) {
122
+ serverToConnect = this.findMaxPriorityServer()
123
+ }
124
+
125
+ if (!serverToConnect) {
126
+ this.server = this.findCurrentServer()
127
+ }
128
+
129
+ this.socketIoClass.initSocketConnection()
130
+
131
+ this.socketIoClass.initSocketEvents()
132
+
133
+ this.socketIoClass.initKeepAlive()
134
+
135
+ if (skipLogin) {
136
+ return
137
+ }
138
+ }
139
+
140
+ private findCurrentServer (): Server {
141
+ if (this.servers.length) {
142
+ this.server = this.servers[0]
143
+ }
144
+ if (!this.server) {
145
+ this.server = this.options.fallbackServer
146
+ }
147
+ return this.server
148
+ }
149
+
150
+ private findNextAvailableServer (): Server {
151
+ // this.log(INFO, 'Failover -> Trying to find another server');
152
+
153
+ const currentServerPriority = this.server.Priority
154
+
155
+ const nextServerPriority = currentServerPriority + 1
156
+
157
+ const nextServer = this.servers.find(server => server.Priority === nextServerPriority) || this.findMinPriorityServer()
158
+
159
+ this.server = { ...nextServer }
160
+
161
+ // this.log(INFO, 'Failover -> Found new server. Connecting to it...', this.server);
162
+
163
+ return this.server
164
+ }
165
+
166
+ private findMaxPriorityServer (): Server {
167
+ // this.log(INFO, 'Fallback -> Trying to find previous server');
168
+
169
+ const maxPriorityServer = this.getServerWithHighestPriority(this.servers)
170
+
171
+ if (!this.server) {
172
+ this.server = maxPriorityServer
173
+
174
+ return this.server
175
+ }
176
+
177
+ if (this.server && maxPriorityServer.Domain !== this.server.Domain) {
178
+ this.server = maxPriorityServer
179
+
180
+ // this.log(INFO, 'Fallback -> Trying to find previous server');
181
+
182
+ return this.server
183
+ }
184
+
185
+ return this.server
186
+ }
187
+
188
+ private findMinPriorityServer (): Server {
189
+ const minPriority = Math.min(...this.servers.map(server => server.Priority))
190
+
191
+ const server = this.servers.find(server => server.Priority === minPriority)
192
+
193
+ if (server) {
194
+ this.server = server
195
+
196
+ return this.server
197
+ }
198
+
199
+ return this.server
200
+ }
201
+
202
+ public getServerWithHighestPriority (servers: Server[]): Server {
203
+ let chosenServer: Server | undefined
204
+
205
+ let maxPriority = Number.MAX_SAFE_INTEGER
206
+
207
+ chosenServer = servers.find(server => {
208
+ if (server.Priority < maxPriority) {
209
+ maxPriority = server.Priority
210
+
211
+ chosenServer = server
212
+ }
213
+ })
214
+
215
+ return chosenServer ? chosenServer : this.server
216
+ }
217
+
218
+ public async init () {
219
+ if (this.socket) {
220
+ // this.emit(eventTypes.CLOSE);
221
+ }
222
+
223
+ await this.authClass.login(this.options)
224
+
225
+ this.getServers()
226
+
227
+ return true
228
+ }
229
+
230
+ private getServers () {
231
+ if (this.options.serverFetchStrategy === 'static' && this.argumentOptions.servers && Array.isArray(this.argumentOptions.servers) && this.argumentOptions.servers.length > 1) {
232
+ this.servers = this.argumentOptions.servers
233
+ }
234
+ }
235
+ }
236
+
237
+ export default EventsSdkClass
@@ -0,0 +1,9 @@
1
+ import EventsSdkClass from '@/classes/events-sdk/events-sdk.class'
2
+ import { eventsSdkDefaultOptions } from '@/classes/events-sdk/events-sdk-default-options'
3
+
4
+ describe('EventsSdkClass', () => {
5
+ it('should be true', () => {
6
+ const eventsSdkClass = new EventsSdkClass(eventsSdkDefaultOptions)
7
+ expect(eventsSdkClass.init()).toBe(true)
8
+ })
9
+ })
@@ -0,0 +1,77 @@
1
+ export interface EventsSdkOptions {
2
+ url?: string,
3
+ environment?: string,
4
+ fallbackServer: Server,
5
+ loginUrl: string,
6
+ refreshTokenUrl?: string,
7
+ refreshToken?: string,
8
+ servers?: string,
9
+ token: string,
10
+ tokenExpiry?: Date,
11
+ loginType: string,
12
+ forceNew?: boolean,
13
+ reconnectionDelay: number,
14
+ reconnectionDelayMax?: number,
15
+ maxReconnectAttempts: number,
16
+ timeout?: number,
17
+ keepAliveTimeout: number,
18
+ idleInterval?: number,
19
+ protocol: string,
20
+ transports?: string[],
21
+ upgrade?: boolean,
22
+ store?: string,
23
+ extensionsModuleName?: string,
24
+ queuesModuleName?: string,
25
+ dialersModuleName?: string,
26
+ serverFetchStrategy?: string,
27
+ serverType?: number,
28
+ useLogger?: boolean,
29
+ loggerSocketConnection?: string,
30
+ loggerServer?: string,
31
+ loggerConfig?: LoggerConfig,
32
+ loggerConnectOptions?: LoggerConnectOptions,
33
+ email: string,
34
+ password: string,
35
+ username: string
36
+ }
37
+
38
+ export enum Environment {
39
+ BROWSER = 'browser',
40
+ CHROME_EXTENSION = 'chrome-extension'
41
+ }
42
+
43
+ export interface Server {
44
+ Priority: number,
45
+ Domain: string
46
+ }
47
+
48
+ export interface LoggerConfig {
49
+ logToConsole?: boolean,
50
+ overloadGlobalConsole?: boolean,
51
+ namespace?: string,
52
+ socketEmitInterval?: number
53
+ }
54
+
55
+ export interface LoggerConnectOptions {
56
+ reconnection?: boolean,
57
+ reconnectionDelay?: number,
58
+ reconnectionAttempts?: number,
59
+ perMessageDeflate?: boolean,
60
+ upgrade?: boolean,
61
+ transports?: string[],
62
+ debug?: boolean
63
+ }
64
+
65
+ export interface ReconnectOptions {
66
+ retryCount: number,
67
+ maxReconnectAttempts: number,
68
+ reconnectionDelay: number,
69
+ minReconnectionDelay: number,
70
+ maxReconnectionDelay: number
71
+ }
72
+
73
+ export enum ServerParameter {
74
+ DEFAULT = 'default',
75
+ NEXT = 'next',
76
+ PREVIOUS = 'previous'
77
+ }
@@ -0,0 +1,166 @@
1
+ import { ManagerOptions, SocketOptions } from 'socket.io-client'
2
+ import EventsSdkClass from '@/classes/events-sdk/events-sdk.class'
3
+ import sockets, { TypedSocketIo } from '@/classes/socket-io/versions'
4
+ import { SocketTyped } from '@/types/socket'
5
+ import { Environment, ServerParameter } from '@/classes/events-sdk/events-sdk.types'
6
+ import { EventsEnum } from '@/enum/events.enum'
7
+ import { KeepAliveResponseEvent } from '@/types/events'
8
+
9
+ export class SocketIoClass{
10
+ constructor (private readonly eventsSdkClass: EventsSdkClass) {
11
+ this.eventsSdkClass = eventsSdkClass
12
+ }
13
+
14
+ public io: SocketTyped | undefined
15
+ public ioFunction: TypedSocketIo | undefined
16
+ public lastEventTimestamp = new Date().getTime()
17
+ private keepAliveInterval: ReturnType<typeof setInterval> | undefined
18
+ private keepReconnectInterval: ReturnType<typeof setInterval> | undefined
19
+ private connected = false
20
+
21
+ public getSocketIoFunction (Client: string) {
22
+ const parsedArray = Client.split('v=')
23
+
24
+ const version = 'v'
25
+ .concat(parsedArray[parsedArray.length - 1])
26
+ .replaceAll('.', '_')
27
+
28
+ this.ioFunction = sockets.getSocketVersion(version)
29
+ }
30
+
31
+ public initSocketConnection () {
32
+ const token = this.eventsSdkClass.authClass.token
33
+
34
+ const protocol = this.eventsSdkClass.options.protocol
35
+
36
+ const server = this.eventsSdkClass.server
37
+
38
+ try {
39
+ const domain = server.Domain
40
+
41
+ const url = `${protocol}://${domain}`
42
+
43
+ // this.log(INFO, 'Connecting to..', url);
44
+
45
+ const options: Partial<ManagerOptions & SocketOptions> = {
46
+ reconnection: false,
47
+ upgrade: false,
48
+ transports: [ 'websocket' ],
49
+ forceNew: true,
50
+ query: {
51
+ token
52
+ }
53
+ }
54
+
55
+ if (token) {
56
+ options.query = {
57
+ token
58
+ }
59
+ }
60
+
61
+ if (this.ioFunction) {
62
+ this.io = this.ioFunction(url, options)
63
+ }
64
+ } catch (e) {
65
+ // this.log(ERROR, e);
66
+ }
67
+ }
68
+
69
+ public initSocketEvents () {
70
+ if (this.io) {
71
+ this.io
72
+ .on(EventsEnum.LOGIN_SUCCESS, (data) => this.eventsSdkClass.emit(EventsEnum.LOGIN_SUCCESS, data))
73
+ .on(EventsEnum.QUEUE_EVENT, (data) => this.eventsSdkClass.emit(EventsEnum.QUEUE_EVENT, data))
74
+ .on(EventsEnum.EXTENSION_EVENT, (data) => this.eventsSdkClass.emit(EventsEnum.EXTENSION_EVENT, data))
75
+ .on(EventsEnum.LOGIN_STATUS, (data) => this.eventsSdkClass.emit(EventsEnum.LOGIN_STATUS, data))
76
+ .on(EventsEnum.ALL_EXTENSION_STATUS, (data) => this.eventsSdkClass.emit(EventsEnum.ALL_EXTENSION_STATUS, data))
77
+ .on(EventsEnum.ALL_DIALER_STATUS, (data) => this.eventsSdkClass.emit(EventsEnum.ALL_DIALER_STATUS, data))
78
+ .on(EventsEnum.KEEP_ALIVE_RESPONSE, (data) => this.onKeepAliveResponse(data))
79
+ .on(EventsEnum.CONNECT, () => this.onConnect())
80
+ .on(EventsEnum.DISCONNECT, () => this.onDisconnect())
81
+ }
82
+ }
83
+
84
+ public initKeepAlive () {
85
+ if (this.keepAliveInterval) {
86
+ clearInterval(this.keepAliveInterval)
87
+ }
88
+
89
+ this.keepAliveInterval = setInterval(async () => {
90
+ const now = new Date().getTime()
91
+
92
+ // if (now > this.lastEventTimestamp + delta) {
93
+ // this.eventsSdkClass.connect(ServerParameter.DEFAULT, true)
94
+ //
95
+ // return
96
+ // }
97
+ //
98
+ // if (!this.io) {
99
+ // this.initSocketConnection()
100
+ //
101
+ // return
102
+ // }
103
+
104
+ if (now > this.lastEventTimestamp + this.eventsSdkClass.options.keepAliveTimeout && this.io) {
105
+ this.io.emit(EventsEnum.KEEP_ALIVE, this.eventsSdkClass.authClass.token)
106
+
107
+ return
108
+ }
109
+
110
+ }, this.eventsSdkClass.options.keepAliveTimeout)
111
+ }
112
+
113
+ public closeAllConnections () {
114
+ if (this.io) {
115
+ this.io.close()
116
+
117
+ this.io.disconnect()
118
+
119
+ this.io = undefined
120
+ }
121
+
122
+ if (this.eventsSdkClass.options.environment === Environment.BROWSER && window) {
123
+ window.sessionStorage.clear()
124
+ }
125
+ if (this.eventsSdkClass.options.environment === Environment.CHROME_EXTENSION && chrome) {
126
+ chrome.storage.session.clear()
127
+ }
128
+ }
129
+
130
+ private onKeepAliveResponse (data: KeepAliveResponseEvent) {
131
+ if (data.errorCode) {
132
+ this.initSocketConnection()
133
+
134
+ return
135
+ }
136
+
137
+ if (this.connected) {
138
+ this.lastEventTimestamp = new Date().getTime()
139
+ } else {
140
+ this.initSocketConnection()
141
+ }
142
+ }
143
+
144
+ private onConnect () {
145
+ if (this.keepReconnectInterval) {
146
+ clearInterval(this.keepReconnectInterval)
147
+ }
148
+
149
+ this.connected = true
150
+
151
+ this.eventsSdkClass.emit(EventsEnum.ONLINE_STATUS_EVENT, { isSocketConnected: true })
152
+ }
153
+
154
+ private onDisconnect () {
155
+ this.connected = false
156
+
157
+ this.closeAllConnections()
158
+
159
+ this.eventsSdkClass.emit(EventsEnum.ONLINE_STATUS_EVENT, { isSocketConnected: false })
160
+
161
+ this.keepReconnectInterval = setInterval(() => {
162
+ console.log('attempt to connect...')
163
+ this.eventsSdkClass.connect(ServerParameter.NEXT, true)
164
+ }, 15000)
165
+ }
166
+ }
@@ -0,0 +1,10 @@
1
+ export interface SocketIoOptions {
2
+ reconnection: boolean,
3
+ perMessageDeflate: boolean,
4
+ upgrade: boolean,
5
+ transports: string[],
6
+ debug: boolean,
7
+ query: {
8
+ token: string
9
+ }
10
+ }
@@ -0,0 +1,52 @@
1
+ import { io } from 'socket.io-client'
2
+ import { SocketTyped } from '@/types/socket'
3
+
4
+ const importModules: Record<string, { default?: unknown }> = import.meta.glob(
5
+ './v*.js',
6
+ { eager: true }
7
+ )
8
+
9
+ const SOCKET_NAME_REGEX = /v\d+_\d+_\d+/
10
+
11
+ export type TypedSocketIo = (...args: Parameters<typeof io>) => SocketTyped
12
+
13
+ type SocketIoFn = () => TypedSocketIo
14
+
15
+ function isSocketIoFn (socket: unknown): socket is SocketIoFn {
16
+ return typeof socket === 'function'
17
+ }
18
+
19
+ const sockets = Object.entries(importModules)
20
+ .reduce<Record<string, TypedSocketIo>>(
21
+ (acc, currentValue) => {
22
+ const module = currentValue[1].default
23
+ const moduleName = currentValue[0].match(SOCKET_NAME_REGEX)?.[0]
24
+
25
+ if (isSocketIoFn(module) && moduleName) {
26
+ acc[moduleName] = module()
27
+ }
28
+
29
+ return acc
30
+ },
31
+ {}
32
+ )
33
+
34
+ const getSocketVersion = (version: string) => {
35
+ if (version in sockets) {
36
+ return sockets[version]
37
+ } else {
38
+ throw new Error(`Socket version ${version} not found`)
39
+ }
40
+ }
41
+
42
+ const makeSocketVersion = (version: string, ...args: Parameters<typeof io>) => {
43
+ const socket = getSocketVersion(version)
44
+
45
+ return socket(...args)
46
+ }
47
+
48
+ export default {
49
+ ...sockets,
50
+ getSocketVersion,
51
+ makeSocketVersion
52
+ }