@stream-io/video-client 0.0.8 → 0.0.10

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/index.es.js CHANGED
@@ -5695,6 +5695,19 @@ class Publisher {
5695
5695
  return this.notifyTrackMuteStateChanged(undefined, transceiver.sender.track, trackType, true);
5696
5696
  }
5697
5697
  });
5698
+ /**
5699
+ * Returns true if the given track type is currently being published to the SFU.
5700
+ *
5701
+ * @param trackType the track type to check.
5702
+ */
5703
+ this.isPublishing = (trackType) => {
5704
+ const transceiverForTrackType = this.transceiverRegistry[trackType];
5705
+ if (transceiverForTrackType && transceiverForTrackType.sender) {
5706
+ const sender = transceiverForTrackType.sender;
5707
+ return !!sender.track && sender.track.readyState === 'live';
5708
+ }
5709
+ return false;
5710
+ };
5698
5711
  this.notifyTrackMuteStateChanged = (mediaStream, track, trackType, isMuted) => __awaiter(this, void 0, void 0, function* () {
5699
5712
  yield this.sfuClient.updateMuteState(trackType, isMuted);
5700
5713
  const audioOrVideoOrScreenShareStream = trackTypeToParticipantStreamKey(trackType);
@@ -9294,20 +9307,22 @@ class Call {
9294
9307
  createSubscription(this.state.ownCapabilities$, (ownCapabilities) => {
9295
9308
  // update the permission context.
9296
9309
  this.permissionsContext.setPermissions(ownCapabilities);
9310
+ if (!this.publisher)
9311
+ return;
9297
9312
  // check if the user still has publishing permissions and stop publishing if not.
9298
9313
  const permissionToTrackType = {
9299
9314
  [OwnCapability.SEND_AUDIO]: TrackType.AUDIO,
9300
9315
  [OwnCapability.SEND_VIDEO]: TrackType.VIDEO,
9301
9316
  [OwnCapability.SCREENSHARE]: TrackType.SCREEN_SHARE,
9302
9317
  };
9303
- Object.entries(permissionToTrackType).forEach(([permission, type]) => {
9318
+ for (const [permission, trackType] of Object.entries(permissionToTrackType)) {
9304
9319
  const hasPermission = this.permissionsContext.hasPermission(permission);
9305
- if (!hasPermission) {
9306
- this.stopPublish(type).catch((err) => {
9307
- console.error('Error stopping publish', type, err);
9320
+ if (!hasPermission && this.publisher.isPublishing(trackType)) {
9321
+ this.stopPublish(trackType).catch((err) => {
9322
+ console.error('Error stopping publish', trackType, err);
9308
9323
  });
9309
9324
  }
9310
- });
9325
+ }
9311
9326
  }),
9312
9327
  // handles the case when the user is blocked by the call owner.
9313
9328
  createSubscription(this.state.metadata$, (metadata) => __awaiter(this, void 0, void 0, function* () {
@@ -10206,7 +10221,7 @@ class TokenManager {
10206
10221
  return;
10207
10222
  // Don't allow empty token for non-server side client.
10208
10223
  if (!this.secret && !tokenOrProvider) {
10209
- throw new Error('User token can not be empty');
10224
+ throw new Error('UserWithId token can not be empty');
10210
10225
  }
10211
10226
  if (tokenOrProvider &&
10212
10227
  typeof tokenOrProvider !== 'string' &&
@@ -10519,7 +10534,7 @@ class StreamClient {
10519
10534
  /**
10520
10535
  * connectUser - Set the current user and open a WebSocket connection
10521
10536
  *
10522
- * @param {OwnUserResponse} user Data about this user. IE {name: "john"}
10537
+ * @param user Data about this user. IE {name: "john"}
10523
10538
  * @param {TokenOrProvider} userTokenOrProvider Token or provider
10524
10539
  *
10525
10540
  * @return {ConnectAPIResponse} Returns a promise that resolves when the connection is setup
@@ -10596,7 +10611,7 @@ class StreamClient {
10596
10611
  this.openConnection = () => __awaiter(this, void 0, void 0, function* () {
10597
10612
  var _d, _e, _f;
10598
10613
  if (!this.userID) {
10599
- throw Error('User is not set on client, use client.connectUser or client.connectAnonymousUser instead');
10614
+ throw Error('UserWithId is not set on client, use client.connectUser or client.connectAnonymousUser instead');
10600
10615
  }
10601
10616
  if (((_d = this.wsConnection) === null || _d === void 0 ? void 0 : _d.isConnecting) && this.wsPromise) {
10602
10617
  this.logger('info', 'client:openConnection() - connection already in progress', {
@@ -10656,7 +10671,9 @@ class StreamClient {
10656
10671
  });
10657
10672
  this.doAxiosRequest = (type, url, data, options = {}) => __awaiter(this, void 0, void 0, function* () {
10658
10673
  var _g;
10659
- yield this.tokenManager.tokenReady();
10674
+ if (!options.publicEndpoint || this.user) {
10675
+ yield this.tokenManager.tokenReady();
10676
+ }
10660
10677
  const requestConfig = this._enrichAxiosOptions(options);
10661
10678
  try {
10662
10679
  let response;
@@ -11009,7 +11026,7 @@ class StreamClient {
11009
11026
  }
11010
11027
  getUserAgent() {
11011
11028
  return (this.userAgent ||
11012
- `stream-video-javascript-client-${this.node ? 'node' : 'browser'}-${"0.0.7"}`);
11029
+ `stream-video-javascript-client-${this.node ? 'node' : 'browser'}-${"0.0.9"}`);
11013
11030
  }
11014
11031
  setUserAgent(userAgent) {
11015
11032
  this.userAgent = userAgent;
@@ -11020,7 +11037,7 @@ class StreamClient {
11020
11037
  config: {},
11021
11038
  }) {
11022
11039
  var _a;
11023
- const token = this._getToken();
11040
+ const token = options.publicEndpoint && !this.user ? undefined : this._getToken();
11024
11041
  const authorization = token ? { Authorization: token } : undefined;
11025
11042
  let signal = null;
11026
11043
  if (this.nextRequestAbortController !== null) {
@@ -11030,7 +11047,9 @@ class StreamClient {
11030
11047
  if (!((_a = options.headers) === null || _a === void 0 ? void 0 : _a['x-client-request-id'])) {
11031
11048
  options.headers = Object.assign(Object.assign({}, options.headers), { 'x-client-request-id': randomId() });
11032
11049
  }
11033
- return Object.assign(Object.assign(Object.assign({ params: Object.assign({ user_id: this.userID, connection_id: this._getConnectionID(), api_key: this.key }, options.params), headers: Object.assign(Object.assign(Object.assign({}, authorization), { 'stream-auth-type': this.getAuthType(), 'X-Stream-Client': this.getUserAgent() }), options.headers) }, (signal ? { signal } : {})), options.config), this.options.axiosRequestConfig);
11050
+ return Object.assign(Object.assign(Object.assign({ params: Object.assign({ user_id: this.userID, connection_id: this._getConnectionID(), api_key: this.key }, options.params), headers: Object.assign(Object.assign(Object.assign({}, authorization), { 'stream-auth-type': options.publicEndpoint && !this.user
11051
+ ? 'anonymous'
11052
+ : this.getAuthType(), 'X-Stream-Client': this.getUserAgent() }), options.headers) }, (signal ? { signal } : {})), options.config), this.options.axiosRequestConfig);
11034
11053
  }
11035
11054
  _getToken() {
11036
11055
  if (!this.tokenManager)
@@ -11047,7 +11066,7 @@ class StreamClient {
11047
11066
  * createToken - Creates a token to authenticate this user. This function is used server side.
11048
11067
  * The resulting token should be passed to the client side when the users registers or logs in.
11049
11068
  *
11050
- * @param {string} userID The User ID
11069
+ * @param {string} userID The UserWithId ID
11051
11070
  * @param {number} [exp] The expiration time for the token expressed in the number of seconds since the epoch
11052
11071
  * @param call_cids for anonymous tokens you have to provide the call cids the use can join
11053
11072
  *
@@ -11082,108 +11101,6 @@ class StreamVideoClient {
11082
11101
  */
11083
11102
  constructor(apiKey, opts) {
11084
11103
  this.eventHandlersToUnregister = [];
11085
- /**
11086
- * Connects the given user to the client.
11087
- * Only one user can connect at a time, if you want to change users, call `disconnectUser` before connecting a new user.
11088
- * If the connection is successful, the connected user [state variable](#readonlystatestore) will be updated accordingly.
11089
- *
11090
- * @param user the user to connect.
11091
- * @param tokenOrProvider a token or a function that returns a token.
11092
- */
11093
- this.connectUser = (user, tokenOrProvider) => __awaiter(this, void 0, void 0, function* () {
11094
- var _a;
11095
- const connectUser = () => {
11096
- return this.streamClient.connectUser(
11097
- // @ts-expect-error
11098
- user, tokenOrProvider);
11099
- };
11100
- this.connectionPromise = this.disconnectionPromise
11101
- ? this.disconnectionPromise.then(() => connectUser())
11102
- : connectUser();
11103
- (_a = this.connectionPromise) === null || _a === void 0 ? void 0 : _a.finally(() => (this.connectionPromise = undefined));
11104
- const connectUserResponse = yield this.connectionPromise;
11105
- this.writeableStateStore.setConnectedUser(user);
11106
- this.eventHandlersToUnregister.push(this.on('connection.changed', (e) => {
11107
- const event = e;
11108
- if (event.online) {
11109
- const callsToReWatch = this.writeableStateStore.calls
11110
- .filter((call) => call.watching)
11111
- .map((call) => call.cid);
11112
- if (callsToReWatch.length > 0) {
11113
- this.queryCalls({
11114
- watch: true,
11115
- filter_conditions: {
11116
- cid: { $in: callsToReWatch },
11117
- },
11118
- sort: [{ field: 'cid', direction: 1 }],
11119
- }).catch((err) => {
11120
- console.warn('Failed to re-watch calls', err);
11121
- });
11122
- }
11123
- }
11124
- }));
11125
- this.eventHandlersToUnregister.push(this.on('call.created', (event) => {
11126
- if (event.type !== 'call.created')
11127
- return;
11128
- const { call, members } = event;
11129
- if (user.id === call.created_by.id) {
11130
- console.warn('Received `call.created` sent by the current user');
11131
- return;
11132
- }
11133
- this.writeableStateStore.registerCall(new Call({
11134
- streamClient: this.streamClient,
11135
- type: call.type,
11136
- id: call.id,
11137
- metadata: call,
11138
- members,
11139
- clientStore: this.writeableStateStore,
11140
- }));
11141
- }));
11142
- this.eventHandlersToUnregister.push(this.on('call.ring', (event) => __awaiter(this, void 0, void 0, function* () {
11143
- if (event.type !== 'call.ring')
11144
- return;
11145
- const { call, members } = event;
11146
- if (user.id === call.created_by.id) {
11147
- console.warn('Received `call.ring` sent by the current user');
11148
- return;
11149
- }
11150
- // The call might already be tracked by the client,
11151
- // if `call.created` was received before `call.ring`.
11152
- // In that case, we just reuse the already tracked call.
11153
- let theCall = this.writeableStateStore.findCall(call.type, call.id);
11154
- if (!theCall) {
11155
- // otherwise, we create a new call
11156
- theCall = new Call({
11157
- streamClient: this.streamClient,
11158
- type: call.type,
11159
- id: call.id,
11160
- members,
11161
- clientStore: this.writeableStateStore,
11162
- ringing: true,
11163
- });
11164
- }
11165
- // we fetch the latest metadata for the call from the server
11166
- yield theCall.get({ ring: true });
11167
- this.writeableStateStore.registerCall(theCall);
11168
- })));
11169
- return connectUserResponse;
11170
- });
11171
- /**
11172
- * Connects the given anonymous user to the client.
11173
- *
11174
- * @param user the user to connect.
11175
- * @param tokenOrProvider a token or a function that returns a token.
11176
- */
11177
- this.connectAnonymousUser = (user, tokenOrProvider) => __awaiter(this, void 0, void 0, function* () {
11178
- const connectAnonymousUser = () =>
11179
- // @ts-expect-error
11180
- this.streamClient.connectAnonymousUser(user, tokenOrProvider);
11181
- this.connectionPromise = this.disconnectionPromise
11182
- ? this.disconnectionPromise.then(() => connectAnonymousUser())
11183
- : connectAnonymousUser();
11184
- this.connectionPromise.finally(() => (this.connectionPromise = undefined));
11185
- return this.connectionPromise;
11186
- });
11187
11104
  /**
11188
11105
  * Disconnects the currently connected user from the client.
11189
11106
  *
@@ -11244,7 +11161,7 @@ class StreamVideoClient {
11244
11161
  * @param data the data for the guest user.
11245
11162
  */
11246
11163
  this.createGuestUser = (data) => __awaiter(this, void 0, void 0, function* () {
11247
- return this.streamClient.post('/guest', data);
11164
+ return this.streamClient.doAxiosRequest('post', '/guest', data, { publicEndpoint: true });
11248
11165
  });
11249
11166
  /**
11250
11167
  * Will query the API for calls matching the given filters.
@@ -11325,10 +11242,123 @@ class StreamVideoClient {
11325
11242
  this.removeDevice = (id, userID) => __awaiter(this, void 0, void 0, function* () {
11326
11243
  return yield this.streamClient.delete('/devices', Object.assign({ id }, (userID ? { user_id: userID } : {})));
11327
11244
  });
11245
+ /**
11246
+ * Connects the given anonymous user to the client.
11247
+ *
11248
+ * @param user the user to connect.
11249
+ * @param tokenOrProvider a token or a function that returns a token.
11250
+ */
11251
+ this.connectAnonymousUser = (user, tokenOrProvider) => __awaiter(this, void 0, void 0, function* () {
11252
+ const connectAnonymousUser = () => this.streamClient.connectAnonymousUser(user, tokenOrProvider);
11253
+ this.connectionPromise = this.disconnectionPromise
11254
+ ? this.disconnectionPromise.then(() => connectAnonymousUser())
11255
+ : connectAnonymousUser();
11256
+ this.connectionPromise.finally(() => (this.connectionPromise = undefined));
11257
+ return this.connectionPromise;
11258
+ });
11328
11259
  this.streamClient = new StreamClient(apiKey, Object.assign({ persistUserOnConnectionFailure: true }, opts));
11329
11260
  this.writeableStateStore = new StreamVideoWriteableStateStore();
11330
11261
  this.readOnlyStateStore = new StreamVideoReadOnlyStateStore(this.writeableStateStore);
11331
11262
  }
11263
+ /**
11264
+ * Connects the given user to the client.
11265
+ * Only one user can connect at a time, if you want to change users, call `disconnectUser` before connecting a new user.
11266
+ * If the connection is successful, the connected user [state variable](#readonlystatestore) will be updated accordingly.
11267
+ *
11268
+ * @param user the user to connect.
11269
+ * @param tokenOrProvider a token or a function that returns a token.
11270
+ */
11271
+ connectUser(user, token) {
11272
+ var _a;
11273
+ return __awaiter(this, void 0, void 0, function* () {
11274
+ if (user.type === 'anonymous') {
11275
+ user.id = '!anon';
11276
+ return this.connectAnonymousUser(user, token);
11277
+ }
11278
+ if (user.type === 'guest') {
11279
+ const response = yield this.createGuestUser({
11280
+ user: Object.assign(Object.assign({}, user), { role: 'guest' }),
11281
+ });
11282
+ return this.connectUser(response.user, response.access_token);
11283
+ }
11284
+ const connectUser = () => {
11285
+ return this.streamClient.connectUser(user, token);
11286
+ };
11287
+ this.connectionPromise = this.disconnectionPromise
11288
+ ? this.disconnectionPromise.then(() => connectUser())
11289
+ : connectUser();
11290
+ (_a = this.connectionPromise) === null || _a === void 0 ? void 0 : _a.finally(() => (this.connectionPromise = undefined));
11291
+ const connectUserResponse = yield this.connectionPromise;
11292
+ // connectUserResponse will be void if connectUser called twice for the same user
11293
+ if (connectUserResponse === null || connectUserResponse === void 0 ? void 0 : connectUserResponse.me) {
11294
+ this.writeableStateStore.setConnectedUser(connectUserResponse.me);
11295
+ }
11296
+ this.eventHandlersToUnregister.push(this.on('connection.changed', (e) => {
11297
+ const event = e;
11298
+ if (event.online) {
11299
+ const callsToReWatch = this.writeableStateStore.calls
11300
+ .filter((call) => call.watching)
11301
+ .map((call) => call.cid);
11302
+ if (callsToReWatch.length > 0) {
11303
+ this.queryCalls({
11304
+ watch: true,
11305
+ filter_conditions: {
11306
+ cid: { $in: callsToReWatch },
11307
+ },
11308
+ sort: [{ field: 'cid', direction: 1 }],
11309
+ }).catch((err) => {
11310
+ console.warn('Failed to re-watch calls', err);
11311
+ });
11312
+ }
11313
+ }
11314
+ }));
11315
+ this.eventHandlersToUnregister.push(this.on('call.created', (event) => {
11316
+ if (event.type !== 'call.created')
11317
+ return;
11318
+ const { call, members } = event;
11319
+ if (user.id === call.created_by.id) {
11320
+ console.warn('Received `call.created` sent by the current user');
11321
+ return;
11322
+ }
11323
+ this.writeableStateStore.registerCall(new Call({
11324
+ streamClient: this.streamClient,
11325
+ type: call.type,
11326
+ id: call.id,
11327
+ metadata: call,
11328
+ members,
11329
+ clientStore: this.writeableStateStore,
11330
+ }));
11331
+ }));
11332
+ this.eventHandlersToUnregister.push(this.on('call.ring', (event) => __awaiter(this, void 0, void 0, function* () {
11333
+ if (event.type !== 'call.ring')
11334
+ return;
11335
+ const { call, members } = event;
11336
+ if (user.id === call.created_by.id) {
11337
+ console.warn('Received `call.ring` sent by the current user');
11338
+ return;
11339
+ }
11340
+ // The call might already be tracked by the client,
11341
+ // if `call.created` was received before `call.ring`.
11342
+ // In that case, we just reuse the already tracked call.
11343
+ let theCall = this.writeableStateStore.findCall(call.type, call.id);
11344
+ if (!theCall) {
11345
+ // otherwise, we create a new call
11346
+ theCall = new Call({
11347
+ streamClient: this.streamClient,
11348
+ type: call.type,
11349
+ id: call.id,
11350
+ members,
11351
+ clientStore: this.writeableStateStore,
11352
+ ringing: true,
11353
+ });
11354
+ }
11355
+ // we fetch the latest metadata for the call from the server
11356
+ yield theCall.get({ ring: true });
11357
+ this.writeableStateStore.registerCall(theCall);
11358
+ })));
11359
+ return connectUserResponse;
11360
+ });
11361
+ }
11332
11362
  /**
11333
11363
  * addDevice - Adds a push device for a user.
11334
11364
  *