@stream-io/video-client 1.11.6 → 1.11.8
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 +98 -575
- package/dist/index.browser.es.js.map +1 -1
- package/dist/index.cjs.js +83 -560
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.es.js +98 -575
- package/dist/index.es.js.map +1 -1
- package/dist/src/coordinator/connection/client.d.ts +0 -18
- package/dist/src/coordinator/connection/connection.d.ts +4 -12
- package/dist/src/coordinator/connection/signing.d.ts +1 -7
- package/dist/src/coordinator/connection/token_manager.d.ts +0 -2
- package/dist/src/coordinator/connection/types.d.ts +5 -6
- package/dist/src/coordinator/connection/utils.d.ts +6 -8
- package/dist/src/rtc/codecs.d.ts +1 -1
- package/package.json +6 -10
- package/src/__tests__/Call.test.ts +3 -2
- package/src/coordinator/connection/client.ts +12 -149
- package/src/coordinator/connection/connection.ts +40 -109
- package/src/coordinator/connection/signing.ts +31 -17
- package/src/coordinator/connection/token_manager.ts +3 -9
- package/src/coordinator/connection/types.ts +5 -9
- package/src/coordinator/connection/utils.ts +18 -50
- package/src/devices/__tests__/InputMediaDeviceManagerState.test.ts +13 -8
- package/src/devices/__tests__/mocks.ts +0 -4
- package/src/helpers/__tests__/sdp-munging.test.ts +92 -0
- package/src/helpers/sdp-munging.ts +10 -6
- package/src/rtc/Publisher.ts +10 -3
- package/src/rtc/__tests__/codecs.test.ts +6 -6
- package/src/rtc/codecs.ts +20 -9
- package/dist/src/coordinator/connection/base64.d.ts +0 -2
- package/dist/src/coordinator/connection/connection_fallback.d.ts +0 -39
- package/dist/src/coordinator/connection/errors.d.ts +0 -16
- package/dist/src/coordinator/connection/insights.d.ts +0 -57
- package/src/coordinator/connection/base64.ts +0 -80
- package/src/coordinator/connection/connection_fallback.ts +0 -242
- package/src/coordinator/connection/errors.ts +0 -80
- package/src/coordinator/connection/insights.ts +0 -88
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
import { AxiosInstance, AxiosRequestConfig, AxiosResponse } from 'axios';
|
|
2
2
|
import { StableWSConnection } from './connection';
|
|
3
3
|
import { TokenManager } from './token_manager';
|
|
4
|
-
import { WSConnectionFallback } from './connection_fallback';
|
|
5
4
|
import { AllClientEvents, AllClientEventTypes, APIErrorResponse, ClientEventListener, ConnectAPIResponse, ErrorFromResponse, Logger, StreamClientOptions, StreamVideoEvent, TokenOrProvider, User, UserWithId } from './types';
|
|
6
|
-
import { InsightMetrics } from './insights';
|
|
7
5
|
import { ConnectedEvent, CreateGuestResponse } from '../../gen/coordinator';
|
|
8
6
|
export declare class StreamClient {
|
|
9
7
|
_user?: UserWithId;
|
|
@@ -27,11 +25,8 @@ export declare class StreamClient {
|
|
|
27
25
|
userID?: string;
|
|
28
26
|
wsBaseURL?: string;
|
|
29
27
|
wsConnection: StableWSConnection | null;
|
|
30
|
-
wsFallback?: WSConnectionFallback;
|
|
31
28
|
private wsPromiseSafe;
|
|
32
29
|
consecutiveFailures: number;
|
|
33
|
-
insightMetrics: InsightMetrics;
|
|
34
|
-
defaultWSTimeoutWithFallback: number;
|
|
35
30
|
defaultWSTimeout: number;
|
|
36
31
|
resolveConnectionId?: Function;
|
|
37
32
|
rejectConnectionId?: Function;
|
|
@@ -50,7 +45,6 @@ export declare class StreamClient {
|
|
|
50
45
|
* @param {httpsAgent} [options.httpsAgent] - custom httpsAgent, in node it's default to https.agent()
|
|
51
46
|
*/
|
|
52
47
|
constructor(key: string, options?: StreamClientOptions);
|
|
53
|
-
devToken: (userID: string) => string;
|
|
54
48
|
getAuthType: () => "anonymous" | "jwt";
|
|
55
49
|
setBaseURL: (baseURL: string) => void;
|
|
56
50
|
getLocationHint: (hintUrl?: string, timeout?: number) => Promise<string>;
|
|
@@ -147,12 +141,6 @@ export declare class StreamClient {
|
|
|
147
141
|
* @private
|
|
148
142
|
*/
|
|
149
143
|
connect: () => Promise<ConnectedEvent | undefined>;
|
|
150
|
-
/**
|
|
151
|
-
* Check the connectivity with server for warmup purpose.
|
|
152
|
-
*
|
|
153
|
-
* @private
|
|
154
|
-
*/
|
|
155
|
-
_sayHi: () => void;
|
|
156
144
|
getUserAgent: () => string;
|
|
157
145
|
setUserAgent: (userAgent: string) => void;
|
|
158
146
|
/**
|
|
@@ -165,12 +153,6 @@ export declare class StreamClient {
|
|
|
165
153
|
publicEndpoint?: boolean;
|
|
166
154
|
}) => AxiosRequestConfig;
|
|
167
155
|
_getToken: () => string | null | undefined;
|
|
168
|
-
/**
|
|
169
|
-
* encode ws url payload
|
|
170
|
-
* @private
|
|
171
|
-
* @returns json string
|
|
172
|
-
*/
|
|
173
|
-
_buildWSPayload: (client_request_id?: string) => string;
|
|
174
156
|
updateNetworkConnectionStatus: (event: {
|
|
175
157
|
type: "online" | "offline";
|
|
176
158
|
} | Event) => void;
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import WebSocket from 'isomorphic-ws';
|
|
2
1
|
import { StreamClient } from './client';
|
|
3
2
|
import type { LogLevel, UR } from './types';
|
|
4
3
|
import type { ConnectedEvent } from '../../gen/coordinator';
|
|
@@ -22,7 +21,6 @@ import type { ConnectedEvent } from '../../gen/coordinator';
|
|
|
22
21
|
export declare class StableWSConnection {
|
|
23
22
|
connectionID?: string;
|
|
24
23
|
private connectionOpenSafe?;
|
|
25
|
-
authenticationSent: boolean;
|
|
26
24
|
consecutiveFailures: number;
|
|
27
25
|
pingInterval: number;
|
|
28
26
|
healthCheckTimeoutRef?: NodeJS.Timeout;
|
|
@@ -96,27 +94,21 @@ export declare class StableWSConnection {
|
|
|
96
94
|
*/
|
|
97
95
|
onlineStatusChanged: (event: Event) => void;
|
|
98
96
|
onopen: (wsID: number) => void;
|
|
99
|
-
onmessage: (wsID: number, event:
|
|
100
|
-
onclose: (wsID: number, event:
|
|
101
|
-
onerror: (wsID: number, event:
|
|
97
|
+
onmessage: (wsID: number, event: MessageEvent) => void;
|
|
98
|
+
onclose: (wsID: number, event: CloseEvent) => void;
|
|
99
|
+
onerror: (wsID: number, event: Event) => void;
|
|
102
100
|
/**
|
|
103
101
|
* _setHealth - Sets the connection to healthy or unhealthy.
|
|
104
102
|
* Broadcasts an event in case the connection status changed.
|
|
105
103
|
*
|
|
106
104
|
* @param {boolean} healthy boolean indicating if the connection is healthy or not
|
|
107
105
|
* @param {boolean} dispatchImmediately boolean indicating to dispatch event immediately even if the connection is unhealthy
|
|
108
|
-
*
|
|
109
106
|
*/
|
|
110
107
|
_setHealth: (healthy: boolean, dispatchImmediately?: boolean) => void;
|
|
111
108
|
/**
|
|
112
109
|
* _errorFromWSEvent - Creates an error object for the WS event
|
|
113
|
-
*
|
|
114
110
|
*/
|
|
115
|
-
_errorFromWSEvent
|
|
116
|
-
code?: string | number;
|
|
117
|
-
isWSFailure?: boolean;
|
|
118
|
-
StatusCode?: string | number;
|
|
119
|
-
};
|
|
111
|
+
private _errorFromWSEvent;
|
|
120
112
|
/**
|
|
121
113
|
* _destroyCurrentWSConnection - Removes the current WS connection
|
|
122
114
|
*
|
|
@@ -1,7 +1 @@
|
|
|
1
|
-
|
|
2
|
-
*
|
|
3
|
-
* @param {string} userId the id of the user
|
|
4
|
-
* @return {string}
|
|
5
|
-
*/
|
|
6
|
-
export declare function DevToken(userId: string): string;
|
|
7
|
-
export declare function UserFromToken(token: string): string;
|
|
1
|
+
export declare function getUserFromToken(token: string): string | undefined;
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { AxiosRequestConfig, AxiosResponse } from 'axios';
|
|
2
|
-
import { StableWSConnection } from './connection';
|
|
3
2
|
import { ConnectedEvent, UserRequest, WSEvent } from '../../gen/coordinator';
|
|
4
3
|
import { AllSfuEvents } from '../../rtc';
|
|
5
4
|
export type UR = Record<string, unknown>;
|
|
@@ -90,9 +89,6 @@ export type StreamClientOptions = Partial<AxiosRequestConfig> & {
|
|
|
90
89
|
*/
|
|
91
90
|
baseURL?: string;
|
|
92
91
|
browser?: boolean;
|
|
93
|
-
enableInsights?: boolean;
|
|
94
|
-
/** experimental feature, please contact support if you want this feature enabled for you */
|
|
95
|
-
enableWSFallback?: boolean;
|
|
96
92
|
logger?: Logger;
|
|
97
93
|
logLevel?: LogLevel;
|
|
98
94
|
/**
|
|
@@ -118,8 +114,11 @@ export type StreamClientOptions = Partial<AxiosRequestConfig> & {
|
|
|
118
114
|
* The secret key for the API key. This is only needed for server side authentication.
|
|
119
115
|
*/
|
|
120
116
|
secret?: string;
|
|
121
|
-
|
|
122
|
-
|
|
117
|
+
/**
|
|
118
|
+
* The WebSocket implementation to use. This is mainly useful for testing.
|
|
119
|
+
* In Node.js environment, you can use the `ws` package.
|
|
120
|
+
*/
|
|
121
|
+
WebSocketImpl?: typeof WebSocket;
|
|
123
122
|
};
|
|
124
123
|
export type TokenProvider = () => Promise<string>;
|
|
125
124
|
export type TokenOrProvider = null | string | TokenProvider | undefined;
|
|
@@ -1,5 +1,7 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
1
|
+
import type { AxiosResponse } from 'axios';
|
|
2
|
+
import type { APIErrorResponse } from './types';
|
|
3
|
+
import type { ConnectionErrorEvent } from '../../gen/coordinator';
|
|
4
|
+
export declare const sleep: (m: number) => Promise<unknown>;
|
|
3
5
|
export declare function isFunction<T>(value: Function | T): value is Function;
|
|
4
6
|
/**
|
|
5
7
|
* A map of known error codes.
|
|
@@ -18,18 +20,14 @@ export declare const KnownCodes: {
|
|
|
18
20
|
export declare function retryInterval(numberOfFailures: number): number;
|
|
19
21
|
export declare function randomId(): string;
|
|
20
22
|
export declare function generateUUIDv4(): string;
|
|
21
|
-
export declare function convertErrorToJson(err: Error): Record<string, unknown>;
|
|
22
23
|
/**
|
|
23
24
|
* Informs if a promise is yet to be resolved or rejected
|
|
24
25
|
*/
|
|
25
26
|
export declare function isPromisePending<T>(promise: Promise<T>): Promise<boolean>;
|
|
26
|
-
/**
|
|
27
|
-
* isOnline safely return the navigator.online value for browser env
|
|
28
|
-
* if navigator is not in global object, it always return true
|
|
29
|
-
*/
|
|
30
|
-
export declare function isOnline(logger: Logger): boolean;
|
|
31
27
|
/**
|
|
32
28
|
* listenForConnectionChanges - Adds an event listener fired on browser going online or offline
|
|
33
29
|
*/
|
|
34
30
|
export declare function addConnectionEventListeners(cb: (e: Event) => void): void;
|
|
35
31
|
export declare function removeConnectionEventListeners(cb: (e: Event) => void): void;
|
|
32
|
+
export declare function isErrorResponse(res: AxiosResponse<unknown>): res is AxiosResponse<APIErrorResponse>;
|
|
33
|
+
export declare function isCloseEvent(res: CloseEvent | ConnectionErrorEvent): res is CloseEvent;
|
package/dist/src/rtc/codecs.d.ts
CHANGED
|
@@ -7,7 +7,7 @@ import type { PreferredCodec } from '../types';
|
|
|
7
7
|
* @param codecToRemove the codec to exclude from the list.
|
|
8
8
|
* @param codecPreferencesSource the source of the codec preferences.
|
|
9
9
|
*/
|
|
10
|
-
export declare const getPreferredCodecs: (kind: "audio" | "video", preferredCodec: string, codecToRemove
|
|
10
|
+
export declare const getPreferredCodecs: (kind: "audio" | "video", preferredCodec: string, codecToRemove: string | undefined, codecPreferencesSource: "sender" | "receiver") => RTCRtpCodec[] | undefined;
|
|
11
11
|
/**
|
|
12
12
|
* Returns a generic SDP for the given direction.
|
|
13
13
|
* We use this SDP to send it as part of our JoinRequest so that the SFU
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@stream-io/video-client",
|
|
3
|
-
"version": "1.11.
|
|
3
|
+
"version": "1.11.8",
|
|
4
4
|
"packageManager": "yarn@3.2.4",
|
|
5
5
|
"main": "dist/index.cjs.js",
|
|
6
6
|
"module": "dist/index.es.js",
|
|
@@ -31,15 +31,11 @@
|
|
|
31
31
|
"@protobuf-ts/runtime": "^2.9.4",
|
|
32
32
|
"@protobuf-ts/runtime-rpc": "^2.9.4",
|
|
33
33
|
"@protobuf-ts/twirp-transport": "^2.9.4",
|
|
34
|
-
"
|
|
35
|
-
"axios": "^1.6.0",
|
|
36
|
-
"base64-js": "^1.5.1",
|
|
37
|
-
"isomorphic-ws": "^5.0.0",
|
|
34
|
+
"axios": "^1.7.7",
|
|
38
35
|
"rxjs": "~7.8.1",
|
|
39
36
|
"sdp-transform": "^2.14.1",
|
|
40
37
|
"ua-parser-js": "^1.0.36",
|
|
41
|
-
"webrtc-adapter": "^8.2.3"
|
|
42
|
-
"ws": "^8.14.2"
|
|
38
|
+
"webrtc-adapter": "^8.2.3"
|
|
43
39
|
},
|
|
44
40
|
"devDependencies": {
|
|
45
41
|
"@openapitools/openapi-generator-cli": "^2.13.4",
|
|
@@ -49,7 +45,7 @@
|
|
|
49
45
|
"@stream-io/node-sdk": "^0.4.3",
|
|
50
46
|
"@types/sdp-transform": "^2.4.7",
|
|
51
47
|
"@types/ua-parser-js": "^0.7.37",
|
|
52
|
-
"@vitest/coverage-v8": "^
|
|
48
|
+
"@vitest/coverage-v8": "^2.1.4",
|
|
53
49
|
"dotenv": "^16.3.1",
|
|
54
50
|
"happy-dom": "^11.0.2",
|
|
55
51
|
"prettier": "^3.3.2",
|
|
@@ -57,7 +53,7 @@
|
|
|
57
53
|
"rollup": "^4.22.0",
|
|
58
54
|
"typescript": "^5.5.2",
|
|
59
55
|
"vite": "^5.4.6",
|
|
60
|
-
"vitest": "^1.
|
|
61
|
-
"vitest-mock-extended": "^
|
|
56
|
+
"vitest": "^2.1.4",
|
|
57
|
+
"vitest-mock-extended": "^2.0.2"
|
|
62
58
|
}
|
|
63
59
|
}
|
|
@@ -10,7 +10,7 @@ import {
|
|
|
10
10
|
import { StreamVideoClient } from '../StreamVideoClient';
|
|
11
11
|
import 'dotenv/config';
|
|
12
12
|
import { StreamClient } from '@stream-io/node-sdk';
|
|
13
|
-
import { generateUUIDv4 } from '../coordinator/connection/utils';
|
|
13
|
+
import { generateUUIDv4, sleep } from '../coordinator/connection/utils';
|
|
14
14
|
import { CallingState } from '../store';
|
|
15
15
|
import { Dispatcher } from '../rtc';
|
|
16
16
|
import { Call } from '../Call';
|
|
@@ -22,7 +22,7 @@ const secret = process.env.STREAM_SECRET!;
|
|
|
22
22
|
const serverClient = new StreamClient(apiKey, secret);
|
|
23
23
|
const userId = 'jane';
|
|
24
24
|
const tokenProvider = async () =>
|
|
25
|
-
serverClient.
|
|
25
|
+
serverClient.generateUserToken({ user_id: userId, role: 'user' });
|
|
26
26
|
|
|
27
27
|
let client: StreamVideoClient;
|
|
28
28
|
|
|
@@ -34,6 +34,7 @@ beforeEach(async () => {
|
|
|
34
34
|
user: { id: 'jane' },
|
|
35
35
|
});
|
|
36
36
|
|
|
37
|
+
await sleep(50);
|
|
37
38
|
await client.streamClient.wsPromise;
|
|
38
39
|
});
|
|
39
40
|
|
|
@@ -1,27 +1,22 @@
|
|
|
1
1
|
import axios, {
|
|
2
2
|
AxiosError,
|
|
3
|
-
AxiosHeaders,
|
|
4
3
|
AxiosInstance,
|
|
5
4
|
AxiosRequestConfig,
|
|
6
5
|
AxiosResponse,
|
|
7
6
|
} from 'axios';
|
|
8
7
|
import https from 'https';
|
|
9
8
|
import { StableWSConnection } from './connection';
|
|
10
|
-
import { DevToken } from './signing';
|
|
11
9
|
import { TokenManager } from './token_manager';
|
|
12
|
-
import { WSConnectionFallback } from './connection_fallback';
|
|
13
|
-
import { isErrorResponse, isWSFailure } from './errors';
|
|
14
10
|
import {
|
|
15
11
|
addConnectionEventListeners,
|
|
12
|
+
isErrorResponse,
|
|
16
13
|
isFunction,
|
|
17
|
-
isOnline,
|
|
18
14
|
KnownCodes,
|
|
19
15
|
randomId,
|
|
20
16
|
removeConnectionEventListeners,
|
|
21
17
|
retryInterval,
|
|
22
18
|
sleep,
|
|
23
19
|
} from './utils';
|
|
24
|
-
|
|
25
20
|
import {
|
|
26
21
|
AllClientEvents,
|
|
27
22
|
AllClientEventTypes,
|
|
@@ -36,7 +31,6 @@ import {
|
|
|
36
31
|
User,
|
|
37
32
|
UserWithId,
|
|
38
33
|
} from './types';
|
|
39
|
-
import { InsightMetrics, postInsights } from './insights';
|
|
40
34
|
import { getLocationHint } from './location';
|
|
41
35
|
import {
|
|
42
36
|
ConnectedEvent,
|
|
@@ -71,11 +65,8 @@ export class StreamClient {
|
|
|
71
65
|
userID?: string;
|
|
72
66
|
wsBaseURL?: string;
|
|
73
67
|
wsConnection: StableWSConnection | null;
|
|
74
|
-
wsFallback?: WSConnectionFallback;
|
|
75
68
|
private wsPromiseSafe: SafePromise<ConnectedEvent | undefined> | null;
|
|
76
69
|
consecutiveFailures: number;
|
|
77
|
-
insightMetrics: InsightMetrics;
|
|
78
|
-
defaultWSTimeoutWithFallback: number;
|
|
79
70
|
defaultWSTimeout: number;
|
|
80
71
|
resolveConnectionId?: Function;
|
|
81
72
|
rejectConnectionId?: Function;
|
|
@@ -122,7 +113,6 @@ export class StreamClient {
|
|
|
122
113
|
this.options = {
|
|
123
114
|
timeout: 5000,
|
|
124
115
|
withCredentials: false, // making sure cookies are not sent
|
|
125
|
-
warmUp: false,
|
|
126
116
|
...inputOptions,
|
|
127
117
|
};
|
|
128
118
|
|
|
@@ -137,22 +127,6 @@ export class StreamClient {
|
|
|
137
127
|
this.options.baseURL || 'https://video.stream-io-api.com/video',
|
|
138
128
|
);
|
|
139
129
|
|
|
140
|
-
if (
|
|
141
|
-
typeof process !== 'undefined' &&
|
|
142
|
-
'env' in process &&
|
|
143
|
-
process.env.STREAM_LOCAL_TEST_RUN
|
|
144
|
-
) {
|
|
145
|
-
this.setBaseURL('http://localhost:3030/video');
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
if (
|
|
149
|
-
typeof process !== 'undefined' &&
|
|
150
|
-
'env' in process &&
|
|
151
|
-
process.env.STREAM_LOCAL_TEST_HOST
|
|
152
|
-
) {
|
|
153
|
-
this.setBaseURL(`http://${process.env.STREAM_LOCAL_TEST_HOST}/video`);
|
|
154
|
-
}
|
|
155
|
-
|
|
156
130
|
this.axiosInstance = axios.create({
|
|
157
131
|
...this.options,
|
|
158
132
|
baseURL: this.baseURL,
|
|
@@ -172,9 +146,7 @@ export class StreamClient {
|
|
|
172
146
|
// generated from secret.
|
|
173
147
|
this.tokenManager = new TokenManager(this.secret);
|
|
174
148
|
this.consecutiveFailures = 0;
|
|
175
|
-
this.insightMetrics = new InsightMetrics();
|
|
176
149
|
|
|
177
|
-
this.defaultWSTimeoutWithFallback = 6000;
|
|
178
150
|
this.defaultWSTimeout = 15000;
|
|
179
151
|
|
|
180
152
|
this.logger = isFunction(inputOptions.logger)
|
|
@@ -182,10 +154,6 @@ export class StreamClient {
|
|
|
182
154
|
: () => null;
|
|
183
155
|
}
|
|
184
156
|
|
|
185
|
-
devToken = (userID: string) => {
|
|
186
|
-
return DevToken(userID);
|
|
187
|
-
};
|
|
188
|
-
|
|
189
157
|
getAuthType = () => {
|
|
190
158
|
return this.anonymous ? 'anonymous' : 'jwt';
|
|
191
159
|
};
|
|
@@ -212,8 +180,7 @@ export class StreamClient {
|
|
|
212
180
|
return hint;
|
|
213
181
|
};
|
|
214
182
|
|
|
215
|
-
_getConnectionID = () =>
|
|
216
|
-
this.wsConnection?.connectionID || this.wsFallback?.connectionID;
|
|
183
|
+
_getConnectionID = () => this.wsConnection?.connectionID;
|
|
217
184
|
|
|
218
185
|
_hasConnectionID = () => Boolean(this._getConnectionID());
|
|
219
186
|
|
|
@@ -328,11 +295,7 @@ export class StreamClient {
|
|
|
328
295
|
* https://developer.mozilla.org/en-US/docs/Web/API/CloseEvent
|
|
329
296
|
*/
|
|
330
297
|
closeConnection = async (timeout?: number) => {
|
|
331
|
-
await
|
|
332
|
-
this.wsConnection?.disconnect(timeout),
|
|
333
|
-
this.wsFallback?.disconnect(timeout),
|
|
334
|
-
]);
|
|
335
|
-
return Promise.resolve();
|
|
298
|
+
await this.wsConnection?.disconnect(timeout);
|
|
336
299
|
};
|
|
337
300
|
|
|
338
301
|
/**
|
|
@@ -354,10 +317,7 @@ export class StreamClient {
|
|
|
354
317
|
return await wsPromise;
|
|
355
318
|
}
|
|
356
319
|
|
|
357
|
-
if (
|
|
358
|
-
(this.wsConnection?.isHealthy || this.wsFallback?.isHealthy()) &&
|
|
359
|
-
this._hasConnectionID()
|
|
360
|
-
) {
|
|
320
|
+
if (this.wsConnection?.isHealthy && this._hasConnectionID()) {
|
|
361
321
|
this.logger(
|
|
362
322
|
'info',
|
|
363
323
|
'client:openConnection() - openConnection called twice, healthy connection already exists',
|
|
@@ -366,7 +326,7 @@ export class StreamClient {
|
|
|
366
326
|
return;
|
|
367
327
|
}
|
|
368
328
|
|
|
369
|
-
this._setupConnectionIdPromise();
|
|
329
|
+
await this._setupConnectionIdPromise();
|
|
370
330
|
|
|
371
331
|
this.clientID = `${this.userID}--${randomId()}`;
|
|
372
332
|
const newWsPromise = this.connect();
|
|
@@ -404,16 +364,7 @@ export class StreamClient {
|
|
|
404
364
|
this.guestUserCreatePromise = this.doAxiosRequest<
|
|
405
365
|
CreateGuestResponse,
|
|
406
366
|
CreateGuestRequest
|
|
407
|
-
>(
|
|
408
|
-
'post',
|
|
409
|
-
'/guest',
|
|
410
|
-
{
|
|
411
|
-
user: {
|
|
412
|
-
...user,
|
|
413
|
-
},
|
|
414
|
-
},
|
|
415
|
-
{ publicEndpoint: true },
|
|
416
|
-
);
|
|
367
|
+
>('post', '/guest', { user }, { publicEndpoint: true });
|
|
417
368
|
|
|
418
369
|
const response = await this.guestUserCreatePromise;
|
|
419
370
|
this.guestUserCreatePromise.finally(
|
|
@@ -431,7 +382,7 @@ export class StreamClient {
|
|
|
431
382
|
tokenOrProvider: TokenOrProvider,
|
|
432
383
|
) => {
|
|
433
384
|
addConnectionEventListeners(this.updateNetworkConnectionStatus);
|
|
434
|
-
this._setupConnectionIdPromise();
|
|
385
|
+
await this._setupConnectionIdPromise();
|
|
435
386
|
|
|
436
387
|
this.anonymous = true;
|
|
437
388
|
await this._setToken(user, tokenOrProvider, this.anonymous);
|
|
@@ -705,89 +656,14 @@ export class StreamClient {
|
|
|
705
656
|
'Call connectUser or connectAnonymousUser before starting the connection',
|
|
706
657
|
);
|
|
707
658
|
}
|
|
708
|
-
if (!this.wsBaseURL)
|
|
709
|
-
|
|
710
|
-
}
|
|
711
|
-
if (!this.clientID) {
|
|
712
|
-
throw Error('clientID is not set');
|
|
713
|
-
}
|
|
659
|
+
if (!this.wsBaseURL) throw Error('Websocket base url not set');
|
|
660
|
+
if (!this.clientID) throw Error('clientID is not set');
|
|
714
661
|
|
|
715
|
-
if (
|
|
716
|
-
!this.wsConnection &&
|
|
717
|
-
(this.options.warmUp || this.options.enableInsights)
|
|
718
|
-
) {
|
|
719
|
-
this._sayHi();
|
|
720
|
-
}
|
|
721
662
|
// The StableWSConnection handles all the reconnection logic.
|
|
722
|
-
|
|
723
|
-
// Intentionally avoiding adding ts generics on wsConnection in options since its only useful for unit test purpose.
|
|
724
|
-
(this.options.wsConnection as unknown as StableWSConnection).setClient(
|
|
725
|
-
this,
|
|
726
|
-
);
|
|
727
|
-
this.wsConnection = this.options
|
|
728
|
-
.wsConnection as unknown as StableWSConnection;
|
|
729
|
-
} else {
|
|
730
|
-
this.wsConnection = new StableWSConnection(this);
|
|
731
|
-
}
|
|
663
|
+
this.wsConnection = new StableWSConnection(this);
|
|
732
664
|
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
if (this.wsFallback) {
|
|
736
|
-
return await this.wsFallback.connect();
|
|
737
|
-
}
|
|
738
|
-
this.logger('info', 'StreamClient.connect: this.wsConnection.connect()');
|
|
739
|
-
// if WSFallback is enabled, ws connect should timeout faster so fallback can try
|
|
740
|
-
return await this.wsConnection.connect(
|
|
741
|
-
this.options.enableWSFallback
|
|
742
|
-
? this.defaultWSTimeoutWithFallback
|
|
743
|
-
: this.defaultWSTimeout,
|
|
744
|
-
);
|
|
745
|
-
} catch (err) {
|
|
746
|
-
// run fallback only if it's WS/Network error and not a normal API error
|
|
747
|
-
// make sure browser is online before even trying the longpoll
|
|
748
|
-
if (
|
|
749
|
-
this.options.enableWSFallback &&
|
|
750
|
-
// @ts-ignore
|
|
751
|
-
isWSFailure(err) &&
|
|
752
|
-
isOnline(this.logger)
|
|
753
|
-
) {
|
|
754
|
-
this.logger(
|
|
755
|
-
'warn',
|
|
756
|
-
'client:connect() - WS failed, fallback to longpoll',
|
|
757
|
-
);
|
|
758
|
-
this.dispatchEvent({ type: 'transport.changed', mode: 'longpoll' });
|
|
759
|
-
|
|
760
|
-
this.wsConnection._destroyCurrentWSConnection();
|
|
761
|
-
this.wsConnection.disconnect().then(); // close WS so no retry
|
|
762
|
-
this.wsFallback = new WSConnectionFallback(this);
|
|
763
|
-
return await this.wsFallback.connect();
|
|
764
|
-
}
|
|
765
|
-
|
|
766
|
-
throw err;
|
|
767
|
-
}
|
|
768
|
-
};
|
|
769
|
-
|
|
770
|
-
/**
|
|
771
|
-
* Check the connectivity with server for warmup purpose.
|
|
772
|
-
*
|
|
773
|
-
* @private
|
|
774
|
-
*/
|
|
775
|
-
_sayHi = () => {
|
|
776
|
-
const client_request_id = randomId();
|
|
777
|
-
const opts = {
|
|
778
|
-
headers: AxiosHeaders.from({
|
|
779
|
-
'x-client-request-id': client_request_id,
|
|
780
|
-
}),
|
|
781
|
-
};
|
|
782
|
-
this.doAxiosRequest('get', this.baseURL + '/hi', null, opts).catch((e) => {
|
|
783
|
-
if (this.options.enableInsights) {
|
|
784
|
-
postInsights('http_hi_failed', {
|
|
785
|
-
api_key: this.key,
|
|
786
|
-
err: e,
|
|
787
|
-
client_request_id,
|
|
788
|
-
});
|
|
789
|
-
}
|
|
790
|
-
});
|
|
665
|
+
this.logger('info', 'StreamClient.connect: this.wsConnection.connect()');
|
|
666
|
+
return await this.wsConnection.connect(this.defaultWSTimeout);
|
|
791
667
|
};
|
|
792
668
|
|
|
793
669
|
getUserAgent = () => {
|
|
@@ -856,19 +732,6 @@ export class StreamClient {
|
|
|
856
732
|
return this.tokenManager.getToken();
|
|
857
733
|
};
|
|
858
734
|
|
|
859
|
-
/**
|
|
860
|
-
* encode ws url payload
|
|
861
|
-
* @private
|
|
862
|
-
* @returns json string
|
|
863
|
-
*/
|
|
864
|
-
_buildWSPayload = (client_request_id?: string) => {
|
|
865
|
-
return JSON.stringify({
|
|
866
|
-
user_id: this.userID,
|
|
867
|
-
user_details: this._user,
|
|
868
|
-
client_request_id,
|
|
869
|
-
});
|
|
870
|
-
};
|
|
871
|
-
|
|
872
735
|
updateNetworkConnectionStatus = (
|
|
873
736
|
event: { type: 'online' | 'offline' } | Event,
|
|
874
737
|
) => {
|