@stream-io/video-client 0.0.39 → 0.0.41
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/CHANGELOG.md +14 -0
- package/dist/index.browser.es.js +316 -311
- package/dist/index.browser.es.js.map +1 -1
- package/dist/index.cjs.js +316 -311
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.es.js +316 -311
- package/dist/index.es.js.map +1 -1
- package/dist/src/Call.d.ts +0 -6
- package/dist/src/coordinator/connection/client.d.ts +29 -29
- package/dist/src/coordinator/connection/connection.d.ts +3 -2
- package/dist/src/events/internal.d.ts +1 -0
- package/package.json +1 -1
- package/src/Call.ts +27 -38
- package/src/StreamSfuClient.ts +2 -2
- package/src/StreamVideoClient.ts +4 -1
- package/src/coordinator/connection/client.ts +58 -54
- package/src/coordinator/connection/connection.ts +7 -5
- package/src/events/callEventHandlers.ts +2 -0
- package/src/events/internal.ts +15 -0
- package/src/rtc/Publisher.ts +3 -3
- package/src/rtc/Subscriber.ts +1 -1
- package/src/stats/state-store-stats-reporter.ts +1 -1
package/dist/src/Call.d.ts
CHANGED
|
@@ -30,12 +30,6 @@ export declare class Call {
|
|
|
30
30
|
* The state of this call.
|
|
31
31
|
*/
|
|
32
32
|
readonly state: CallState;
|
|
33
|
-
private rejoinPromise;
|
|
34
|
-
/**
|
|
35
|
-
* A promise that exposes the reconnection logic
|
|
36
|
-
* The use-case is for the react-native platform where online/offline events are not available in the window
|
|
37
|
-
*/
|
|
38
|
-
get rejoin(): (() => Promise<void>) | undefined;
|
|
39
33
|
/**
|
|
40
34
|
* Flag indicating whether this call is "watched" and receives
|
|
41
35
|
* updates from the backend.
|
|
@@ -53,9 +53,9 @@ export declare class StreamClient {
|
|
|
53
53
|
* @param {httpsAgent} [options.httpsAgent] - custom httpsAgent, in node it's default to https.agent()
|
|
54
54
|
*/
|
|
55
55
|
constructor(key: string, options?: StreamClientOptions);
|
|
56
|
-
devToken(userID: string)
|
|
57
|
-
getAuthType()
|
|
58
|
-
setBaseURL(baseURL: string)
|
|
56
|
+
devToken: (userID: string) => string;
|
|
57
|
+
getAuthType: () => "anonymous" | "jwt";
|
|
58
|
+
setBaseURL: (baseURL: string) => void;
|
|
59
59
|
_getConnectionID: () => string | undefined;
|
|
60
60
|
_hasConnectionID: () => boolean;
|
|
61
61
|
/**
|
|
@@ -72,7 +72,7 @@ export declare class StreamClient {
|
|
|
72
72
|
*/
|
|
73
73
|
connectUser: (user: UserWithId, userTokenOrProvider: TokenOrProvider) => Promise<void | import("../../..").ConnectedEvent>;
|
|
74
74
|
_setToken: (user: UserWithId, userTokenOrProvider: TokenOrProvider, isAnonymous: boolean) => Promise<void>;
|
|
75
|
-
_setUser(user: UserWithId)
|
|
75
|
+
_setUser: (user: UserWithId) => void;
|
|
76
76
|
/**
|
|
77
77
|
* Disconnects the websocket connection, without removing the user set on client.
|
|
78
78
|
* client.closeConnection will not trigger default auto-retry mechanism for reconnection. You need
|
|
@@ -115,19 +115,19 @@ export declare class StreamClient {
|
|
|
115
115
|
*
|
|
116
116
|
* @return {Function} Returns a function which, when called, unsubscribes the event handler.
|
|
117
117
|
*/
|
|
118
|
-
on(callbackOrEventName: EventHandler | string, callbackOrNothing?: EventHandler)
|
|
118
|
+
on: (callbackOrEventName: EventHandler | string, callbackOrNothing?: EventHandler) => () => void;
|
|
119
119
|
/**
|
|
120
120
|
* off - Remove the event handler
|
|
121
121
|
*
|
|
122
122
|
*/
|
|
123
|
-
off(callbackOrEventName: EventHandler | string, callbackOrNothing?: EventHandler)
|
|
124
|
-
_logApiRequest(type: string, url: string, data: unknown, config: AxiosRequestConfig & {
|
|
125
|
-
config?: AxiosRequestConfig & {
|
|
126
|
-
maxBodyLength?: number;
|
|
127
|
-
};
|
|
128
|
-
})
|
|
129
|
-
_logApiResponse<T>(type: string, url: string, response: AxiosResponse<T>)
|
|
130
|
-
_logApiError(type: string, url: string, error: unknown)
|
|
123
|
+
off: (callbackOrEventName: EventHandler | string, callbackOrNothing?: EventHandler) => void;
|
|
124
|
+
_logApiRequest: (type: string, url: string, data: unknown, config: AxiosRequestConfig<any> & {
|
|
125
|
+
config?: (AxiosRequestConfig<any> & {
|
|
126
|
+
maxBodyLength?: number | undefined;
|
|
127
|
+
}) | undefined;
|
|
128
|
+
}) => void;
|
|
129
|
+
_logApiResponse: <T>(type: string, url: string, response: AxiosResponse<T, any>) => void;
|
|
130
|
+
_logApiError: (type: string, url: string, error: unknown) => void;
|
|
131
131
|
doAxiosRequest: <T, D = unknown>(type: string, url: string, data?: D | undefined, options?: AxiosRequestConfig & {
|
|
132
132
|
config?: AxiosRequestConfig & {
|
|
133
133
|
maxBodyLength?: number;
|
|
@@ -135,38 +135,38 @@ export declare class StreamClient {
|
|
|
135
135
|
} & {
|
|
136
136
|
publicEndpoint?: boolean;
|
|
137
137
|
}) => Promise<T>;
|
|
138
|
-
get<T>(url: string, params?: AxiosRequestConfig['params'])
|
|
139
|
-
put<T, D = unknown>(url: string, data?: D)
|
|
140
|
-
post<T, D = unknown>(url: string, data?: D)
|
|
141
|
-
patch<T, D = unknown>(url: string, data?: D)
|
|
142
|
-
delete<T>(url: string, params?: AxiosRequestConfig['params'])
|
|
143
|
-
errorFromResponse(response: AxiosResponse<APIErrorResponse>)
|
|
144
|
-
handleResponse<T>(response: AxiosResponse<T>)
|
|
138
|
+
get: <T>(url: string, params?: AxiosRequestConfig['params']) => Promise<T>;
|
|
139
|
+
put: <T, D = unknown>(url: string, data?: D | undefined) => Promise<T>;
|
|
140
|
+
post: <T, D = unknown>(url: string, data?: D | undefined) => Promise<T>;
|
|
141
|
+
patch: <T, D = unknown>(url: string, data?: D | undefined) => Promise<T>;
|
|
142
|
+
delete: <T>(url: string, params?: AxiosRequestConfig['params']) => Promise<T>;
|
|
143
|
+
errorFromResponse: (response: AxiosResponse<APIErrorResponse>) => ErrorFromResponse<APIErrorResponse>;
|
|
144
|
+
handleResponse: <T>(response: AxiosResponse<T, any>) => T;
|
|
145
145
|
dispatchEvent: (event: StreamVideoEvent) => void;
|
|
146
146
|
handleEvent: (messageEvent: WebSocket.MessageEvent) => void;
|
|
147
147
|
_callClientListeners: (event: StreamVideoEvent) => void;
|
|
148
148
|
/**
|
|
149
149
|
* @private
|
|
150
150
|
*/
|
|
151
|
-
connect()
|
|
151
|
+
connect: () => Promise<void | import("../../..").ConnectedEvent>;
|
|
152
152
|
/**
|
|
153
153
|
* Check the connectivity with server for warmup purpose.
|
|
154
154
|
*
|
|
155
155
|
* @private
|
|
156
156
|
*/
|
|
157
|
-
_sayHi()
|
|
158
|
-
getUserAgent()
|
|
159
|
-
setUserAgent(userAgent: string)
|
|
157
|
+
_sayHi: () => void;
|
|
158
|
+
getUserAgent: () => string;
|
|
159
|
+
setUserAgent: (userAgent: string) => void;
|
|
160
160
|
/**
|
|
161
161
|
* _isUsingServerAuth - Returns true if we're using server side auth
|
|
162
162
|
*/
|
|
163
163
|
_isUsingServerAuth: () => boolean;
|
|
164
|
-
_enrichAxiosOptions(options?: AxiosRequestConfig & {
|
|
164
|
+
_enrichAxiosOptions: (options?: AxiosRequestConfig & {
|
|
165
165
|
config?: AxiosRequestConfig;
|
|
166
166
|
} & {
|
|
167
167
|
publicEndpoint?: boolean;
|
|
168
|
-
})
|
|
169
|
-
_getToken()
|
|
168
|
+
}) => AxiosRequestConfig;
|
|
169
|
+
_getToken: () => string | null | undefined;
|
|
170
170
|
/**
|
|
171
171
|
* encode ws url payload
|
|
172
172
|
* @private
|
|
@@ -176,7 +176,7 @@ export declare class StreamClient {
|
|
|
176
176
|
/**
|
|
177
177
|
* creates an abort controller that will be used by the next HTTP Request.
|
|
178
178
|
*/
|
|
179
|
-
createAbortControllerForNextRequest()
|
|
179
|
+
createAbortControllerForNextRequest: () => AbortController;
|
|
180
180
|
/**
|
|
181
181
|
* createToken - Creates a token to authenticate this user. This function is used server side.
|
|
182
182
|
* The resulting token should be passed to the client side when the users registers or logs in.
|
|
@@ -187,5 +187,5 @@ export declare class StreamClient {
|
|
|
187
187
|
*
|
|
188
188
|
* @return {string} Returns a token
|
|
189
189
|
*/
|
|
190
|
-
createToken(userID: string, exp?: number, iat?: number, call_cids?: string[])
|
|
190
|
+
createToken: (userID: string, exp?: number, iat?: number, call_cids?: string[]) => string;
|
|
191
191
|
}
|
|
@@ -47,7 +47,7 @@ export declare class StableWSConnection {
|
|
|
47
47
|
wsID: number;
|
|
48
48
|
client: StreamClient;
|
|
49
49
|
constructor(client: StreamClient);
|
|
50
|
-
_log(msg: string, extra?: UR, level?: LogLevel)
|
|
50
|
+
_log: (msg: string, extra?: UR, level?: LogLevel) => void;
|
|
51
51
|
setClient: (client: StreamClient) => void;
|
|
52
52
|
/**
|
|
53
53
|
* connect - Connect to the WS URL
|
|
@@ -106,9 +106,10 @@ export declare class StableWSConnection {
|
|
|
106
106
|
* Broadcasts an event in case the connection status changed.
|
|
107
107
|
*
|
|
108
108
|
* @param {boolean} healthy boolean indicating if the connection is healthy or not
|
|
109
|
+
* @param {boolean} dispatchImmediately boolean indicating to dispatch event immediately even if the connection is unhealthy
|
|
109
110
|
*
|
|
110
111
|
*/
|
|
111
|
-
_setHealth: (healthy: boolean) => void;
|
|
112
|
+
_setHealth: (healthy: boolean, dispatchImmediately?: boolean) => void;
|
|
112
113
|
/**
|
|
113
114
|
* _errorFromWSEvent - Creates an error object for the WS event
|
|
114
115
|
*
|
|
@@ -11,6 +11,7 @@ export declare const watchConnectionQualityChanged: (dispatcher: Dispatcher, sta
|
|
|
11
11
|
* health check events that our SFU sends.
|
|
12
12
|
*/
|
|
13
13
|
export declare const watchParticipantCountChanged: (dispatcher: Dispatcher, state: CallState) => () => void;
|
|
14
|
+
export declare const watchLiveEnded: (dispatcher: Dispatcher, call: Call) => () => void;
|
|
14
15
|
/**
|
|
15
16
|
* Watches and logs the errors reported by the currently connected SFU.
|
|
16
17
|
*/
|
package/package.json
CHANGED
package/src/Call.ts
CHANGED
|
@@ -103,7 +103,6 @@ import {
|
|
|
103
103
|
StreamCallEvent,
|
|
104
104
|
} from './coordinator/connection/types';
|
|
105
105
|
import { getClientDetails } from './client-details';
|
|
106
|
-
import { isReactNative } from './helpers/platforms';
|
|
107
106
|
import { getLogger } from './logger';
|
|
108
107
|
|
|
109
108
|
/**
|
|
@@ -135,16 +134,6 @@ export class Call {
|
|
|
135
134
|
*/
|
|
136
135
|
readonly state = new CallState();
|
|
137
136
|
|
|
138
|
-
private rejoinPromise: (() => Promise<void>) | undefined;
|
|
139
|
-
|
|
140
|
-
/**
|
|
141
|
-
* A promise that exposes the reconnection logic
|
|
142
|
-
* The use-case is for the react-native platform where online/offline events are not available in the window
|
|
143
|
-
*/
|
|
144
|
-
get rejoin(): (() => Promise<void>) | undefined {
|
|
145
|
-
return this.rejoinPromise;
|
|
146
|
-
}
|
|
147
|
-
|
|
148
137
|
/**
|
|
149
138
|
* Flag indicating whether this call is "watched" and receives
|
|
150
139
|
* updates from the backend.
|
|
@@ -387,7 +376,6 @@ export class Call {
|
|
|
387
376
|
if (callingState === CallingState.LEFT) {
|
|
388
377
|
throw new Error('Cannot leave call that has already been left.');
|
|
389
378
|
}
|
|
390
|
-
this.rejoinPromise = undefined;
|
|
391
379
|
|
|
392
380
|
if (this.ringing) {
|
|
393
381
|
// I'm the one who started the call, so I should cancel it.
|
|
@@ -685,7 +673,7 @@ export class Call {
|
|
|
685
673
|
// we shouldn't be republishing the streams if we're migrating
|
|
686
674
|
// as the underlying peer connection will take care of it as part
|
|
687
675
|
// of the ice-restart process
|
|
688
|
-
if (localParticipant && !
|
|
676
|
+
if (localParticipant && !migrate) {
|
|
689
677
|
const {
|
|
690
678
|
audioStream,
|
|
691
679
|
videoStream,
|
|
@@ -703,8 +691,6 @@ export class Call {
|
|
|
703
691
|
);
|
|
704
692
|
};
|
|
705
693
|
|
|
706
|
-
this.rejoinPromise = rejoin;
|
|
707
|
-
|
|
708
694
|
// reconnect if the connection was closed unexpectedly. example:
|
|
709
695
|
// - SFU crash or restart
|
|
710
696
|
// - network change
|
|
@@ -744,8 +730,6 @@ export class Call {
|
|
|
744
730
|
sfuClient.isMigratingAway
|
|
745
731
|
)
|
|
746
732
|
return;
|
|
747
|
-
// do nothing for react-native as it is handled by SDK
|
|
748
|
-
if (isReactNative()) return;
|
|
749
733
|
if (this.reconnectAttempts < this.maxReconnectAttempts) {
|
|
750
734
|
rejoin().catch((err) => {
|
|
751
735
|
this.logger(
|
|
@@ -766,17 +750,17 @@ export class Call {
|
|
|
766
750
|
});
|
|
767
751
|
|
|
768
752
|
// handlers for connection online/offline events
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
753
|
+
const unsubscribeOnlineEvent = this.streamClient.on(
|
|
754
|
+
'connection.changed',
|
|
755
|
+
(e) => {
|
|
756
|
+
if (e.type !== 'connection.changed') return;
|
|
757
|
+
if (!e.online) return;
|
|
758
|
+
unsubscribeOnlineEvent();
|
|
759
|
+
const currentCallingState = this.state.callingState;
|
|
760
|
+
if (
|
|
761
|
+
currentCallingState === CallingState.OFFLINE ||
|
|
762
|
+
currentCallingState === CallingState.RECONNECTING_FAILED
|
|
763
|
+
) {
|
|
780
764
|
this.logger('info', '[Rejoin]: Going online...');
|
|
781
765
|
rejoin().catch((err) => {
|
|
782
766
|
this.logger(
|
|
@@ -787,17 +771,22 @@ export class Call {
|
|
|
787
771
|
this.state.setCallingState(CallingState.RECONNECTING_FAILED);
|
|
788
772
|
});
|
|
789
773
|
}
|
|
790
|
-
}
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
774
|
+
},
|
|
775
|
+
);
|
|
776
|
+
const unsubscribeOfflineEvent = this.streamClient.on(
|
|
777
|
+
'connection.changed',
|
|
778
|
+
(e) => {
|
|
779
|
+
if (e.type !== 'connection.changed') return;
|
|
780
|
+
if (e.online) return;
|
|
781
|
+
unsubscribeOfflineEvent();
|
|
782
|
+
this.state.setCallingState(CallingState.OFFLINE);
|
|
783
|
+
},
|
|
784
|
+
);
|
|
794
785
|
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
);
|
|
800
|
-
}
|
|
786
|
+
this.leaveCallHooks.push(() => {
|
|
787
|
+
unsubscribeOnlineEvent();
|
|
788
|
+
unsubscribeOfflineEvent();
|
|
789
|
+
});
|
|
801
790
|
|
|
802
791
|
if (!this.subscriber) {
|
|
803
792
|
this.subscriber = new Subscriber({
|
package/src/StreamSfuClient.ts
CHANGED
|
@@ -106,7 +106,7 @@ export class StreamSfuClient {
|
|
|
106
106
|
private readonly rpc: SignalServerClient;
|
|
107
107
|
private keepAliveInterval?: NodeJS.Timeout;
|
|
108
108
|
private connectionCheckTimeout?: NodeJS.Timeout;
|
|
109
|
-
private pingIntervalInMs =
|
|
109
|
+
private pingIntervalInMs = 10 * 1000;
|
|
110
110
|
private unhealthyTimeoutInMs = this.pingIntervalInMs + 5 * 1000;
|
|
111
111
|
private lastMessageTimestamp?: Date;
|
|
112
112
|
private readonly unsubscribeIceTrickle: () => void;
|
|
@@ -319,7 +319,7 @@ export class StreamSfuClient {
|
|
|
319
319
|
new Date().getTime() - this.lastMessageTimestamp.getTime();
|
|
320
320
|
|
|
321
321
|
if (timeSinceLastMessage > this.unhealthyTimeoutInMs) {
|
|
322
|
-
this.logger('
|
|
322
|
+
this.logger('debug', 'SFU connection unhealthy, closing');
|
|
323
323
|
this.close(
|
|
324
324
|
4001,
|
|
325
325
|
`SFU connection unhealthy. Didn't receive any healthcheck messages for ${this.unhealthyTimeoutInMs}ms`,
|
package/src/StreamVideoClient.ts
CHANGED
|
@@ -221,7 +221,10 @@ export class StreamVideoClient {
|
|
|
221
221
|
if (event.type !== 'call.ring') return;
|
|
222
222
|
const { call, members } = event;
|
|
223
223
|
if (userToConnect.id === call.created_by.id) {
|
|
224
|
-
this.logger(
|
|
224
|
+
this.logger(
|
|
225
|
+
'debug',
|
|
226
|
+
'Received `call.ring` sent by the current user so ignoring the event',
|
|
227
|
+
);
|
|
225
228
|
return;
|
|
226
229
|
}
|
|
227
230
|
|
|
@@ -162,20 +162,20 @@ export class StreamClient {
|
|
|
162
162
|
: () => null;
|
|
163
163
|
}
|
|
164
164
|
|
|
165
|
-
devToken(userID: string) {
|
|
165
|
+
devToken = (userID: string) => {
|
|
166
166
|
return DevToken(userID);
|
|
167
|
-
}
|
|
167
|
+
};
|
|
168
168
|
|
|
169
|
-
getAuthType() {
|
|
169
|
+
getAuthType = () => {
|
|
170
170
|
return this.anonymous ? 'anonymous' : 'jwt';
|
|
171
|
-
}
|
|
171
|
+
};
|
|
172
172
|
|
|
173
|
-
setBaseURL(baseURL: string) {
|
|
173
|
+
setBaseURL = (baseURL: string) => {
|
|
174
174
|
this.baseURL = baseURL;
|
|
175
175
|
this.wsBaseURL = this.baseURL
|
|
176
176
|
.replace('http', 'ws')
|
|
177
177
|
.replace(':3030', ':8800');
|
|
178
|
-
}
|
|
178
|
+
};
|
|
179
179
|
|
|
180
180
|
_getConnectionID = () =>
|
|
181
181
|
this.wsConnection?.connectionID || this.wsFallback?.connectionID;
|
|
@@ -282,7 +282,7 @@ export class StreamClient {
|
|
|
282
282
|
isAnonymous,
|
|
283
283
|
);
|
|
284
284
|
|
|
285
|
-
_setUser(user: UserWithId) {
|
|
285
|
+
_setUser = (user: UserWithId) => {
|
|
286
286
|
/**
|
|
287
287
|
* This one is used by the frontend. This is a copy of the current user object stored on backend.
|
|
288
288
|
* It contains reserved properties and own user properties which are not present in `this._user`.
|
|
@@ -291,7 +291,7 @@ export class StreamClient {
|
|
|
291
291
|
this.userID = user.id;
|
|
292
292
|
// this one is actually used for requests. This is a copy of current user provided to `connectUser` function.
|
|
293
293
|
this._user = { ...user };
|
|
294
|
-
}
|
|
294
|
+
};
|
|
295
295
|
|
|
296
296
|
/**
|
|
297
297
|
* Disconnects the websocket connection, without removing the user set on client.
|
|
@@ -423,10 +423,10 @@ export class StreamClient {
|
|
|
423
423
|
*
|
|
424
424
|
* @return {Function} Returns a function which, when called, unsubscribes the event handler.
|
|
425
425
|
*/
|
|
426
|
-
on(
|
|
426
|
+
on = (
|
|
427
427
|
callbackOrEventName: EventHandler | string,
|
|
428
428
|
callbackOrNothing?: EventHandler,
|
|
429
|
-
) {
|
|
429
|
+
) => {
|
|
430
430
|
const key = callbackOrNothing ? (callbackOrEventName as string) : 'all';
|
|
431
431
|
const callback = callbackOrNothing
|
|
432
432
|
? callbackOrNothing
|
|
@@ -439,16 +439,16 @@ export class StreamClient {
|
|
|
439
439
|
return () => {
|
|
440
440
|
this.off(key, callback);
|
|
441
441
|
};
|
|
442
|
-
}
|
|
442
|
+
};
|
|
443
443
|
|
|
444
444
|
/**
|
|
445
445
|
* off - Remove the event handler
|
|
446
446
|
*
|
|
447
447
|
*/
|
|
448
|
-
off(
|
|
448
|
+
off = (
|
|
449
449
|
callbackOrEventName: EventHandler | string,
|
|
450
450
|
callbackOrNothing?: EventHandler,
|
|
451
|
-
) {
|
|
451
|
+
) => {
|
|
452
452
|
const key = callbackOrNothing ? (callbackOrEventName as string) : 'all';
|
|
453
453
|
const callback = callbackOrNothing
|
|
454
454
|
? callbackOrNothing
|
|
@@ -461,23 +461,27 @@ export class StreamClient {
|
|
|
461
461
|
this.listeners[key] = this.listeners[key].filter(
|
|
462
462
|
(value) => value !== callback,
|
|
463
463
|
);
|
|
464
|
-
}
|
|
464
|
+
};
|
|
465
465
|
|
|
466
|
-
_logApiRequest(
|
|
466
|
+
_logApiRequest = (
|
|
467
467
|
type: string,
|
|
468
468
|
url: string,
|
|
469
469
|
data: unknown,
|
|
470
470
|
config: AxiosRequestConfig & {
|
|
471
471
|
config?: AxiosRequestConfig & { maxBodyLength?: number };
|
|
472
472
|
},
|
|
473
|
-
) {
|
|
473
|
+
) => {
|
|
474
474
|
this.logger('trace', `client: ${type} - Request - ${url}`, {
|
|
475
475
|
payload: data,
|
|
476
476
|
config,
|
|
477
477
|
});
|
|
478
|
-
}
|
|
478
|
+
};
|
|
479
479
|
|
|
480
|
-
_logApiResponse
|
|
480
|
+
_logApiResponse = <T>(
|
|
481
|
+
type: string,
|
|
482
|
+
url: string,
|
|
483
|
+
response: AxiosResponse<T>,
|
|
484
|
+
) => {
|
|
481
485
|
this.logger(
|
|
482
486
|
'trace',
|
|
483
487
|
`client:${type} - Response - url: ${url} > status ${response.status}`,
|
|
@@ -488,14 +492,14 @@ export class StreamClient {
|
|
|
488
492
|
this.logger('trace', `client:${type} - Response payload`, {
|
|
489
493
|
response,
|
|
490
494
|
});
|
|
491
|
-
}
|
|
495
|
+
};
|
|
492
496
|
|
|
493
|
-
_logApiError(type: string, url: string, error: unknown) {
|
|
497
|
+
_logApiError = (type: string, url: string, error: unknown) => {
|
|
494
498
|
this.logger('error', `client:${type} - Error - url: ${url}`, {
|
|
495
499
|
url,
|
|
496
500
|
error,
|
|
497
501
|
});
|
|
498
|
-
}
|
|
502
|
+
};
|
|
499
503
|
|
|
500
504
|
doAxiosRequest = async <T, D = unknown>(
|
|
501
505
|
type: string,
|
|
@@ -568,33 +572,33 @@ export class StreamClient {
|
|
|
568
572
|
}
|
|
569
573
|
};
|
|
570
574
|
|
|
571
|
-
get<T>(url: string, params?: AxiosRequestConfig['params']) {
|
|
575
|
+
get = <T>(url: string, params?: AxiosRequestConfig['params']) => {
|
|
572
576
|
return this.doAxiosRequest<T, unknown>('get', url, null, {
|
|
573
577
|
params,
|
|
574
578
|
});
|
|
575
|
-
}
|
|
579
|
+
};
|
|
576
580
|
|
|
577
|
-
put<T, D = unknown>(url: string, data?: D) {
|
|
581
|
+
put = <T, D = unknown>(url: string, data?: D) => {
|
|
578
582
|
return this.doAxiosRequest<T, D>('put', url, data);
|
|
579
|
-
}
|
|
583
|
+
};
|
|
580
584
|
|
|
581
|
-
post<T, D = unknown>(url: string, data?: D) {
|
|
585
|
+
post = <T, D = unknown>(url: string, data?: D) => {
|
|
582
586
|
return this.doAxiosRequest<T, D>('post', url, data);
|
|
583
|
-
}
|
|
587
|
+
};
|
|
584
588
|
|
|
585
|
-
patch<T, D = unknown>(url: string, data?: D) {
|
|
589
|
+
patch = <T, D = unknown>(url: string, data?: D) => {
|
|
586
590
|
return this.doAxiosRequest<T, D>('patch', url, data);
|
|
587
|
-
}
|
|
591
|
+
};
|
|
588
592
|
|
|
589
|
-
delete<T>(url: string, params?: AxiosRequestConfig['params']) {
|
|
593
|
+
delete = <T>(url: string, params?: AxiosRequestConfig['params']) => {
|
|
590
594
|
return this.doAxiosRequest<T, unknown>('delete', url, null, {
|
|
591
595
|
params,
|
|
592
596
|
});
|
|
593
|
-
}
|
|
597
|
+
};
|
|
594
598
|
|
|
595
|
-
errorFromResponse(
|
|
599
|
+
errorFromResponse = (
|
|
596
600
|
response: AxiosResponse<APIErrorResponse>,
|
|
597
|
-
): ErrorFromResponse<APIErrorResponse> {
|
|
601
|
+
): ErrorFromResponse<APIErrorResponse> => {
|
|
598
602
|
let err: ErrorFromResponse<APIErrorResponse>;
|
|
599
603
|
err = new ErrorFromResponse(`Stream error HTTP code: ${response.status}`);
|
|
600
604
|
if (response.data && response.data.code) {
|
|
@@ -606,15 +610,15 @@ export class StreamClient {
|
|
|
606
610
|
err.response = response;
|
|
607
611
|
err.status = response.status;
|
|
608
612
|
return err;
|
|
609
|
-
}
|
|
613
|
+
};
|
|
610
614
|
|
|
611
|
-
handleResponse<T>(response: AxiosResponse<T>) {
|
|
615
|
+
handleResponse = <T>(response: AxiosResponse<T>) => {
|
|
612
616
|
const data = response.data;
|
|
613
617
|
if (isErrorResponse(response)) {
|
|
614
618
|
throw this.errorFromResponse(response);
|
|
615
619
|
}
|
|
616
620
|
return data;
|
|
617
|
-
}
|
|
621
|
+
};
|
|
618
622
|
|
|
619
623
|
dispatchEvent = (event: StreamVideoEvent) => {
|
|
620
624
|
if (!event.received_at) event.received_at = new Date();
|
|
@@ -650,7 +654,7 @@ export class StreamClient {
|
|
|
650
654
|
/**
|
|
651
655
|
* @private
|
|
652
656
|
*/
|
|
653
|
-
async
|
|
657
|
+
connect = async () => {
|
|
654
658
|
if (!this.userID || !this._user) {
|
|
655
659
|
throw Error(
|
|
656
660
|
'Call connectUser or connectAnonymousUser before starting the connection',
|
|
@@ -716,14 +720,14 @@ export class StreamClient {
|
|
|
716
720
|
|
|
717
721
|
throw err;
|
|
718
722
|
}
|
|
719
|
-
}
|
|
723
|
+
};
|
|
720
724
|
|
|
721
725
|
/**
|
|
722
726
|
* Check the connectivity with server for warmup purpose.
|
|
723
727
|
*
|
|
724
728
|
* @private
|
|
725
729
|
*/
|
|
726
|
-
_sayHi() {
|
|
730
|
+
_sayHi = () => {
|
|
727
731
|
const client_request_id = randomId();
|
|
728
732
|
const opts = {
|
|
729
733
|
headers: AxiosHeaders.from({
|
|
@@ -739,27 +743,27 @@ export class StreamClient {
|
|
|
739
743
|
});
|
|
740
744
|
}
|
|
741
745
|
});
|
|
742
|
-
}
|
|
746
|
+
};
|
|
743
747
|
|
|
744
|
-
getUserAgent() {
|
|
748
|
+
getUserAgent = () => {
|
|
745
749
|
return (
|
|
746
750
|
this.userAgent ||
|
|
747
751
|
`stream-video-javascript-client-${this.node ? 'node' : 'browser'}-${
|
|
748
752
|
process.env.PKG_VERSION
|
|
749
753
|
}`
|
|
750
754
|
);
|
|
751
|
-
}
|
|
755
|
+
};
|
|
752
756
|
|
|
753
|
-
setUserAgent(userAgent: string) {
|
|
757
|
+
setUserAgent = (userAgent: string) => {
|
|
754
758
|
this.userAgent = userAgent;
|
|
755
|
-
}
|
|
759
|
+
};
|
|
756
760
|
|
|
757
761
|
/**
|
|
758
762
|
* _isUsingServerAuth - Returns true if we're using server side auth
|
|
759
763
|
*/
|
|
760
764
|
_isUsingServerAuth = () => !!this.secret;
|
|
761
765
|
|
|
762
|
-
_enrichAxiosOptions(
|
|
766
|
+
_enrichAxiosOptions = (
|
|
763
767
|
options: AxiosRequestConfig & { config?: AxiosRequestConfig } & {
|
|
764
768
|
publicEndpoint?: boolean;
|
|
765
769
|
} = {
|
|
@@ -767,7 +771,7 @@ export class StreamClient {
|
|
|
767
771
|
headers: {},
|
|
768
772
|
config: {},
|
|
769
773
|
},
|
|
770
|
-
): AxiosRequestConfig {
|
|
774
|
+
): AxiosRequestConfig => {
|
|
771
775
|
const token =
|
|
772
776
|
options.publicEndpoint && !this.user ? undefined : this._getToken();
|
|
773
777
|
const authorization = token ? { Authorization: token } : undefined;
|
|
@@ -804,13 +808,13 @@ export class StreamClient {
|
|
|
804
808
|
...options.config,
|
|
805
809
|
...this.options.axiosRequestConfig,
|
|
806
810
|
};
|
|
807
|
-
}
|
|
811
|
+
};
|
|
808
812
|
|
|
809
|
-
_getToken() {
|
|
813
|
+
_getToken = () => {
|
|
810
814
|
if (!this.tokenManager) return null;
|
|
811
815
|
|
|
812
816
|
return this.tokenManager.getToken();
|
|
813
|
-
}
|
|
817
|
+
};
|
|
814
818
|
|
|
815
819
|
/**
|
|
816
820
|
* encode ws url payload
|
|
@@ -828,9 +832,9 @@ export class StreamClient {
|
|
|
828
832
|
/**
|
|
829
833
|
* creates an abort controller that will be used by the next HTTP Request.
|
|
830
834
|
*/
|
|
831
|
-
createAbortControllerForNextRequest() {
|
|
835
|
+
createAbortControllerForNextRequest = () => {
|
|
832
836
|
return (this.nextRequestAbortController = new AbortController());
|
|
833
|
-
}
|
|
837
|
+
};
|
|
834
838
|
|
|
835
839
|
/**
|
|
836
840
|
* createToken - Creates a token to authenticate this user. This function is used server side.
|
|
@@ -842,12 +846,12 @@ export class StreamClient {
|
|
|
842
846
|
*
|
|
843
847
|
* @return {string} Returns a token
|
|
844
848
|
*/
|
|
845
|
-
createToken(
|
|
849
|
+
createToken = (
|
|
846
850
|
userID: string,
|
|
847
851
|
exp?: number,
|
|
848
852
|
iat?: number,
|
|
849
853
|
call_cids?: string[],
|
|
850
|
-
) {
|
|
854
|
+
) => {
|
|
851
855
|
if (this.secret == null) {
|
|
852
856
|
throw Error(
|
|
853
857
|
`tokens can only be created server-side using the API Secret`,
|
|
@@ -868,5 +872,5 @@ export class StreamClient {
|
|
|
868
872
|
}
|
|
869
873
|
|
|
870
874
|
return JWTUserToken(this.secret, userID, extra, {});
|
|
871
|
-
}
|
|
875
|
+
};
|
|
872
876
|
}
|
|
@@ -105,11 +105,11 @@ export class StableWSConnection {
|
|
|
105
105
|
addConnectionEventListeners(this.onlineStatusChanged);
|
|
106
106
|
}
|
|
107
107
|
|
|
108
|
-
_log(msg: string, extra: UR = {}, level: LogLevel = 'info') {
|
|
108
|
+
_log = (msg: string, extra: UR = {}, level: LogLevel = 'info') => {
|
|
109
109
|
this.client.logger(level, 'connection:' + msg, {
|
|
110
110
|
...extra,
|
|
111
111
|
});
|
|
112
|
-
}
|
|
112
|
+
};
|
|
113
113
|
|
|
114
114
|
setClient = (client: StreamClient) => {
|
|
115
115
|
this.client = client;
|
|
@@ -475,7 +475,8 @@ export class StableWSConnection {
|
|
|
475
475
|
if (event.type === 'offline') {
|
|
476
476
|
// mark the connection as down
|
|
477
477
|
this._log('onlineStatusChanged() - Status changing to offline');
|
|
478
|
-
|
|
478
|
+
// we know that the app is offline so dispatch the unhealthy connection event immediately
|
|
479
|
+
this._setHealth(false, true);
|
|
479
480
|
} else if (event.type === 'online') {
|
|
480
481
|
// retry right now...
|
|
481
482
|
// We check this.isHealthy, not sure if it's always
|
|
@@ -628,14 +629,15 @@ export class StableWSConnection {
|
|
|
628
629
|
* Broadcasts an event in case the connection status changed.
|
|
629
630
|
*
|
|
630
631
|
* @param {boolean} healthy boolean indicating if the connection is healthy or not
|
|
632
|
+
* @param {boolean} dispatchImmediately boolean indicating to dispatch event immediately even if the connection is unhealthy
|
|
631
633
|
*
|
|
632
634
|
*/
|
|
633
|
-
_setHealth = (healthy: boolean) => {
|
|
635
|
+
_setHealth = (healthy: boolean, dispatchImmediately = false) => {
|
|
634
636
|
if (healthy === this.isHealthy) return;
|
|
635
637
|
|
|
636
638
|
this.isHealthy = healthy;
|
|
637
639
|
|
|
638
|
-
if (this.isHealthy) {
|
|
640
|
+
if (this.isHealthy || dispatchImmediately) {
|
|
639
641
|
this.client.dispatchEvent({
|
|
640
642
|
type: 'connection.changed',
|
|
641
643
|
online: this.isHealthy,
|