@stream-io/video-client 1.31.0 → 1.32.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/CHANGELOG.md +11 -0
- package/dist/index.browser.es.js +45 -11
- package/dist/index.browser.es.js.map +1 -1
- package/dist/index.cjs.js +45 -11
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.es.js +45 -11
- package/dist/index.es.js.map +1 -1
- package/dist/src/StreamVideoClient.d.ts +2 -0
- package/dist/src/coordinator/connection/types.d.ts +4 -0
- package/dist/src/gen/video/sfu/event/events.d.ts +8 -0
- package/package.json +1 -1
- package/src/Call.ts +6 -6
- package/src/StreamVideoClient.ts +42 -3
- package/src/coordinator/connection/types.ts +5 -0
- package/src/gen/video/sfu/event/events.ts +14 -0
package/dist/index.cjs.js
CHANGED
|
@@ -2951,6 +2951,12 @@ class JoinRequest$Type extends runtime.MessageType {
|
|
|
2951
2951
|
super('stream.video.sfu.event.JoinRequest', [
|
|
2952
2952
|
{ no: 1, name: 'token', kind: 'scalar', T: 9 /*ScalarType.STRING*/ },
|
|
2953
2953
|
{ no: 2, name: 'session_id', kind: 'scalar', T: 9 /*ScalarType.STRING*/ },
|
|
2954
|
+
{
|
|
2955
|
+
no: 13,
|
|
2956
|
+
name: 'unified_session_id',
|
|
2957
|
+
kind: 'scalar',
|
|
2958
|
+
T: 9 /*ScalarType.STRING*/,
|
|
2959
|
+
},
|
|
2954
2960
|
{
|
|
2955
2961
|
no: 3,
|
|
2956
2962
|
name: 'subscriber_sdp',
|
|
@@ -5760,7 +5766,7 @@ const getSdkVersion = (sdk) => {
|
|
|
5760
5766
|
return sdk ? `${sdk.major}.${sdk.minor}.${sdk.patch}` : '0.0.0-development';
|
|
5761
5767
|
};
|
|
5762
5768
|
|
|
5763
|
-
const version = "1.
|
|
5769
|
+
const version = "1.32.0";
|
|
5764
5770
|
const [major, minor, patch] = version.split('.');
|
|
5765
5771
|
let sdkInfo = {
|
|
5766
5772
|
type: SdkType.PLAIN_JAVASCRIPT,
|
|
@@ -11871,7 +11877,6 @@ class Call {
|
|
|
11871
11877
|
if ([exports.CallingState.JOINED, exports.CallingState.JOINING].includes(callingState)) {
|
|
11872
11878
|
throw new Error(`Illegal State: call.join() shall be called only once`);
|
|
11873
11879
|
}
|
|
11874
|
-
this.state.setCallingState(exports.CallingState.JOINING);
|
|
11875
11880
|
// we will count the number of join failures per SFU.
|
|
11876
11881
|
// once the number of failures reaches 2, we will piggyback on the `migrating_from`
|
|
11877
11882
|
// field to force the coordinator to provide us another SFU
|
|
@@ -11900,8 +11905,6 @@ class Call {
|
|
|
11900
11905
|
joinData.migrating_from = sfuId;
|
|
11901
11906
|
}
|
|
11902
11907
|
if (attempt === maxJoinRetries - 1) {
|
|
11903
|
-
// restore the previous call state if the join-flow fails
|
|
11904
|
-
this.state.setCallingState(callingState);
|
|
11905
11908
|
throw err;
|
|
11906
11909
|
}
|
|
11907
11910
|
}
|
|
@@ -11961,6 +11964,7 @@ class Call {
|
|
|
11961
11964
|
})
|
|
11962
11965
|
: previousSfuClient;
|
|
11963
11966
|
this.sfuClient = sfuClient;
|
|
11967
|
+
this.unifiedSessionId ?? (this.unifiedSessionId = sfuClient.sessionId);
|
|
11964
11968
|
this.dynascaleManager.setSfuClient(sfuClient);
|
|
11965
11969
|
const clientDetails = await getClientDetails();
|
|
11966
11970
|
// we don't need to send JoinRequest if we are re-using an existing healthy SFU client
|
|
@@ -11984,6 +11988,7 @@ class Call {
|
|
|
11984
11988
|
: [];
|
|
11985
11989
|
try {
|
|
11986
11990
|
const { callState, fastReconnectDeadlineSeconds, publishOptions } = await sfuClient.join({
|
|
11991
|
+
unifiedSessionId: this.unifiedSessionId,
|
|
11987
11992
|
subscriberSdp,
|
|
11988
11993
|
publisherSdp,
|
|
11989
11994
|
clientDetails,
|
|
@@ -12029,6 +12034,7 @@ class Call {
|
|
|
12029
12034
|
statsOptions,
|
|
12030
12035
|
publishOptions: this.currentPublishOptions || [],
|
|
12031
12036
|
closePreviousInstances: !performingMigration,
|
|
12037
|
+
unifiedSessionId: this.unifiedSessionId,
|
|
12032
12038
|
});
|
|
12033
12039
|
}
|
|
12034
12040
|
// make sure we only track connection timing if we are not calling this method as part of a reconnection flow
|
|
@@ -12155,7 +12161,7 @@ class Call {
|
|
|
12155
12161
|
* @internal
|
|
12156
12162
|
*/
|
|
12157
12163
|
this.initPublisherAndSubscriber = (opts) => {
|
|
12158
|
-
const { sfuClient, connectionConfig, clientDetails, statsOptions, publishOptions, closePreviousInstances, } = opts;
|
|
12164
|
+
const { sfuClient, connectionConfig, clientDetails, statsOptions, publishOptions, closePreviousInstances, unifiedSessionId, } = opts;
|
|
12159
12165
|
const { enable_rtc_stats: enableTracing } = statsOptions;
|
|
12160
12166
|
if (closePreviousInstances && this.subscriber) {
|
|
12161
12167
|
this.subscriber.dispose();
|
|
@@ -12210,7 +12216,6 @@ class Call {
|
|
|
12210
12216
|
this.tracer.setEnabled(enableTracing);
|
|
12211
12217
|
this.sfuStatsReporter?.stop();
|
|
12212
12218
|
if (statsOptions?.reporting_interval_ms > 0) {
|
|
12213
|
-
this.unifiedSessionId ?? (this.unifiedSessionId = sfuClient.sessionId);
|
|
12214
12219
|
this.sfuStatsReporter = new SfuStatsReporter(sfuClient, {
|
|
12215
12220
|
clientDetails,
|
|
12216
12221
|
options: statsOptions,
|
|
@@ -12220,7 +12225,7 @@ class Call {
|
|
|
12220
12225
|
camera: this.camera,
|
|
12221
12226
|
state: this.state,
|
|
12222
12227
|
tracer: this.tracer,
|
|
12223
|
-
unifiedSessionId
|
|
12228
|
+
unifiedSessionId,
|
|
12224
12229
|
});
|
|
12225
12230
|
this.sfuStatsReporter.start();
|
|
12226
12231
|
}
|
|
@@ -14540,7 +14545,7 @@ class StreamClient {
|
|
|
14540
14545
|
this.getUserAgent = () => {
|
|
14541
14546
|
if (!this.cachedUserAgent) {
|
|
14542
14547
|
const { clientAppIdentifier = {} } = this.options;
|
|
14543
|
-
const { sdkName = 'js', sdkVersion = "1.
|
|
14548
|
+
const { sdkName = 'js', sdkVersion = "1.32.0", ...extras } = clientAppIdentifier;
|
|
14544
14549
|
this.cachedUserAgent = [
|
|
14545
14550
|
`stream-video-${sdkName}-v${sdkVersion}`,
|
|
14546
14551
|
...Object.entries(extras).map(([key, value]) => `${key}=${value}`),
|
|
@@ -14729,6 +14734,7 @@ class StreamVideoClient {
|
|
|
14729
14734
|
this.effectsRegistered = false;
|
|
14730
14735
|
this.eventHandlersToUnregister = [];
|
|
14731
14736
|
this.connectionConcurrencyTag = Symbol('connectionConcurrencyTag');
|
|
14737
|
+
this.rejectCallWhenBusy = false;
|
|
14732
14738
|
this.registerClientInstance = (apiKey, user) => {
|
|
14733
14739
|
const instanceKey = getInstanceKey(apiKey, user);
|
|
14734
14740
|
if (StreamVideoClient._instances.has(instanceKey)) {
|
|
@@ -14774,7 +14780,16 @@ class StreamVideoClient {
|
|
|
14774
14780
|
let call = this.writeableStateStore.findCall(e.call.type, e.call.id);
|
|
14775
14781
|
if (call) {
|
|
14776
14782
|
if (ringing) {
|
|
14777
|
-
|
|
14783
|
+
if (this.shouldRejectCall(call.cid)) {
|
|
14784
|
+
this.logger('info', `Leaving call with busy reject reason ${call.cid} because user is busy`);
|
|
14785
|
+
// remove the instance from the state store
|
|
14786
|
+
await call.leave();
|
|
14787
|
+
// explicitly reject the call with busy reason as calling state was not ringing before and leave would not call it therefore
|
|
14788
|
+
await call.reject('busy');
|
|
14789
|
+
}
|
|
14790
|
+
else {
|
|
14791
|
+
await call.updateFromRingingEvent(e);
|
|
14792
|
+
}
|
|
14778
14793
|
}
|
|
14779
14794
|
else {
|
|
14780
14795
|
call.state.updateFromCallResponse(e.call);
|
|
@@ -14789,11 +14804,19 @@ class StreamVideoClient {
|
|
|
14789
14804
|
clientStore: this.writeableStateStore,
|
|
14790
14805
|
ringing,
|
|
14791
14806
|
});
|
|
14792
|
-
call.state.updateFromCallResponse(e.call);
|
|
14793
14807
|
if (ringing) {
|
|
14794
|
-
|
|
14808
|
+
if (this.shouldRejectCall(call.cid)) {
|
|
14809
|
+
this.logger('info', `Rejecting call ${call.cid} because user is busy`);
|
|
14810
|
+
// call is not in the state store yet, so just reject api is enough
|
|
14811
|
+
await call.reject('busy');
|
|
14812
|
+
}
|
|
14813
|
+
else {
|
|
14814
|
+
await call.updateFromRingingEvent(e);
|
|
14815
|
+
await call.get();
|
|
14816
|
+
}
|
|
14795
14817
|
}
|
|
14796
14818
|
else {
|
|
14819
|
+
call.state.updateFromCallResponse(e.call);
|
|
14797
14820
|
this.writeableStateStore.registerCall(call);
|
|
14798
14821
|
this.logger('info', `New call created and registered: ${call.cid}`);
|
|
14799
14822
|
}
|
|
@@ -15060,6 +15083,16 @@ class StreamVideoClient {
|
|
|
15060
15083
|
this.connectAnonymousUser = async (user, tokenOrProvider) => {
|
|
15061
15084
|
return withoutConcurrency(this.connectionConcurrencyTag, () => this.streamClient.connectAnonymousUser(user, tokenOrProvider));
|
|
15062
15085
|
};
|
|
15086
|
+
this.shouldRejectCall = (currentCallId) => {
|
|
15087
|
+
if (!this.rejectCallWhenBusy)
|
|
15088
|
+
return false;
|
|
15089
|
+
const hasOngoingRingingCall = this.state.calls.some((c) => c.cid !== currentCallId &&
|
|
15090
|
+
c.ringing &&
|
|
15091
|
+
c.state.callingState !== exports.CallingState.IDLE &&
|
|
15092
|
+
c.state.callingState !== exports.CallingState.LEFT &&
|
|
15093
|
+
c.state.callingState !== exports.CallingState.RECONNECTING_FAILED);
|
|
15094
|
+
return hasOngoingRingingCall;
|
|
15095
|
+
};
|
|
15063
15096
|
const apiKey = typeof apiKeyOrArgs === 'string' ? apiKeyOrArgs : apiKeyOrArgs.apiKey;
|
|
15064
15097
|
const clientOptions = typeof apiKeyOrArgs === 'string' ? opts : apiKeyOrArgs.options;
|
|
15065
15098
|
if (clientOptions?.enableTimerWorker)
|
|
@@ -15067,6 +15100,7 @@ class StreamVideoClient {
|
|
|
15067
15100
|
const rootLogger = clientOptions?.logger || logToConsole;
|
|
15068
15101
|
setLogger(rootLogger, clientOptions?.logLevel || 'warn');
|
|
15069
15102
|
this.logger = getLogger(['client']);
|
|
15103
|
+
this.rejectCallWhenBusy = clientOptions?.rejectCallWhenBusy ?? false;
|
|
15070
15104
|
this.streamClient = createCoordinatorClient(apiKey, clientOptions);
|
|
15071
15105
|
this.writeableStateStore = new StreamVideoWriteableStateStore();
|
|
15072
15106
|
this.readOnlyStateStore = new StreamVideoReadOnlyStateStore(this.writeableStateStore);
|