@stream-io/video-client 0.8.0 → 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -16,6 +16,7 @@ import {
16
16
  WireType,
17
17
  } from '@protobuf-ts/runtime';
18
18
  import {
19
+ CallEndedReason,
19
20
  CallGrants,
20
21
  CallState,
21
22
  ClientDetails,
@@ -31,6 +32,7 @@ import {
31
32
  TrackInfo,
32
33
  TrackType,
33
34
  TrackUnpublishReason,
35
+ WebsocketReconnectStrategy,
34
36
  } from '../models/models';
35
37
  import { TrackSubscriptionDetails } from '../signal_rpc/signal';
36
38
 
@@ -227,6 +229,25 @@ export interface SfuEvent {
227
229
  */
228
230
  pinsUpdated: PinsChanged;
229
231
  }
232
+ | {
233
+ oneofKind: 'callEnded';
234
+ /**
235
+ * CallEnded is sent by the SFU to the client to signal that the call has ended.
236
+ * The reason may specify why the call has ended.
237
+ *
238
+ * @generated from protobuf field: stream.video.sfu.event.CallEnded call_ended = 23;
239
+ */
240
+ callEnded: CallEnded;
241
+ }
242
+ | {
243
+ oneofKind: 'participantUpdated';
244
+ /**
245
+ * ParticipantUpdated is sent when user data is updated
246
+ *
247
+ * @generated from protobuf field: stream.video.sfu.event.ParticipantUpdated participant_updated = 24;
248
+ */
249
+ participantUpdated: ParticipantUpdated;
250
+ }
230
251
  | {
231
252
  oneofKind: undefined;
232
253
  };
@@ -251,6 +272,12 @@ export interface Error {
251
272
  * @generated from protobuf field: stream.video.sfu.models.Error error = 4;
252
273
  */
253
274
  error?: Error$;
275
+ /**
276
+ * returns the reconnect strategy to be used by the client
277
+ *
278
+ * @generated from protobuf field: stream.video.sfu.models.WebsocketReconnectStrategy reconnect_strategy = 5;
279
+ */
280
+ reconnectStrategy: WebsocketReconnectStrategy;
254
281
  }
255
282
  /**
256
283
  * @generated from protobuf message stream.video.sfu.event.ICETrickle
@@ -477,6 +504,21 @@ export interface ParticipantLeft {
477
504
  */
478
505
  participant?: Participant;
479
506
  }
507
+ /**
508
+ * ParticipantUpdated is fired when user data is updated
509
+ *
510
+ * @generated from protobuf message stream.video.sfu.event.ParticipantUpdated
511
+ */
512
+ export interface ParticipantUpdated {
513
+ /**
514
+ * @generated from protobuf field: string call_cid = 1;
515
+ */
516
+ callCid: string;
517
+ /**
518
+ * @generated from protobuf field: stream.video.sfu.models.Participant participant = 2;
519
+ */
520
+ participant?: Participant;
521
+ }
480
522
  /**
481
523
  * SubscriberOffer is sent when the SFU adds tracks to a subscription
482
524
  *
@@ -750,6 +792,18 @@ export interface GoAway {
750
792
  */
751
793
  reason: GoAwayReason;
752
794
  }
795
+ /**
796
+ * CallEnded is sent by the SFU to the client to signal that the call has ended.
797
+ * The reason may specify why the call has ended.
798
+ *
799
+ * @generated from protobuf message stream.video.sfu.event.CallEnded
800
+ */
801
+ export interface CallEnded {
802
+ /**
803
+ * @generated from protobuf field: stream.video.sfu.models.CallEndedReason reason = 1;
804
+ */
805
+ reason: CallEndedReason;
806
+ }
753
807
  // @generated message type with reflection information, may provide speed optimized methods
754
808
  class SfuEvent$Type extends MessageType<SfuEvent> {
755
809
  constructor() {
@@ -880,6 +934,20 @@ class SfuEvent$Type extends MessageType<SfuEvent> {
880
934
  oneof: 'eventPayload',
881
935
  T: () => PinsChanged,
882
936
  },
937
+ {
938
+ no: 23,
939
+ name: 'call_ended',
940
+ kind: 'message',
941
+ oneof: 'eventPayload',
942
+ T: () => CallEnded,
943
+ },
944
+ {
945
+ no: 24,
946
+ name: 'participant_updated',
947
+ kind: 'message',
948
+ oneof: 'eventPayload',
949
+ T: () => ParticipantUpdated,
950
+ },
883
951
  ]);
884
952
  }
885
953
  create(value?: PartialMessage<SfuEvent>): SfuEvent {
@@ -1099,6 +1167,28 @@ class SfuEvent$Type extends MessageType<SfuEvent> {
1099
1167
  ),
1100
1168
  };
1101
1169
  break;
1170
+ case /* stream.video.sfu.event.CallEnded call_ended */ 23:
1171
+ message.eventPayload = {
1172
+ oneofKind: 'callEnded',
1173
+ callEnded: CallEnded.internalBinaryRead(
1174
+ reader,
1175
+ reader.uint32(),
1176
+ options,
1177
+ (message.eventPayload as any).callEnded,
1178
+ ),
1179
+ };
1180
+ break;
1181
+ case /* stream.video.sfu.event.ParticipantUpdated participant_updated */ 24:
1182
+ message.eventPayload = {
1183
+ oneofKind: 'participantUpdated',
1184
+ participantUpdated: ParticipantUpdated.internalBinaryRead(
1185
+ reader,
1186
+ reader.uint32(),
1187
+ options,
1188
+ (message.eventPayload as any).participantUpdated,
1189
+ ),
1190
+ };
1191
+ break;
1102
1192
  default:
1103
1193
  let u = options.readUnknownField;
1104
1194
  if (u === 'throw')
@@ -1249,6 +1339,20 @@ class SfuEvent$Type extends MessageType<SfuEvent> {
1249
1339
  writer.tag(22, WireType.LengthDelimited).fork(),
1250
1340
  options,
1251
1341
  ).join();
1342
+ /* stream.video.sfu.event.CallEnded call_ended = 23; */
1343
+ if (message.eventPayload.oneofKind === 'callEnded')
1344
+ CallEnded.internalBinaryWrite(
1345
+ message.eventPayload.callEnded,
1346
+ writer.tag(23, WireType.LengthDelimited).fork(),
1347
+ options,
1348
+ ).join();
1349
+ /* stream.video.sfu.event.ParticipantUpdated participant_updated = 24; */
1350
+ if (message.eventPayload.oneofKind === 'participantUpdated')
1351
+ ParticipantUpdated.internalBinaryWrite(
1352
+ message.eventPayload.participantUpdated,
1353
+ writer.tag(24, WireType.LengthDelimited).fork(),
1354
+ options,
1355
+ ).join();
1252
1356
  let u = options.writeUnknownFields;
1253
1357
  if (u !== false)
1254
1358
  (u == true ? UnknownFieldHandler.onWrite : u)(
@@ -1349,10 +1453,21 @@ class Error$Type extends MessageType<Error> {
1349
1453
  constructor() {
1350
1454
  super('stream.video.sfu.event.Error', [
1351
1455
  { no: 4, name: 'error', kind: 'message', T: () => Error$ },
1456
+ {
1457
+ no: 5,
1458
+ name: 'reconnect_strategy',
1459
+ kind: 'enum',
1460
+ T: () => [
1461
+ 'stream.video.sfu.models.WebsocketReconnectStrategy',
1462
+ WebsocketReconnectStrategy,
1463
+ 'WEBSOCKET_RECONNECT_STRATEGY_',
1464
+ ],
1465
+ },
1352
1466
  ]);
1353
1467
  }
1354
1468
  create(value?: PartialMessage<Error>): Error {
1355
1469
  const message = globalThis.Object.create(this.messagePrototype!);
1470
+ message.reconnectStrategy = 0;
1356
1471
  if (value !== undefined)
1357
1472
  reflectionMergePartial<Error>(this, message, value);
1358
1473
  return message;
@@ -1376,6 +1491,9 @@ class Error$Type extends MessageType<Error> {
1376
1491
  message.error,
1377
1492
  );
1378
1493
  break;
1494
+ case /* stream.video.sfu.models.WebsocketReconnectStrategy reconnect_strategy */ 5:
1495
+ message.reconnectStrategy = reader.int32();
1496
+ break;
1379
1497
  default:
1380
1498
  let u = options.readUnknownField;
1381
1499
  if (u === 'throw')
@@ -1407,6 +1525,9 @@ class Error$Type extends MessageType<Error> {
1407
1525
  writer.tag(4, WireType.LengthDelimited).fork(),
1408
1526
  options,
1409
1527
  ).join();
1528
+ /* stream.video.sfu.models.WebsocketReconnectStrategy reconnect_strategy = 5; */
1529
+ if (message.reconnectStrategy !== 0)
1530
+ writer.tag(5, WireType.Varint).int32(message.reconnectStrategy);
1410
1531
  let u = options.writeUnknownFields;
1411
1532
  if (u !== false)
1412
1533
  (u == true ? UnknownFieldHandler.onWrite : u)(
@@ -2563,6 +2684,91 @@ class ParticipantLeft$Type extends MessageType<ParticipantLeft> {
2563
2684
  */
2564
2685
  export const ParticipantLeft = new ParticipantLeft$Type();
2565
2686
  // @generated message type with reflection information, may provide speed optimized methods
2687
+ class ParticipantUpdated$Type extends MessageType<ParticipantUpdated> {
2688
+ constructor() {
2689
+ super('stream.video.sfu.event.ParticipantUpdated', [
2690
+ { no: 1, name: 'call_cid', kind: 'scalar', T: 9 /*ScalarType.STRING*/ },
2691
+ { no: 2, name: 'participant', kind: 'message', T: () => Participant },
2692
+ ]);
2693
+ }
2694
+ create(value?: PartialMessage<ParticipantUpdated>): ParticipantUpdated {
2695
+ const message = globalThis.Object.create(this.messagePrototype!);
2696
+ message.callCid = '';
2697
+ if (value !== undefined)
2698
+ reflectionMergePartial<ParticipantUpdated>(this, message, value);
2699
+ return message;
2700
+ }
2701
+ internalBinaryRead(
2702
+ reader: IBinaryReader,
2703
+ length: number,
2704
+ options: BinaryReadOptions,
2705
+ target?: ParticipantUpdated,
2706
+ ): ParticipantUpdated {
2707
+ let message = target ?? this.create(),
2708
+ end = reader.pos + length;
2709
+ while (reader.pos < end) {
2710
+ let [fieldNo, wireType] = reader.tag();
2711
+ switch (fieldNo) {
2712
+ case /* string call_cid */ 1:
2713
+ message.callCid = reader.string();
2714
+ break;
2715
+ case /* stream.video.sfu.models.Participant participant */ 2:
2716
+ message.participant = Participant.internalBinaryRead(
2717
+ reader,
2718
+ reader.uint32(),
2719
+ options,
2720
+ message.participant,
2721
+ );
2722
+ break;
2723
+ default:
2724
+ let u = options.readUnknownField;
2725
+ if (u === 'throw')
2726
+ throw new globalThis.Error(
2727
+ `Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`,
2728
+ );
2729
+ let d = reader.skip(wireType);
2730
+ if (u !== false)
2731
+ (u === true ? UnknownFieldHandler.onRead : u)(
2732
+ this.typeName,
2733
+ message,
2734
+ fieldNo,
2735
+ wireType,
2736
+ d,
2737
+ );
2738
+ }
2739
+ }
2740
+ return message;
2741
+ }
2742
+ internalBinaryWrite(
2743
+ message: ParticipantUpdated,
2744
+ writer: IBinaryWriter,
2745
+ options: BinaryWriteOptions,
2746
+ ): IBinaryWriter {
2747
+ /* string call_cid = 1; */
2748
+ if (message.callCid !== '')
2749
+ writer.tag(1, WireType.LengthDelimited).string(message.callCid);
2750
+ /* stream.video.sfu.models.Participant participant = 2; */
2751
+ if (message.participant)
2752
+ Participant.internalBinaryWrite(
2753
+ message.participant,
2754
+ writer.tag(2, WireType.LengthDelimited).fork(),
2755
+ options,
2756
+ ).join();
2757
+ let u = options.writeUnknownFields;
2758
+ if (u !== false)
2759
+ (u == true ? UnknownFieldHandler.onWrite : u)(
2760
+ this.typeName,
2761
+ message,
2762
+ writer,
2763
+ );
2764
+ return writer;
2765
+ }
2766
+ }
2767
+ /**
2768
+ * @generated MessageType for protobuf message stream.video.sfu.event.ParticipantUpdated
2769
+ */
2770
+ export const ParticipantUpdated = new ParticipantUpdated$Type();
2771
+ // @generated message type with reflection information, may provide speed optimized methods
2566
2772
  class SubscriberOffer$Type extends MessageType<SubscriberOffer> {
2567
2773
  constructor() {
2568
2774
  super('stream.video.sfu.event.SubscriberOffer', [
@@ -3938,3 +4144,81 @@ class GoAway$Type extends MessageType<GoAway> {
3938
4144
  * @generated MessageType for protobuf message stream.video.sfu.event.GoAway
3939
4145
  */
3940
4146
  export const GoAway = new GoAway$Type();
4147
+ // @generated message type with reflection information, may provide speed optimized methods
4148
+ class CallEnded$Type extends MessageType<CallEnded> {
4149
+ constructor() {
4150
+ super('stream.video.sfu.event.CallEnded', [
4151
+ {
4152
+ no: 1,
4153
+ name: 'reason',
4154
+ kind: 'enum',
4155
+ T: () => [
4156
+ 'stream.video.sfu.models.CallEndedReason',
4157
+ CallEndedReason,
4158
+ 'CALL_ENDED_REASON_',
4159
+ ],
4160
+ },
4161
+ ]);
4162
+ }
4163
+ create(value?: PartialMessage<CallEnded>): CallEnded {
4164
+ const message = globalThis.Object.create(this.messagePrototype!);
4165
+ message.reason = 0;
4166
+ if (value !== undefined)
4167
+ reflectionMergePartial<CallEnded>(this, message, value);
4168
+ return message;
4169
+ }
4170
+ internalBinaryRead(
4171
+ reader: IBinaryReader,
4172
+ length: number,
4173
+ options: BinaryReadOptions,
4174
+ target?: CallEnded,
4175
+ ): CallEnded {
4176
+ let message = target ?? this.create(),
4177
+ end = reader.pos + length;
4178
+ while (reader.pos < end) {
4179
+ let [fieldNo, wireType] = reader.tag();
4180
+ switch (fieldNo) {
4181
+ case /* stream.video.sfu.models.CallEndedReason reason */ 1:
4182
+ message.reason = reader.int32();
4183
+ break;
4184
+ default:
4185
+ let u = options.readUnknownField;
4186
+ if (u === 'throw')
4187
+ throw new globalThis.Error(
4188
+ `Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`,
4189
+ );
4190
+ let d = reader.skip(wireType);
4191
+ if (u !== false)
4192
+ (u === true ? UnknownFieldHandler.onRead : u)(
4193
+ this.typeName,
4194
+ message,
4195
+ fieldNo,
4196
+ wireType,
4197
+ d,
4198
+ );
4199
+ }
4200
+ }
4201
+ return message;
4202
+ }
4203
+ internalBinaryWrite(
4204
+ message: CallEnded,
4205
+ writer: IBinaryWriter,
4206
+ options: BinaryWriteOptions,
4207
+ ): IBinaryWriter {
4208
+ /* stream.video.sfu.models.CallEndedReason reason = 1; */
4209
+ if (message.reason !== 0)
4210
+ writer.tag(1, WireType.Varint).int32(message.reason);
4211
+ let u = options.writeUnknownFields;
4212
+ if (u !== false)
4213
+ (u == true ? UnknownFieldHandler.onWrite : u)(
4214
+ this.typeName,
4215
+ message,
4216
+ writer,
4217
+ );
4218
+ return writer;
4219
+ }
4220
+ }
4221
+ /**
4222
+ * @generated MessageType for protobuf message stream.video.sfu.event.CallEnded
4223
+ */
4224
+ export const CallEnded = new CallEnded$Type();
@@ -692,6 +692,9 @@ export enum TrackUnpublishReason {
692
692
  MODERATION = 3,
693
693
  }
694
694
  /**
695
+ * GoAwayReason represents the reason for the SFU to
696
+ * disconnect the client.
697
+ *
695
698
  * @generated from protobuf enum stream.video.sfu.models.GoAwayReason
696
699
  */
697
700
  export enum GoAwayReason {
@@ -708,6 +711,73 @@ export enum GoAwayReason {
708
711
  */
709
712
  REBALANCE = 2,
710
713
  }
714
+ /**
715
+ * CallEndedReason represents the reason for the call to end.
716
+ *
717
+ * @generated from protobuf enum stream.video.sfu.models.CallEndedReason
718
+ */
719
+ export enum CallEndedReason {
720
+ /**
721
+ * @generated from protobuf enum value: CALL_ENDED_REASON_UNSPECIFIED = 0;
722
+ */
723
+ UNSPECIFIED = 0,
724
+ /**
725
+ * @generated from protobuf enum value: CALL_ENDED_REASON_ENDED = 1;
726
+ */
727
+ ENDED = 1,
728
+ /**
729
+ * @generated from protobuf enum value: CALL_ENDED_REASON_LIVE_ENDED = 2;
730
+ */
731
+ LIVE_ENDED = 2,
732
+ /**
733
+ * @generated from protobuf enum value: CALL_ENDED_REASON_KICKED = 3;
734
+ */
735
+ KICKED = 3,
736
+ }
737
+ /**
738
+ * WebsocketReconnectStrategy defines the ws strategies available for handling reconnections.
739
+ *
740
+ * @generated from protobuf enum stream.video.sfu.models.WebsocketReconnectStrategy
741
+ */
742
+ export enum WebsocketReconnectStrategy {
743
+ /**
744
+ * @generated from protobuf enum value: WEBSOCKET_RECONNECT_STRATEGY_UNSPECIFIED = 0;
745
+ */
746
+ UNSPECIFIED = 0,
747
+ /**
748
+ * Sent after reaching the maximum reconnection attempts, leading to permanent disconnect.
749
+ *
750
+ * @generated from protobuf enum value: WEBSOCKET_RECONNECT_STRATEGY_DISCONNECT = 1;
751
+ */
752
+ DISCONNECT = 1,
753
+ /**
754
+ * SDK should maintaining existing publisher/subscriber pc instances
755
+ * and establish a new WebSocket connection.
756
+ *
757
+ * @generated from protobuf enum value: WEBSOCKET_RECONNECT_STRATEGY_FAST = 2;
758
+ */
759
+ FAST = 2,
760
+ /**
761
+ * SDK should drop existing pc instances and creates a fresh WebSocket connection,
762
+ * ensuring a clean state for the reconnection.
763
+ *
764
+ * @generated from protobuf enum value: WEBSOCKET_RECONNECT_STRATEGY_CLEAN = 3;
765
+ */
766
+ CLEAN = 3,
767
+ /**
768
+ * SDK should obtain new credentials from the coordinator, drops existing pc instances, and initializes
769
+ * a completely new WebSocket connection, ensuring a comprehensive reset.
770
+ *
771
+ * @generated from protobuf enum value: WEBSOCKET_RECONNECT_STRATEGY_FULL = 4;
772
+ */
773
+ FULL = 4,
774
+ /**
775
+ * SDK should migrate to a new SFU instance
776
+ *
777
+ * @generated from protobuf enum value: WEBSOCKET_RECONNECT_STRATEGY_MIGRATE = 5;
778
+ */
779
+ MIGRATE = 5,
780
+ }
711
781
  // @generated message type with reflection information, may provide speed optimized methods
712
782
  class CallState$Type extends MessageType<CallState> {
713
783
  constructor() {
@@ -39,6 +39,8 @@ const sfuEventKinds: { [key in SfuEventKinds]: undefined } = {
39
39
  goAway: undefined,
40
40
  iceRestart: undefined,
41
41
  pinsUpdated: undefined,
42
+ callEnded: undefined,
43
+ participantUpdated: undefined,
42
44
  };
43
45
 
44
46
  export const isSfuEvent = (
@@ -1006,12 +1006,14 @@ export class CallState {
1006
1006
  };
1007
1007
 
1008
1008
  private updateFromMemberRemoved = (event: CallMemberRemovedEvent) => {
1009
+ this.updateFromCallResponse(event.call);
1009
1010
  this.setCurrentValue(this.membersSubject, (members) =>
1010
1011
  members.filter((m) => event.members.indexOf(m.user_id) === -1),
1011
1012
  );
1012
1013
  };
1013
1014
 
1014
1015
  private updateFromMemberAdded = (event: CallMemberAddedEvent) => {
1016
+ this.updateFromCallResponse(event.call);
1015
1017
  this.setCurrentValue(this.membersSubject, (members) => [
1016
1018
  ...members,
1017
1019
  ...event.members,
@@ -1123,6 +1125,7 @@ export class CallState {
1123
1125
  private updateMembers = (
1124
1126
  event: CallMemberUpdatedEvent | CallMemberUpdatedPermissionEvent,
1125
1127
  ) => {
1128
+ this.updateFromCallResponse(event.call);
1126
1129
  this.setCurrentValue(this.membersSubject, (members) =>
1127
1130
  members.map((member) => {
1128
1131
  const memberUpdate = event.members.find(
@@ -534,8 +534,10 @@ describe('CallState', () => {
534
534
  state.setMembers(initialMembers);
535
535
  state.updateFromEvent({
536
536
  type: 'call.member_added',
537
- // @ts-ignore
537
+ // @ts-expect-error incomplete data
538
538
  members: [{ user_id: 'user1' }, { user_id: 'user2' }],
539
+ // @ts-expect-error incomplete data
540
+ call: {},
539
541
  });
540
542
 
541
543
  const updatedMembers = state.members;
@@ -560,6 +562,8 @@ describe('CallState', () => {
560
562
  state.updateFromEvent({
561
563
  type: 'call.member_removed',
562
564
  members: removedMembers,
565
+ // @ts-expect-error incomplete data
566
+ call: {},
563
567
  });
564
568
 
565
569
  const updatedMembers = state.members;
@@ -609,6 +613,8 @@ describe('CallState', () => {
609
613
  role: 'host',
610
614
  },
611
615
  ],
616
+ // @ts-expect-error incomplete data
617
+ call: {},
612
618
  });
613
619
 
614
620
  const updatedMembers = state.members;
@@ -643,6 +649,8 @@ describe('CallState', () => {
643
649
  type: 'call.member_updated',
644
650
  // @ts-ignore
645
651
  members: [{ ...user1, user: { name: 'John' } }],
652
+ // @ts-expect-error incomplete data
653
+ call: {},
646
654
  });
647
655
 
648
656
  const updatedMembers = state.members;