@signalwire/js 3.26.0 → 3.27.0-dev.202404301530.94a97d7.0
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/dist/core/src/BaseComponent.d.ts +10 -0
- package/dist/core/src/BaseComponent.d.ts.map +1 -1
- package/dist/core/src/BaseJWTSession.d.ts.map +1 -1
- package/dist/core/src/BaseSession.d.ts +3 -0
- package/dist/core/src/BaseSession.d.ts.map +1 -1
- package/dist/core/src/RPCMessages/RPCConnect.d.ts +14 -0
- package/dist/core/src/RPCMessages/RPCConnect.d.ts.map +1 -1
- package/dist/core/src/index.d.ts +4 -3
- package/dist/core/src/index.d.ts.map +1 -1
- package/dist/core/src/memberPosition/workers.d.ts.map +1 -1
- package/dist/core/src/redux/index.d.ts +5 -0
- package/dist/core/src/redux/index.d.ts.map +1 -1
- package/dist/core/src/redux/interfaces.d.ts +2 -0
- package/dist/core/src/redux/interfaces.d.ts.map +1 -1
- package/dist/core/src/redux/utils/useInstanceMap.d.ts +2 -0
- package/dist/core/src/redux/utils/useInstanceMap.d.ts.map +1 -1
- package/dist/core/src/rooms/RoomSessionMember.d.ts +39 -0
- package/dist/core/src/rooms/RoomSessionMember.d.ts.map +1 -0
- package/dist/core/src/rooms/index.d.ts +1 -0
- package/dist/core/src/rooms/index.d.ts.map +1 -1
- package/dist/core/src/rooms/methods.d.ts +2 -2
- package/dist/core/src/rooms/methods.d.ts.map +1 -1
- package/dist/core/src/testUtils.d.ts +8 -0
- package/dist/core/src/testUtils.d.ts.map +1 -1
- package/dist/core/src/types/callSegment.d.ts +21 -0
- package/dist/core/src/types/callSegment.d.ts.map +1 -0
- package/dist/core/src/types/callfabric.d.ts +337 -16
- package/dist/core/src/types/callfabric.d.ts.map +1 -1
- package/dist/core/src/types/conversation.d.ts +24 -0
- package/dist/core/src/types/conversation.d.ts.map +1 -0
- package/dist/core/src/types/index.d.ts +15 -1
- package/dist/core/src/types/index.d.ts.map +1 -1
- package/dist/core/src/types/unified.d.ts +36 -0
- package/dist/core/src/types/unified.d.ts.map +1 -0
- package/dist/core/src/types/utils.d.ts +3 -0
- package/dist/core/src/types/utils.d.ts.map +1 -1
- package/dist/core/src/types/videoMember.d.ts +11 -1
- package/dist/core/src/types/videoMember.d.ts.map +1 -1
- package/dist/core/src/types/videoRoomSession.d.ts +3 -0
- package/dist/core/src/types/videoRoomSession.d.ts.map +1 -1
- package/dist/core/src/utils/index.d.ts +1 -0
- package/dist/core/src/utils/index.d.ts.map +1 -1
- package/dist/core/src/utils/interfaces.d.ts +16 -9
- package/dist/core/src/utils/interfaces.d.ts.map +1 -1
- package/dist/core/src/utils/mapObject.d.ts +7 -0
- package/dist/core/src/utils/mapObject.d.ts.map +1 -0
- package/dist/core/src/utils/mapObject.test.d.ts +2 -0
- package/dist/core/src/utils/mapObject.test.d.ts.map +1 -0
- package/dist/core/src/workers/executeActionWorker.d.ts.map +1 -1
- package/dist/index.esm.js +1352 -527
- package/dist/index.esm.js.map +3 -3
- package/dist/index.js +1448 -642
- package/dist/index.js.map +3 -3
- package/dist/index.umd.js +3 -3
- package/dist/index.umd.js.map +1 -1
- package/dist/js/src/BaseRoomSession.d.ts +6 -4
- package/dist/js/src/BaseRoomSession.d.ts.map +1 -1
- package/dist/js/src/Client.d.ts +1 -0
- package/dist/js/src/Client.d.ts.map +1 -1
- package/dist/js/src/JWTSession.d.ts.map +1 -1
- package/dist/js/src/UnifiedJWTSession.d.ts +16 -0
- package/dist/js/src/UnifiedJWTSession.d.ts.map +1 -0
- package/dist/js/src/fabric/CallFabricBaseRoomSession.d.ts +30 -0
- package/dist/js/src/fabric/CallFabricBaseRoomSession.d.ts.map +1 -0
- package/dist/js/src/fabric/CallSegment.d.ts +26 -0
- package/dist/js/src/fabric/CallSegment.d.ts.map +1 -0
- package/dist/js/src/fabric/Conversation.d.ts +144 -0
- package/dist/js/src/fabric/Conversation.d.ts.map +1 -0
- package/dist/js/src/fabric/ConversationAPI.d.ts +61 -0
- package/dist/js/src/fabric/ConversationAPI.d.ts.map +1 -0
- package/dist/js/src/fabric/HTTPClient.d.ts +45 -27
- package/dist/js/src/fabric/HTTPClient.d.ts.map +1 -1
- package/dist/js/src/fabric/IncomingCallManager.d.ts +14 -0
- package/dist/js/src/fabric/IncomingCallManager.d.ts.map +1 -0
- package/dist/js/src/fabric/SignalWire.d.ts +1 -16
- package/dist/js/src/fabric/SignalWire.d.ts.map +1 -1
- package/dist/js/src/fabric/WSClient.d.ts +23 -28
- package/dist/js/src/fabric/WSClient.d.ts.map +1 -1
- package/dist/js/src/fabric/createHttpClient.d.ts +1 -0
- package/dist/js/src/fabric/createHttpClient.d.ts.map +1 -1
- package/dist/js/src/fabric/index.d.ts +3 -0
- package/dist/js/src/fabric/index.d.ts.map +1 -1
- package/dist/js/src/fabric/types.d.ts +93 -0
- package/dist/js/src/fabric/types.d.ts.map +1 -0
- package/dist/js/src/fabric/workers/callFabricWorker.d.ts +7 -0
- package/dist/js/src/fabric/workers/callFabricWorker.d.ts.map +1 -0
- package/dist/js/src/fabric/workers/callJoinWorker.d.ts +4 -0
- package/dist/js/src/fabric/workers/callJoinWorker.d.ts.map +1 -0
- package/dist/js/src/fabric/workers/callLeftWorker.d.ts +4 -0
- package/dist/js/src/fabric/workers/callLeftWorker.d.ts.map +1 -0
- package/dist/js/src/fabric/workers/callStateWorker.d.ts +4 -0
- package/dist/js/src/fabric/workers/callStateWorker.d.ts.map +1 -0
- package/dist/js/src/fabric/workers/conversationWorker.d.ts +4 -0
- package/dist/js/src/fabric/workers/conversationWorker.d.ts.map +1 -0
- package/dist/js/src/fabric/workers/index.d.ts +6 -0
- package/dist/js/src/fabric/workers/index.d.ts.map +1 -0
- package/dist/js/src/fabric/workers/mappers/unifiedEventsMapper.d.ts +3 -0
- package/dist/js/src/fabric/workers/mappers/unifiedEventsMapper.d.ts.map +1 -0
- package/dist/js/src/fabric/workers/unifiedEventsWatcher.d.ts +7 -0
- package/dist/js/src/fabric/workers/unifiedEventsWatcher.d.ts.map +1 -0
- package/dist/js/src/fabric/workers/unifiedTargetWorker.d.ts +3 -0
- package/dist/js/src/fabric/workers/unifiedTargetWorker.d.ts.map +1 -0
- package/dist/js/src/fabric/{WSClientWorker.d.ts → workers/wsClientWorker.d.ts} +3 -3
- package/dist/js/src/fabric/workers/wsClientWorker.d.ts.map +1 -0
- package/dist/js/src/features/mediaElements/mediaElementsSagas.d.ts.map +1 -1
- package/dist/js/src/index.d.ts +7 -8
- package/dist/js/src/index.d.ts.map +1 -1
- package/dist/js/src/testUtils.d.ts +17 -0
- package/dist/js/src/testUtils.d.ts.map +1 -1
- package/dist/js/src/utils/UnifiedRequestMapper.d.ts +4 -0
- package/dist/js/src/utils/UnifiedRequestMapper.d.ts.map +1 -0
- package/dist/js/src/utils/aspectRatioListener.d.ts +8 -0
- package/dist/js/src/utils/aspectRatioListener.d.ts.map +1 -0
- package/dist/js/src/utils/interfaces.d.ts +3 -1
- package/dist/js/src/utils/interfaces.d.ts.map +1 -1
- package/dist/js/src/utils/makeQueryParamsUrl.d.ts +9 -0
- package/dist/js/src/utils/makeQueryParamsUrl.d.ts.map +1 -0
- package/dist/js/src/utils/paginatedResult.d.ts +44 -0
- package/dist/js/src/utils/paginatedResult.d.ts.map +1 -0
- package/dist/js/src/utils/videoElement.d.ts +4 -0
- package/dist/js/src/utils/videoElement.d.ts.map +1 -1
- package/dist/js/src/video/videoMemberWorker.d.ts +6 -0
- package/dist/js/src/video/videoMemberWorker.d.ts.map +1 -0
- package/dist/js/src/video/videoRoomWorker.d.ts +4 -0
- package/dist/js/src/video/videoRoomWorker.d.ts.map +1 -0
- package/dist/js/src/video/videoWorker.d.ts.map +1 -1
- package/dist/js/src/video/videoWorkerUnifiedEventing.d.ts +4 -0
- package/dist/js/src/video/videoWorkerUnifiedEventing.d.ts.map +1 -0
- package/dist/js/src/video/workers.d.ts +5 -0
- package/dist/js/src/video/workers.d.ts.map +1 -1
- package/dist/js/tsconfig.build.tsbuildinfo +1 -1
- package/dist/webrtc/src/BaseConnection.d.ts.map +1 -1
- package/dist/webrtc/src/RTCPeer.d.ts.map +1 -1
- package/dist/webrtc/src/workers/roomSubscribedWorker.d.ts.map +1 -1
- package/package.json +6 -3
- package/src/BaseRoomSession.test.ts +3 -2
- package/src/BaseRoomSession.ts +8 -2
- package/src/Client.ts +10 -2
- package/src/JWTSession.test.ts +2 -2
- package/src/JWTSession.ts +1 -1
- package/src/UnifiedJWTSession.ts +78 -0
- package/src/fabric/CallFabricBaseRoomSession.test.ts +460 -0
- package/src/fabric/CallFabricBaseRoomSession.ts +269 -0
- package/src/fabric/CallSegment.ts +83 -0
- package/src/fabric/Conversation.test.ts +257 -0
- package/src/fabric/Conversation.ts +150 -0
- package/src/fabric/ConversationAPI.ts +44 -0
- package/src/fabric/HTTPClient.test.ts +23 -18
- package/src/fabric/HTTPClient.ts +52 -55
- package/src/fabric/IncomingCallManager.test.ts +245 -0
- package/src/fabric/IncomingCallManager.ts +89 -0
- package/src/fabric/SignalWire.ts +20 -17
- package/src/fabric/WSClient.ts +153 -117
- package/src/fabric/createHttpClient.ts +2 -0
- package/src/fabric/index.ts +3 -0
- package/src/fabric/types.ts +104 -0
- package/src/fabric/workers/callFabricWorker.ts +121 -0
- package/src/fabric/workers/callJoinWorker.ts +90 -0
- package/src/fabric/workers/callLeftWorker.ts +47 -0
- package/src/fabric/workers/callStateWorker.ts +39 -0
- package/src/fabric/workers/conversationWorker.ts +41 -0
- package/src/fabric/workers/index.ts +5 -0
- package/src/fabric/workers/mappers/unifiedEventsMapper.ts +54 -0
- package/src/fabric/workers/unifiedEventsWatcher.ts +75 -0
- package/src/fabric/workers/unifiedTargetWorker.ts +96 -0
- package/src/fabric/{WSClientWorker.ts → workers/wsClientWorker.ts} +14 -18
- package/src/features/mediaElements/mediaElementsSagas.ts +9 -15
- package/src/index.ts +25 -9
- package/src/testUtils.ts +83 -0
- package/src/utils/UnifiedRequestMapper.ts +149 -0
- package/src/utils/aspectRatioListener.ts +40 -0
- package/src/utils/interfaces.ts +3 -0
- package/src/utils/makeQueryParamsUrl.ts +14 -0
- package/src/utils/paginatedResult.ts +34 -0
- package/src/utils/videoElement.ts +4 -0
- package/src/video/videoMemberWorker.ts +107 -0
- package/src/video/videoRoomWorker.ts +103 -0
- package/src/video/videoWorker.ts +8 -3
- package/src/video/videoWorkerUnifiedEventing.ts +95 -0
- package/src/video/workers.ts +5 -0
- package/dist/js/src/fabric/WSClientWorker.d.ts.map +0 -1
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
import { HTTPClient } from './HTTPClient'
|
|
2
|
+
import { WSClient } from './WSClient'
|
|
3
|
+
import {
|
|
4
|
+
ConversationEventParams,
|
|
5
|
+
FetchConversationsResponse,
|
|
6
|
+
GetMessagesOptions,
|
|
7
|
+
GetConversationsOptions,
|
|
8
|
+
GetConversationMessagesOptions,
|
|
9
|
+
FetchConversationMessagesResponse,
|
|
10
|
+
ConversationMessage,
|
|
11
|
+
SendConversationMessageOptions,
|
|
12
|
+
SendConversationMessageResponse,
|
|
13
|
+
} from '@signalwire/core'
|
|
14
|
+
import { conversationWorker } from './workers'
|
|
15
|
+
import { buildPaginatedResult } from '../utils/paginatedResult'
|
|
16
|
+
import { makeQueryParamsUrls } from '../utils/makeQueryParamsUrl'
|
|
17
|
+
import { ConversationAPI } from './ConversationAPI'
|
|
18
|
+
|
|
19
|
+
type Callback = (event: ConversationEventParams) => unknown
|
|
20
|
+
|
|
21
|
+
interface ConversationOptions {
|
|
22
|
+
httpClient: HTTPClient
|
|
23
|
+
wsClient: WSClient
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export class Conversation {
|
|
27
|
+
private httpClient: HTTPClient
|
|
28
|
+
private wsClient: WSClient
|
|
29
|
+
private callbacks: Callback[] = []
|
|
30
|
+
|
|
31
|
+
constructor(options: ConversationOptions) {
|
|
32
|
+
this.httpClient = options.httpClient
|
|
33
|
+
this.wsClient = options.wsClient
|
|
34
|
+
|
|
35
|
+
// @ts-expect-error
|
|
36
|
+
this.wsClient.clientApi.runWorker('conversationWorker', {
|
|
37
|
+
worker: conversationWorker,
|
|
38
|
+
initialState: {
|
|
39
|
+
conversation: this,
|
|
40
|
+
},
|
|
41
|
+
})
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
public async sendMessage(options: SendConversationMessageOptions) {
|
|
45
|
+
try {
|
|
46
|
+
const { addressId, text } = options
|
|
47
|
+
const path = '/api/fabric/messages'
|
|
48
|
+
const { body } =
|
|
49
|
+
await this.httpClient.fetch<SendConversationMessageResponse>(path, {
|
|
50
|
+
method: 'POST',
|
|
51
|
+
body: {
|
|
52
|
+
conversation_id: addressId,
|
|
53
|
+
text,
|
|
54
|
+
},
|
|
55
|
+
})
|
|
56
|
+
return body
|
|
57
|
+
} catch (error) {
|
|
58
|
+
throw new Error('Error sending message to conversation!', error)
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
public async getConversations(options?: GetConversationsOptions) {
|
|
63
|
+
try {
|
|
64
|
+
const { pageSize } = options || {}
|
|
65
|
+
|
|
66
|
+
const path = '/api/fabric/conversations'
|
|
67
|
+
const queryParams = new URLSearchParams()
|
|
68
|
+
if (pageSize) {
|
|
69
|
+
queryParams.append('page_size', pageSize.toString())
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
const { body } = await this.httpClient.fetch<FetchConversationsResponse>(
|
|
73
|
+
makeQueryParamsUrls(path, queryParams)
|
|
74
|
+
)
|
|
75
|
+
const self = this
|
|
76
|
+
const data = body.data.map(
|
|
77
|
+
(conversation) => new ConversationAPI(self, conversation)
|
|
78
|
+
)
|
|
79
|
+
return buildPaginatedResult({ ...body, data }, this.httpClient.fetch)
|
|
80
|
+
} catch (error) {
|
|
81
|
+
throw new Error('Error fetching the conversation history!', error)
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
public async getMessages(options?: GetMessagesOptions) {
|
|
86
|
+
try {
|
|
87
|
+
const { pageSize } = options || {}
|
|
88
|
+
|
|
89
|
+
const path = '/api/fabric/messages'
|
|
90
|
+
const queryParams = new URLSearchParams()
|
|
91
|
+
if (pageSize) {
|
|
92
|
+
queryParams.append('page_size', pageSize.toString())
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
const { body } =
|
|
96
|
+
await this.httpClient.fetch<FetchConversationMessagesResponse>(
|
|
97
|
+
makeQueryParamsUrls(path, queryParams)
|
|
98
|
+
)
|
|
99
|
+
|
|
100
|
+
return buildPaginatedResult<ConversationMessage>(
|
|
101
|
+
body,
|
|
102
|
+
this.httpClient.fetch
|
|
103
|
+
)
|
|
104
|
+
} catch (error) {
|
|
105
|
+
throw new Error('Error fetching the conversation messages!', error)
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
public async getConversationMessages(
|
|
110
|
+
options: GetConversationMessagesOptions
|
|
111
|
+
) {
|
|
112
|
+
try {
|
|
113
|
+
const { addressId, pageSize } = options || {}
|
|
114
|
+
|
|
115
|
+
const path = `/api/fabric/conversations/${addressId}/messages`
|
|
116
|
+
const queryParams = new URLSearchParams()
|
|
117
|
+
if (pageSize) {
|
|
118
|
+
queryParams.append('page_size', pageSize.toString())
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
const { body } =
|
|
122
|
+
await this.httpClient.fetch<FetchConversationMessagesResponse>(
|
|
123
|
+
makeQueryParamsUrls(path, queryParams)
|
|
124
|
+
)
|
|
125
|
+
|
|
126
|
+
return buildPaginatedResult<ConversationMessage>(
|
|
127
|
+
body,
|
|
128
|
+
this.httpClient.fetch
|
|
129
|
+
)
|
|
130
|
+
} catch (error) {
|
|
131
|
+
throw new Error('Error fetching the conversation messages!', error)
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
public async subscribe(callback: Callback) {
|
|
136
|
+
// Connect the websocket client first
|
|
137
|
+
this.wsClient.connect()
|
|
138
|
+
|
|
139
|
+
this.callbacks.push(callback)
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/** @internal */
|
|
143
|
+
public handleEvent(event: ConversationEventParams) {
|
|
144
|
+
if (this.callbacks.length) {
|
|
145
|
+
this.callbacks.forEach((callback) => {
|
|
146
|
+
callback(event)
|
|
147
|
+
})
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { Conversation } from './Conversation'
|
|
2
|
+
import { Conversation as ConversationType } from '@signalwire/core'
|
|
3
|
+
|
|
4
|
+
export interface ConversationAPISendMessageOptions {
|
|
5
|
+
text: string
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export interface ConversationAPIGetMessagesOptions {
|
|
9
|
+
pageSize?: number
|
|
10
|
+
}
|
|
11
|
+
export class ConversationAPI {
|
|
12
|
+
|
|
13
|
+
get id() {
|
|
14
|
+
return this.data.id
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
get created_at() {
|
|
18
|
+
return this.data.created_at
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
get last_message_at() {
|
|
22
|
+
return this.data.last_message_at
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
get metadata() {
|
|
26
|
+
return this.data.metadata
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
get name() {
|
|
30
|
+
return this.data.name
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
constructor(private conversation: Conversation, private data: ConversationType) {}
|
|
34
|
+
|
|
35
|
+
sendMessage(options: ConversationAPISendMessageOptions) {
|
|
36
|
+
return this.conversation.sendMessage({
|
|
37
|
+
addressId: this.id,
|
|
38
|
+
text: options.text,
|
|
39
|
+
})
|
|
40
|
+
}
|
|
41
|
+
getMessages(options: ConversationAPIGetMessagesOptions | undefined) {
|
|
42
|
+
return this.conversation.getConversationMessages({ addressId: this.id, ...options })
|
|
43
|
+
}
|
|
44
|
+
}
|
|
@@ -1,23 +1,28 @@
|
|
|
1
|
-
import { HTTPClient } from
|
|
1
|
+
import { HTTPClient } from './HTTPClient'
|
|
2
2
|
|
|
3
3
|
describe('HTTPClient Class', () => {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
expect(client.httpHost).toEqual('fabric.swire.io');
|
|
4
|
+
it('Should return the host value from the token ch header', () => {
|
|
5
|
+
const client = new HTTPClient({
|
|
6
|
+
token:
|
|
7
|
+
'eyJhbGciOiJkaXIiLCJlbmMiOiJBMjU2R0NNIiwiY2giOiJwdWMuc3dpcmUuaW8iLCJ0eXAiOiJTQVQifQ..WI4IT6Bny7lfcU8-.lV5QlKfnONM-5FGwmkllyv747du_UB2nLGqGz3WcB4jemGjofhCzLDhJIiMzp7_xtVjHkV-K2DxiiftxWEgwo3cMn3Eo8ICqA0tZ227tGVEuOztOopsmM3CAMUDej5aovPyznw6grkQ3e7VbzwByDFxs0rS9__c1_bZrAHET1PE8AmigjN35ggY2axEHhSpo7P-vtS321Nv4qURQIococCkWhcUIr0NIbOzTDMJqGLfP2AWSFOtVd9tuyamGMZ0tSUC-JICaS-A4-JdHpKLHbaRn6XTyYj0CKeW1DdrI7uvcglVVN2ooLyWAtv__1MnGdnBoDuXKgzqd2JuiCcN3oIYLt9I3bEu2PWPu1nxumP1aJpk6VXrci0x_nRamRtr9zjVsjzK3RdhYY5Gi1q6Pf1UZvNAPv1-hF1vgthG_QLs-T76HCRm6AN0r_wS97xvBAFbSZ5rCbUR2_1fMG4YOz8dfrlF19WIzY7zaAhMhXiuX.AMbl6Ha3VmKkD40vuz3q6Q',
|
|
9
8
|
})
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
9
|
+
expect(client.httpHost).toEqual('fabric.swire.io')
|
|
10
|
+
})
|
|
11
|
+
|
|
12
|
+
it('Should return the host value from the host option', () => {
|
|
13
|
+
const client = new HTTPClient({
|
|
14
|
+
host: 'server.custom.io',
|
|
15
|
+
token:
|
|
16
|
+
'eyJhbGciOiJkaXIiLCJlbmMiOiJBMjU2R0NNIiwiY2giOiJwdWMuc3dpcmUuaW8iLCJ0eXAiOiJTQVQifQ..WI4IT6Bny7lfcU8-.lV5QlKfnONM-5FGwmkllyv747du_UB2nLGqGz3WcB4jemGjofhCzLDhJIiMzp7_xtVjHkV-K2DxiiftxWEgwo3cMn3Eo8ICqA0tZ227tGVEuOztOopsmM3CAMUDej5aovPyznw6grkQ3e7VbzwByDFxs0rS9__c1_bZrAHET1PE8AmigjN35ggY2axEHhSpo7P-vtS321Nv4qURQIococCkWhcUIr0NIbOzTDMJqGLfP2AWSFOtVd9tuyamGMZ0tSUC-JICaS-A4-JdHpKLHbaRn6XTyYj0CKeW1DdrI7uvcglVVN2ooLyWAtv__1MnGdnBoDuXKgzqd2JuiCcN3oIYLt9I3bEu2PWPu1nxumP1aJpk6VXrci0x_nRamRtr9zjVsjzK3RdhYY5Gi1q6Pf1UZvNAPv1-hF1vgthG_QLs-T76HCRm6AN0r_wS97xvBAFbSZ5rCbUR2_1fMG4YOz8dfrlF19WIzY7zaAhMhXiuX.AMbl6Ha3VmKkD40vuz3q6Q',
|
|
16
17
|
})
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
18
|
+
expect(client.httpHost).toEqual('fabric.custom.io')
|
|
19
|
+
})
|
|
20
|
+
|
|
21
|
+
it('Should base the host value from default value', () => {
|
|
22
|
+
const client = new HTTPClient({
|
|
23
|
+
token:
|
|
24
|
+
'eyJhbGciOiJkaXIiLCJlbmMiOiJBMjU2R0NNIiwidHlwIjoiU0FUIn0..HV7ITWNVgpVAXymg.7SchDC_tOtLy860sMcSpLhBjN1oBHU8ImVc6sZJBGSyDSflZoGi4sVogyK47R9sNaWS0zNBKZFBNfoFE3AeHZTIgcMgYZqS3kUsdLxZv6dNuHvO_pXOJns5OWf2B5MSHyQrNrVv-WDAaFTo2q4AIHitn5o05SEEoEB8zz52BCfFb9NmuN5MpQHH9GZBcBpRAc-fbKLgG17GqYIpRfoGCgzpvcWOCa_Auwfz9WUdSvjEcO6ZDkOsUJVx6N5oA003gwbdWtX4gMU-lBWKSmkN8o6XTPjfn5wV9X5stdA_A_n4K2qW6gtySdxBZMoP3SrY-t0VKDE00l8Yoy7-e8sV7YH4dXSPfMxvEmhYcHiQIF9je5Urwgy6dwMCVi9KaSCBniHeD9-LK--E2gXeCPCFTN5dpvOtyYidXSRAJbeeGM_iaDnphV9-10dpAMtWcFxtxOxZzzpCgG_w30r6_6wMvGNXrIY0NFgQy1w1371s3mmZs.8uiq7Gl0W4YQHYniuBetoA',
|
|
22
25
|
})
|
|
23
|
-
|
|
26
|
+
expect(client.httpHost).toEqual('fabric.signalwire.com')
|
|
27
|
+
})
|
|
28
|
+
})
|
package/src/fabric/HTTPClient.ts
CHANGED
|
@@ -1,22 +1,26 @@
|
|
|
1
|
+
import jwtDecode from 'jwt-decode'
|
|
1
2
|
import {
|
|
2
|
-
FetchAddressResponse,
|
|
3
|
-
GetAddressesOptions,
|
|
4
3
|
getLogger,
|
|
4
|
+
type Address,
|
|
5
|
+
type FetchAddressResponse,
|
|
6
|
+
type GetAddressesOptions,
|
|
5
7
|
type UserOptions,
|
|
8
|
+
type SubscriberInfoResponse,
|
|
9
|
+
type RegisterDeviceParams,
|
|
10
|
+
type UnregisterDeviceParams,
|
|
11
|
+
type RegisterDeviceResponse,
|
|
12
|
+
GetAddressOptions,
|
|
13
|
+
GetAddressResponse,
|
|
6
14
|
} from '@signalwire/core'
|
|
7
|
-
import { createHttpClient } from './createHttpClient'
|
|
8
|
-
import
|
|
15
|
+
import { CreateHttpClient, createHttpClient } from './createHttpClient'
|
|
16
|
+
import { buildPaginatedResult } from '../utils/paginatedResult'
|
|
17
|
+
import { makeQueryParamsUrls } from '../utils/makeQueryParamsUrl'
|
|
9
18
|
|
|
10
19
|
type JWTHeader = { ch?: string; typ?: string }
|
|
11
20
|
|
|
12
|
-
interface RegisterDeviceParams {
|
|
13
|
-
deviceType: 'iOS' | 'Android' | 'Desktop'
|
|
14
|
-
deviceToken: string
|
|
15
|
-
}
|
|
16
|
-
|
|
17
21
|
// TODO: extends from a Base class to share from core
|
|
18
22
|
export class HTTPClient {
|
|
19
|
-
private httpClient:
|
|
23
|
+
private httpClient: CreateHttpClient
|
|
20
24
|
|
|
21
25
|
constructor(public options: UserOptions) {
|
|
22
26
|
this.httpClient = createHttpClient({
|
|
@@ -27,11 +31,14 @@ export class HTTPClient {
|
|
|
27
31
|
})
|
|
28
32
|
}
|
|
29
33
|
|
|
34
|
+
get fetch(): CreateHttpClient {
|
|
35
|
+
return this.httpClient
|
|
36
|
+
}
|
|
37
|
+
|
|
30
38
|
get httpHost() {
|
|
31
|
-
|
|
32
39
|
let decodedJwt: JWTHeader = {}
|
|
33
40
|
try {
|
|
34
|
-
|
|
41
|
+
decodedJwt = jwtDecode<JWTHeader>(this.options.token, {
|
|
35
42
|
header: true,
|
|
36
43
|
})
|
|
37
44
|
} catch (e) {
|
|
@@ -46,53 +53,35 @@ export class HTTPClient {
|
|
|
46
53
|
return `fabric.${host.split('.').splice(1).join('.')}`
|
|
47
54
|
}
|
|
48
55
|
|
|
49
|
-
public async
|
|
50
|
-
const {
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
+
public async getAddress(options: GetAddressOptions) {
|
|
57
|
+
const { id } = options
|
|
58
|
+
let path = `/api/fabric/addresses/${id}`
|
|
59
|
+
|
|
60
|
+
const { body } = await this.httpClient<GetAddressResponse>(path)
|
|
61
|
+
return body
|
|
62
|
+
}
|
|
56
63
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
}
|
|
64
|
+
public async getAddresses(options?: GetAddressesOptions) {
|
|
65
|
+
const { type, displayName, pageSize } = options || {}
|
|
60
66
|
|
|
61
|
-
|
|
62
|
-
queryParams.append('display_name', displayName)
|
|
63
|
-
}
|
|
67
|
+
let path = '/api/fabric/addresses'
|
|
64
68
|
|
|
65
|
-
|
|
69
|
+
const queryParams = new URLSearchParams()
|
|
70
|
+
if (type) {
|
|
71
|
+
queryParams.append('type', type)
|
|
66
72
|
}
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
const anotherPage = async (url: string) => {
|
|
71
|
-
const { body } = await this.httpClient<FetchAddressResponse>(url)
|
|
72
|
-
return buildResult(body)
|
|
73
|
+
if (displayName) {
|
|
74
|
+
queryParams.append('display_name', displayName)
|
|
73
75
|
}
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
return {
|
|
77
|
-
addresses: body.data,
|
|
78
|
-
nextPage: async () => {
|
|
79
|
-
const { next } = body.links
|
|
80
|
-
return next ? anotherPage(next) : undefined
|
|
81
|
-
},
|
|
82
|
-
prevPage: async () => {
|
|
83
|
-
const { prev } = body.links
|
|
84
|
-
return prev ? anotherPage(prev) : undefined
|
|
85
|
-
},
|
|
86
|
-
firstPage: async () => {
|
|
87
|
-
const { first } = body.links
|
|
88
|
-
return first ? anotherPage(first) : undefined
|
|
89
|
-
},
|
|
90
|
-
hasNext: Boolean(body.links.next),
|
|
91
|
-
hasPrev: Boolean(body.links.prev),
|
|
92
|
-
}
|
|
76
|
+
if (pageSize) {
|
|
77
|
+
queryParams.append('page_size', pageSize.toString())
|
|
93
78
|
}
|
|
94
79
|
|
|
95
|
-
|
|
80
|
+
const { body } = await this.httpClient<FetchAddressResponse>(
|
|
81
|
+
makeQueryParamsUrls(path, queryParams)
|
|
82
|
+
)
|
|
83
|
+
|
|
84
|
+
return buildPaginatedResult<Address>(body, this.httpClient)
|
|
96
85
|
}
|
|
97
86
|
|
|
98
87
|
public async registerDevice({
|
|
@@ -100,7 +89,7 @@ export class HTTPClient {
|
|
|
100
89
|
deviceToken,
|
|
101
90
|
}: RegisterDeviceParams) {
|
|
102
91
|
const path = '/subscriber/devices' as const
|
|
103
|
-
const { body } = await this.httpClient<
|
|
92
|
+
const { body } = await this.httpClient<RegisterDeviceResponse>(path, {
|
|
104
93
|
method: 'POST',
|
|
105
94
|
body: {
|
|
106
95
|
device_type: deviceType,
|
|
@@ -111,10 +100,18 @@ export class HTTPClient {
|
|
|
111
100
|
return body
|
|
112
101
|
}
|
|
113
102
|
|
|
114
|
-
public async unregisterDevice({ id }:
|
|
103
|
+
public async unregisterDevice({ id }: UnregisterDeviceParams) {
|
|
115
104
|
const path = `/subscriber/devices/${id}` as const
|
|
116
|
-
return await this.httpClient<
|
|
105
|
+
return await this.httpClient<void>(path, {
|
|
117
106
|
method: 'DELETE',
|
|
118
107
|
})
|
|
119
108
|
}
|
|
109
|
+
|
|
110
|
+
public async getSubscriberInfo() {
|
|
111
|
+
let path = '/api/fabric/subscriber/info'
|
|
112
|
+
|
|
113
|
+
const { body } = await this.httpClient<SubscriberInfoResponse>(path)
|
|
114
|
+
|
|
115
|
+
return body
|
|
116
|
+
}
|
|
120
117
|
}
|
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
import { IncomingCallManager, IncomingCallNotification } from './IncomingCallManager'
|
|
2
|
+
|
|
3
|
+
describe('IncomingCallManager', () => {
|
|
4
|
+
const answer = jest.fn()
|
|
5
|
+
const buildCall = () => ({ answer })
|
|
6
|
+
const rejectCall = jest.fn().mockResolvedValue(null)
|
|
7
|
+
|
|
8
|
+
beforeAll(() => {
|
|
9
|
+
jest.resetAllMocks()
|
|
10
|
+
})
|
|
11
|
+
|
|
12
|
+
test('It should invoke the proper listeners', () => {
|
|
13
|
+
//@ts-ignore
|
|
14
|
+
const manager = new IncomingCallManager(buildCall, rejectCall)
|
|
15
|
+
const allNotificationListerner = jest.fn()
|
|
16
|
+
const pnNotificationListerner = jest.fn()
|
|
17
|
+
const wsNotificationListerner = jest.fn()
|
|
18
|
+
|
|
19
|
+
manager.setNotificationHandlers({
|
|
20
|
+
all: allNotificationListerner,
|
|
21
|
+
websocket: wsNotificationListerner,
|
|
22
|
+
pushNotification: pnNotificationListerner,
|
|
23
|
+
})
|
|
24
|
+
|
|
25
|
+
manager.handleIncomingInvite({
|
|
26
|
+
source: 'websocket',
|
|
27
|
+
callID: 'foo1',
|
|
28
|
+
callee_id_name: 'foo',
|
|
29
|
+
callee_id_number: 'foo',
|
|
30
|
+
caller_id_name: 'foo',
|
|
31
|
+
caller_id_number: 'foo',
|
|
32
|
+
sdp: 'foo',
|
|
33
|
+
display_direction: 'foo',
|
|
34
|
+
nodeId: 'foo'
|
|
35
|
+
})
|
|
36
|
+
|
|
37
|
+
expect(allNotificationListerner).toHaveBeenCalledTimes(1)
|
|
38
|
+
expect(wsNotificationListerner).toHaveBeenCalledTimes(1)
|
|
39
|
+
expect(pnNotificationListerner).toHaveBeenCalledTimes(0)
|
|
40
|
+
|
|
41
|
+
manager.handleIncomingInvite({
|
|
42
|
+
source: 'pushNotification',
|
|
43
|
+
callID: 'foo2',
|
|
44
|
+
callee_id_name: 'foo',
|
|
45
|
+
callee_id_number: 'foo',
|
|
46
|
+
caller_id_name: 'foo',
|
|
47
|
+
caller_id_number: 'foo',
|
|
48
|
+
sdp: 'foo',
|
|
49
|
+
display_direction: 'foo',
|
|
50
|
+
nodeId: 'foo'
|
|
51
|
+
})
|
|
52
|
+
|
|
53
|
+
expect(allNotificationListerner).toHaveBeenCalledTimes(2)
|
|
54
|
+
expect(wsNotificationListerner).toHaveBeenCalledTimes(1)
|
|
55
|
+
expect(pnNotificationListerner).toHaveBeenCalledTimes(1)
|
|
56
|
+
|
|
57
|
+
})
|
|
58
|
+
|
|
59
|
+
test('It should not answer the call when the invite is rejected', () => {
|
|
60
|
+
//@ts-ignore
|
|
61
|
+
const manager = new IncomingCallManager(buildCall, rejectCall)
|
|
62
|
+
const allNotificationListerner = jest.fn((notification: IncomingCallNotification) => {notification.invite.reject()})
|
|
63
|
+
|
|
64
|
+
manager.setNotificationHandlers({
|
|
65
|
+
//@ts-ignore
|
|
66
|
+
all: allNotificationListerner,
|
|
67
|
+
})
|
|
68
|
+
|
|
69
|
+
manager.handleIncomingInvite({
|
|
70
|
+
source: 'websocket',
|
|
71
|
+
callID: 'foo1',
|
|
72
|
+
callee_id_name: 'foo',
|
|
73
|
+
callee_id_number: 'foo',
|
|
74
|
+
caller_id_name: 'foo',
|
|
75
|
+
caller_id_number: 'foo',
|
|
76
|
+
sdp: 'foo',
|
|
77
|
+
display_direction: 'foo',
|
|
78
|
+
nodeId: 'foo'
|
|
79
|
+
})
|
|
80
|
+
|
|
81
|
+
expect(allNotificationListerner).toHaveBeenCalledTimes(1)
|
|
82
|
+
expect(answer).toBeCalledTimes(0)
|
|
83
|
+
})
|
|
84
|
+
|
|
85
|
+
test('It should answer the call when the invite is accepted', () => {
|
|
86
|
+
//@ts-ignore
|
|
87
|
+
const manager = new IncomingCallManager(buildCall, rejectCall)
|
|
88
|
+
//@ts-ignore
|
|
89
|
+
const allNotificationListerner = jest.fn((notification: IncomingCallNotification) => {notification.invite.accept({})})
|
|
90
|
+
|
|
91
|
+
manager.setNotificationHandlers({
|
|
92
|
+
//@ts-ignore
|
|
93
|
+
all: allNotificationListerner,
|
|
94
|
+
})
|
|
95
|
+
|
|
96
|
+
manager.handleIncomingInvite({
|
|
97
|
+
source: 'websocket',
|
|
98
|
+
callID: 'foo1',
|
|
99
|
+
callee_id_name: 'foo',
|
|
100
|
+
callee_id_number: 'foo',
|
|
101
|
+
caller_id_name: 'foo',
|
|
102
|
+
caller_id_number: 'foo',
|
|
103
|
+
sdp: 'foo',
|
|
104
|
+
display_direction: 'foo',
|
|
105
|
+
nodeId: 'foo'
|
|
106
|
+
})
|
|
107
|
+
|
|
108
|
+
expect(allNotificationListerner).toHaveBeenCalledTimes(1)
|
|
109
|
+
expect(answer).toBeCalledTimes(1)
|
|
110
|
+
})
|
|
111
|
+
|
|
112
|
+
test('It should dedupe overlaping listeners', () => {
|
|
113
|
+
//@ts-ignore
|
|
114
|
+
const manager = new IncomingCallManager(buildCall, rejectCall)
|
|
115
|
+
const notificationListerner = jest.fn()
|
|
116
|
+
manager.setNotificationHandlers({
|
|
117
|
+
all: notificationListerner,
|
|
118
|
+
websocket: notificationListerner,
|
|
119
|
+
pushNotification: notificationListerner,
|
|
120
|
+
})
|
|
121
|
+
|
|
122
|
+
manager.handleIncomingInvite({
|
|
123
|
+
source: 'websocket',
|
|
124
|
+
callID: 'foo',
|
|
125
|
+
callee_id_name: 'foo',
|
|
126
|
+
callee_id_number: 'foo',
|
|
127
|
+
caller_id_name: 'foo',
|
|
128
|
+
caller_id_number: 'foo',
|
|
129
|
+
sdp: 'foo',
|
|
130
|
+
display_direction: 'foo',
|
|
131
|
+
nodeId: 'foo'
|
|
132
|
+
})
|
|
133
|
+
|
|
134
|
+
expect(notificationListerner).toHaveBeenCalledTimes(1)
|
|
135
|
+
})
|
|
136
|
+
|
|
137
|
+
test('It should dedupe invites', () => {
|
|
138
|
+
//@ts-ignore
|
|
139
|
+
const manager = new IncomingCallManager(buildCall, rejectCall)
|
|
140
|
+
const notificationListerner = jest.fn()
|
|
141
|
+
manager.setNotificationHandlers({
|
|
142
|
+
all: notificationListerner,
|
|
143
|
+
})
|
|
144
|
+
|
|
145
|
+
manager.handleIncomingInvite({
|
|
146
|
+
source: 'websocket',
|
|
147
|
+
callID: 'same-id',
|
|
148
|
+
callee_id_name: 'foo',
|
|
149
|
+
callee_id_number: 'foo',
|
|
150
|
+
caller_id_name: 'foo',
|
|
151
|
+
caller_id_number: 'foo',
|
|
152
|
+
sdp: 'foo',
|
|
153
|
+
display_direction: 'foo',
|
|
154
|
+
nodeId: 'foo'
|
|
155
|
+
})
|
|
156
|
+
|
|
157
|
+
manager.handleIncomingInvite({
|
|
158
|
+
source: 'websocket',
|
|
159
|
+
callID: 'same-id',
|
|
160
|
+
callee_id_name: 'foo',
|
|
161
|
+
callee_id_number: 'foo',
|
|
162
|
+
caller_id_name: 'foo',
|
|
163
|
+
caller_id_number: 'foo',
|
|
164
|
+
sdp: 'foo',
|
|
165
|
+
display_direction: 'foo',
|
|
166
|
+
nodeId: 'foo'
|
|
167
|
+
})
|
|
168
|
+
|
|
169
|
+
expect(notificationListerner).toHaveBeenCalledTimes(1)
|
|
170
|
+
})
|
|
171
|
+
|
|
172
|
+
test('It should clean up invites after reject', () => {
|
|
173
|
+
//@ts-ignore
|
|
174
|
+
const manager = new IncomingCallManager(buildCall, rejectCall)
|
|
175
|
+
const notificationListerner = jest.fn((notification: IncomingCallNotification) => {notification.invite.reject()})
|
|
176
|
+
manager.setNotificationHandlers({
|
|
177
|
+
//@ts-ignore
|
|
178
|
+
all: notificationListerner,
|
|
179
|
+
})
|
|
180
|
+
|
|
181
|
+
manager.handleIncomingInvite({
|
|
182
|
+
source: 'websocket',
|
|
183
|
+
callID: 'same-id',
|
|
184
|
+
callee_id_name: 'foo',
|
|
185
|
+
callee_id_number: 'foo',
|
|
186
|
+
caller_id_name: 'foo',
|
|
187
|
+
caller_id_number: 'foo',
|
|
188
|
+
sdp: 'foo',
|
|
189
|
+
display_direction: 'foo',
|
|
190
|
+
nodeId: 'foo'
|
|
191
|
+
})
|
|
192
|
+
|
|
193
|
+
manager.handleIncomingInvite({
|
|
194
|
+
source: 'websocket',
|
|
195
|
+
callID: 'same-id',
|
|
196
|
+
callee_id_name: 'foo',
|
|
197
|
+
callee_id_number: 'foo',
|
|
198
|
+
caller_id_name: 'foo',
|
|
199
|
+
caller_id_number: 'foo',
|
|
200
|
+
sdp: 'foo',
|
|
201
|
+
display_direction: 'foo',
|
|
202
|
+
nodeId: 'foo'
|
|
203
|
+
})
|
|
204
|
+
|
|
205
|
+
expect(notificationListerner).toHaveBeenCalledTimes(2)
|
|
206
|
+
})
|
|
207
|
+
|
|
208
|
+
test('It should clean up invites after accept', () => {
|
|
209
|
+
//@ts-ignore
|
|
210
|
+
const manager = new IncomingCallManager(buildCall, rejectCall)
|
|
211
|
+
//@ts-ignore
|
|
212
|
+
const notificationListerner = jest.fn((notification: IncomingCallNotification) => {notification.invite.accept({})})
|
|
213
|
+
manager.setNotificationHandlers({
|
|
214
|
+
//@ts-ignore
|
|
215
|
+
all: notificationListerner,
|
|
216
|
+
})
|
|
217
|
+
|
|
218
|
+
manager.handleIncomingInvite({
|
|
219
|
+
source: 'websocket',
|
|
220
|
+
callID: 'same-id',
|
|
221
|
+
callee_id_name: 'foo',
|
|
222
|
+
callee_id_number: 'foo',
|
|
223
|
+
caller_id_name: 'foo',
|
|
224
|
+
caller_id_number: 'foo',
|
|
225
|
+
sdp: 'foo',
|
|
226
|
+
display_direction: 'foo',
|
|
227
|
+
nodeId: 'foo'
|
|
228
|
+
})
|
|
229
|
+
|
|
230
|
+
manager.handleIncomingInvite({
|
|
231
|
+
source: 'websocket',
|
|
232
|
+
callID: 'same-id',
|
|
233
|
+
callee_id_name: 'foo',
|
|
234
|
+
callee_id_number: 'foo',
|
|
235
|
+
caller_id_name: 'foo',
|
|
236
|
+
caller_id_number: 'foo',
|
|
237
|
+
sdp: 'foo',
|
|
238
|
+
display_direction: 'foo',
|
|
239
|
+
nodeId: 'foo'
|
|
240
|
+
})
|
|
241
|
+
|
|
242
|
+
expect(notificationListerner).toHaveBeenCalledTimes(2)
|
|
243
|
+
})
|
|
244
|
+
|
|
245
|
+
})
|