@stream-io/video-client 0.0.9 → 0.0.11
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 +126 -111
- package/dist/index.browser.es.js.map +1 -1
- package/dist/index.cjs.js +126 -111
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.es.js +126 -111
- package/dist/index.es.js.map +1 -1
- package/dist/src/Call.d.ts +4 -4
- package/dist/src/StreamVideoClient.d.ts +8 -8
- package/dist/src/coordinator/connection/client.d.ts +13 -9
- package/dist/src/coordinator/connection/insights.d.ts +2 -2
- package/dist/src/coordinator/connection/token_manager.d.ts +4 -4
- package/dist/src/coordinator/connection/types.d.ts +17 -12
- package/dist/src/store/stateStore.d.ts +6 -6
- package/package.json +3 -3
- package/src/Call.ts +4 -4
- package/src/StreamVideoClient.ts +47 -32
- package/src/coordinator/connection/client.ts +23 -15
- package/src/coordinator/connection/token_manager.ts +5 -5
- package/src/coordinator/connection/types.ts +16 -10
- package/src/events/__tests__/call.test.ts +6 -0
- package/src/store/stateStore.ts +8 -6
package/dist/src/Call.d.ts
CHANGED
|
@@ -41,14 +41,14 @@ export declare class Call {
|
|
|
41
41
|
* updates from the backend.
|
|
42
42
|
*/
|
|
43
43
|
watching: boolean;
|
|
44
|
-
/**
|
|
45
|
-
* The permissions context of this call.
|
|
46
|
-
*/
|
|
47
|
-
readonly permissionsContext: PermissionsContext;
|
|
48
44
|
/**
|
|
49
45
|
* Flag telling whether this call is a "ringing" call.
|
|
50
46
|
*/
|
|
51
47
|
private readonly ringingSubject;
|
|
48
|
+
/**
|
|
49
|
+
* The permissions context of this call.
|
|
50
|
+
*/
|
|
51
|
+
readonly permissionsContext: PermissionsContext;
|
|
52
52
|
/**
|
|
53
53
|
* The event dispatcher instance dedicated to this Call instance.
|
|
54
54
|
* @private
|
|
@@ -30,14 +30,7 @@ export declare class StreamVideoClient {
|
|
|
30
30
|
* @param user the user to connect.
|
|
31
31
|
* @param tokenOrProvider a token or a function that returns a token.
|
|
32
32
|
*/
|
|
33
|
-
connectUser
|
|
34
|
-
/**
|
|
35
|
-
* Connects the given anonymous user to the client.
|
|
36
|
-
*
|
|
37
|
-
* @param user the user to connect.
|
|
38
|
-
* @param tokenOrProvider a token or a function that returns a token.
|
|
39
|
-
*/
|
|
40
|
-
connectAnonymousUser: (user: User, tokenOrProvider: TokenOrProvider) => Promise<void | ConnectedEvent>;
|
|
33
|
+
connectUser(user: User, token: TokenOrProvider): Promise<void | ConnectedEvent>;
|
|
41
34
|
/**
|
|
42
35
|
* Disconnects the currently connected user from the client.
|
|
43
36
|
*
|
|
@@ -137,4 +130,11 @@ export declare class StreamVideoClient {
|
|
|
137
130
|
* @return {string} Returns a token
|
|
138
131
|
*/
|
|
139
132
|
createToken(userID: string, exp?: number, iat?: number, call_cids?: string[]): string;
|
|
133
|
+
/**
|
|
134
|
+
* Connects the given anonymous user to the client.
|
|
135
|
+
*
|
|
136
|
+
* @param user the user to connect.
|
|
137
|
+
* @param tokenOrProvider a token or a function that returns a token.
|
|
138
|
+
*/
|
|
139
|
+
private connectAnonymousUser;
|
|
140
140
|
}
|
|
@@ -4,10 +4,10 @@ import WebSocket from 'isomorphic-ws';
|
|
|
4
4
|
import { StableWSConnection } from './connection';
|
|
5
5
|
import { TokenManager } from './token_manager';
|
|
6
6
|
import { WSConnectionFallback } from './connection_fallback';
|
|
7
|
-
import { APIErrorResponse, ConnectAPIResponse, ErrorFromResponse, EventHandler, Logger,
|
|
7
|
+
import { APIErrorResponse, ConnectAPIResponse, ErrorFromResponse, EventHandler, Logger, StreamClientOptions, StreamVideoEvent, TokenOrProvider, UserWithId } from './types';
|
|
8
8
|
import { InsightMetrics } from './insights';
|
|
9
9
|
export declare class StreamClient {
|
|
10
|
-
_user?:
|
|
10
|
+
_user?: UserWithId;
|
|
11
11
|
anonymous: boolean;
|
|
12
12
|
persistUserOnConnectionFailure?: boolean;
|
|
13
13
|
axiosInstance: AxiosInstance;
|
|
@@ -23,7 +23,7 @@ export declare class StreamClient {
|
|
|
23
23
|
secret?: string;
|
|
24
24
|
setUserPromise: ConnectAPIResponse | null;
|
|
25
25
|
tokenManager: TokenManager;
|
|
26
|
-
user?:
|
|
26
|
+
user?: UserWithId;
|
|
27
27
|
userAgent?: string;
|
|
28
28
|
userID?: string;
|
|
29
29
|
wsBaseURL?: string;
|
|
@@ -59,14 +59,14 @@ export declare class StreamClient {
|
|
|
59
59
|
/**
|
|
60
60
|
* connectUser - Set the current user and open a WebSocket connection
|
|
61
61
|
*
|
|
62
|
-
* @param
|
|
62
|
+
* @param user Data about this user. IE {name: "john"}
|
|
63
63
|
* @param {TokenOrProvider} userTokenOrProvider Token or provider
|
|
64
64
|
*
|
|
65
65
|
* @return {ConnectAPIResponse} Returns a promise that resolves when the connection is setup
|
|
66
66
|
*/
|
|
67
|
-
connectUser: (user:
|
|
68
|
-
_setToken: (user:
|
|
69
|
-
_setUser(user:
|
|
67
|
+
connectUser: (user: UserWithId, userTokenOrProvider: TokenOrProvider) => Promise<void | import("../../..").ConnectedEvent>;
|
|
68
|
+
_setToken: (user: UserWithId, userTokenOrProvider: TokenOrProvider, isAnonymous: boolean) => Promise<void>;
|
|
69
|
+
_setUser(user: UserWithId): void;
|
|
70
70
|
/**
|
|
71
71
|
* Disconnects the websocket connection, without removing the user set on client.
|
|
72
72
|
* client.closeConnection will not trigger default auto-retry mechanism for reconnection. You need
|
|
@@ -96,7 +96,7 @@ export declare class StreamClient {
|
|
|
96
96
|
/**
|
|
97
97
|
* connectAnonymousUser - Set an anonymous user and open a WebSocket connection
|
|
98
98
|
*/
|
|
99
|
-
connectAnonymousUser: (user:
|
|
99
|
+
connectAnonymousUser: (user: UserWithId, tokenOrProvider: TokenOrProvider) => Promise<void>;
|
|
100
100
|
/**
|
|
101
101
|
* on - Listen to events on all channels and users your watching
|
|
102
102
|
*
|
|
@@ -126,6 +126,8 @@ export declare class StreamClient {
|
|
|
126
126
|
config?: AxiosRequestConfig & {
|
|
127
127
|
maxBodyLength?: number;
|
|
128
128
|
};
|
|
129
|
+
} & {
|
|
130
|
+
publicEndpoint?: boolean;
|
|
129
131
|
}) => Promise<T>;
|
|
130
132
|
get<T>(url: string, params?: AxiosRequestConfig['params']): Promise<T>;
|
|
131
133
|
put<T, D = unknown>(url: string, data?: D): Promise<T>;
|
|
@@ -155,6 +157,8 @@ export declare class StreamClient {
|
|
|
155
157
|
_isUsingServerAuth: () => boolean;
|
|
156
158
|
_enrichAxiosOptions(options?: AxiosRequestConfig & {
|
|
157
159
|
config?: AxiosRequestConfig;
|
|
160
|
+
} & {
|
|
161
|
+
publicEndpoint?: boolean;
|
|
158
162
|
}): AxiosRequestConfig;
|
|
159
163
|
_getToken(): string | null | undefined;
|
|
160
164
|
/**
|
|
@@ -171,7 +175,7 @@ export declare class StreamClient {
|
|
|
171
175
|
* createToken - Creates a token to authenticate this user. This function is used server side.
|
|
172
176
|
* The resulting token should be passed to the client side when the users registers or logs in.
|
|
173
177
|
*
|
|
174
|
-
* @param {string} userID The
|
|
178
|
+
* @param {string} userID The UserWithId ID
|
|
175
179
|
* @param {number} [exp] The expiration time for the token expressed in the number of seconds since the epoch
|
|
176
180
|
* @param call_cids for anonymous tokens you have to provide the call cids the use can join
|
|
177
181
|
*
|
|
@@ -24,7 +24,7 @@ export declare function buildWsFatalInsight(connection: StableWSConnection, even
|
|
|
24
24
|
auth_type: string;
|
|
25
25
|
token: string | undefined;
|
|
26
26
|
user_id: string | undefined;
|
|
27
|
-
user_details: import("./types").
|
|
27
|
+
user_details: import("./types").UserWithId | undefined;
|
|
28
28
|
device: string;
|
|
29
29
|
client_id: string | undefined;
|
|
30
30
|
ws_details: import("ws") | undefined;
|
|
@@ -44,7 +44,7 @@ export declare function buildWsSuccessAfterFailureInsight(connection: StableWSCo
|
|
|
44
44
|
auth_type: string;
|
|
45
45
|
token: string | undefined;
|
|
46
46
|
user_id: string | undefined;
|
|
47
|
-
user_details: import("./types").
|
|
47
|
+
user_details: import("./types").UserWithId | undefined;
|
|
48
48
|
device: string;
|
|
49
49
|
client_id: string | undefined;
|
|
50
50
|
ws_details: import("ws") | undefined;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Secret } from 'jsonwebtoken';
|
|
2
|
-
import type {
|
|
2
|
+
import type { TokenOrProvider, UserWithId } from './types';
|
|
3
3
|
/**
|
|
4
4
|
* TokenManager
|
|
5
5
|
*
|
|
@@ -11,7 +11,7 @@ export declare class TokenManager {
|
|
|
11
11
|
secret?: Secret;
|
|
12
12
|
token?: string;
|
|
13
13
|
tokenProvider?: TokenOrProvider;
|
|
14
|
-
user?:
|
|
14
|
+
user?: UserWithId;
|
|
15
15
|
/**
|
|
16
16
|
* Constructor
|
|
17
17
|
*
|
|
@@ -26,13 +26,13 @@ export declare class TokenManager {
|
|
|
26
26
|
* @param {UserResponse} user - the user object.
|
|
27
27
|
* @param {boolean} isAnonymous - whether the user is anonymous or not.
|
|
28
28
|
*/
|
|
29
|
-
setTokenOrProvider: (tokenOrProvider: TokenOrProvider, user:
|
|
29
|
+
setTokenOrProvider: (tokenOrProvider: TokenOrProvider, user: UserWithId, isAnonymous: boolean) => Promise<void>;
|
|
30
30
|
/**
|
|
31
31
|
* Resets the token manager.
|
|
32
32
|
* Useful for client disconnection or switching user.
|
|
33
33
|
*/
|
|
34
34
|
reset: () => void;
|
|
35
|
-
validateToken: (tokenOrProvider: TokenOrProvider, user:
|
|
35
|
+
validateToken: (tokenOrProvider: TokenOrProvider, user: UserWithId, isAnonymous: boolean) => void;
|
|
36
36
|
tokenReady: () => Promise<string> | null;
|
|
37
37
|
loadToken: () => Promise<string>;
|
|
38
38
|
getToken: () => string | undefined;
|
|
@@ -1,18 +1,23 @@
|
|
|
1
1
|
import { AxiosRequestConfig, AxiosResponse } from 'axios';
|
|
2
2
|
import { StableWSConnection } from './connection';
|
|
3
|
-
import { ConnectedEvent, VideoEvent } from '../../gen/coordinator';
|
|
3
|
+
import { ConnectedEvent, UserRequest, VideoEvent } from '../../gen/coordinator';
|
|
4
4
|
export type UR = Record<string, unknown>;
|
|
5
|
-
export type User = {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
}
|
|
5
|
+
export type User = (UserRequest & {
|
|
6
|
+
type?: 'authenticated';
|
|
7
|
+
}) | (UserRequest & {
|
|
8
|
+
type: 'guest';
|
|
9
|
+
}) | (Omit<UserRequest, 'id'> & {
|
|
10
|
+
id?: '!anon';
|
|
11
|
+
type: 'anonymous';
|
|
12
|
+
});
|
|
13
|
+
export type UserWithId = (UserRequest & {
|
|
14
|
+
type?: 'authenticated';
|
|
15
|
+
}) | (UserRequest & {
|
|
16
|
+
type: 'guest';
|
|
17
|
+
}) | (UserRequest & {
|
|
18
|
+
id: '!anon';
|
|
19
|
+
type: 'anonymous';
|
|
20
|
+
});
|
|
16
21
|
export type { OwnUserResponse } from '../../gen/coordinator';
|
|
17
22
|
export type ConnectAPIResponse = Promise<void | ConnectedEvent>;
|
|
18
23
|
export type LogLevel = 'info' | 'error' | 'warn';
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { BehaviorSubject, Observable } from 'rxjs';
|
|
2
2
|
import type { Patch } from './rxUtils';
|
|
3
3
|
import { Call } from '../Call';
|
|
4
|
-
import type {
|
|
4
|
+
import type { OwnUserResponse } from '../coordinator/connection/types';
|
|
5
5
|
export declare class StreamVideoWriteableStateStore {
|
|
6
6
|
/**
|
|
7
7
|
* A store keeping data of a successfully connected user over WS to the coordinator server.
|
|
8
8
|
*/
|
|
9
|
-
connectedUserSubject: BehaviorSubject<
|
|
9
|
+
connectedUserSubject: BehaviorSubject<OwnUserResponse | undefined>;
|
|
10
10
|
/**
|
|
11
11
|
* A list of {@link Call} objects created/tracked by this client.
|
|
12
12
|
*/
|
|
@@ -42,14 +42,14 @@ export declare class StreamVideoWriteableStateStore {
|
|
|
42
42
|
/**
|
|
43
43
|
* The currently connected user.
|
|
44
44
|
*/
|
|
45
|
-
get connectedUser():
|
|
45
|
+
get connectedUser(): OwnUserResponse | undefined;
|
|
46
46
|
/**
|
|
47
47
|
* Sets the currently connected user.
|
|
48
48
|
*
|
|
49
49
|
* @internal
|
|
50
50
|
* @param user the user to set as connected.
|
|
51
51
|
*/
|
|
52
|
-
setConnectedUser: (user: Patch<
|
|
52
|
+
setConnectedUser: (user: Patch<OwnUserResponse | undefined>) => OwnUserResponse | undefined;
|
|
53
53
|
/**
|
|
54
54
|
* A list of {@link Call} objects created/tracked by this client.
|
|
55
55
|
*/
|
|
@@ -98,7 +98,7 @@ export declare class StreamVideoReadOnlyStateStore {
|
|
|
98
98
|
/**
|
|
99
99
|
* Data describing a user successfully connected over WS to coordinator server.
|
|
100
100
|
*/
|
|
101
|
-
connectedUser$: Observable<
|
|
101
|
+
connectedUser$: Observable<OwnUserResponse | undefined>;
|
|
102
102
|
/**
|
|
103
103
|
* A list of {@link Call} objects created/tracked by this client.
|
|
104
104
|
*/
|
|
@@ -124,7 +124,7 @@ export declare class StreamVideoReadOnlyStateStore {
|
|
|
124
124
|
/**
|
|
125
125
|
* The current user connected over WS to the backend.
|
|
126
126
|
*/
|
|
127
|
-
get connectedUser():
|
|
127
|
+
get connectedUser(): OwnUserResponse | undefined;
|
|
128
128
|
/**
|
|
129
129
|
* A list of {@link Call} objects created/tracked by this client.
|
|
130
130
|
*/
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@stream-io/video-client",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.11",
|
|
4
4
|
"packageManager": "yarn@3.2.4",
|
|
5
5
|
"main": "dist/index.cjs.js",
|
|
6
6
|
"module": "dist/index.es.js",
|
|
@@ -55,11 +55,11 @@
|
|
|
55
55
|
"prettier": "^2.8.4",
|
|
56
56
|
"replace-in-file": "^6.3.5",
|
|
57
57
|
"rimraf": "^3.0.2",
|
|
58
|
-
"rollup": "^3.
|
|
58
|
+
"rollup": "^3.25.1",
|
|
59
59
|
"typedoc": "^0.24.7",
|
|
60
60
|
"typedoc-plugin-markdown": "^3.15.3",
|
|
61
61
|
"typescript": "^4.9.5",
|
|
62
|
-
"vite": "^4.3.
|
|
62
|
+
"vite": "^4.3.9",
|
|
63
63
|
"vitest": "^0.30.1",
|
|
64
64
|
"vitest-mock-extended": "^1.1.3"
|
|
65
65
|
}
|
package/src/Call.ts
CHANGED
|
@@ -152,14 +152,14 @@ export class Call {
|
|
|
152
152
|
watching: boolean;
|
|
153
153
|
|
|
154
154
|
/**
|
|
155
|
-
*
|
|
155
|
+
* Flag telling whether this call is a "ringing" call.
|
|
156
156
|
*/
|
|
157
|
-
readonly
|
|
157
|
+
private readonly ringingSubject: Subject<boolean>;
|
|
158
158
|
|
|
159
159
|
/**
|
|
160
|
-
*
|
|
160
|
+
* The permissions context of this call.
|
|
161
161
|
*/
|
|
162
|
-
|
|
162
|
+
readonly permissionsContext = new PermissionsContext();
|
|
163
163
|
|
|
164
164
|
/**
|
|
165
165
|
* The event dispatcher instance dedicated to this Call instance.
|
package/src/StreamVideoClient.ts
CHANGED
|
@@ -27,6 +27,7 @@ import type {
|
|
|
27
27
|
StreamClientOptions,
|
|
28
28
|
TokenOrProvider,
|
|
29
29
|
User,
|
|
30
|
+
UserWithId,
|
|
30
31
|
} from './coordinator/connection/types';
|
|
31
32
|
|
|
32
33
|
/**
|
|
@@ -69,13 +70,25 @@ export class StreamVideoClient {
|
|
|
69
70
|
* @param user the user to connect.
|
|
70
71
|
* @param tokenOrProvider a token or a function that returns a token.
|
|
71
72
|
*/
|
|
72
|
-
|
|
73
|
+
async connectUser(
|
|
74
|
+
user: User,
|
|
75
|
+
token: TokenOrProvider,
|
|
76
|
+
): Promise<void | ConnectedEvent> {
|
|
77
|
+
if (user.type === 'anonymous') {
|
|
78
|
+
user.id = '!anon';
|
|
79
|
+
return this.connectAnonymousUser(user as UserWithId, token);
|
|
80
|
+
}
|
|
81
|
+
if (user.type === 'guest') {
|
|
82
|
+
const response = await this.createGuestUser({
|
|
83
|
+
user: {
|
|
84
|
+
...user,
|
|
85
|
+
role: 'guest',
|
|
86
|
+
},
|
|
87
|
+
});
|
|
88
|
+
return this.connectUser(response.user, response.access_token);
|
|
89
|
+
}
|
|
73
90
|
const connectUser = () => {
|
|
74
|
-
return this.streamClient.connectUser(
|
|
75
|
-
// @ts-expect-error
|
|
76
|
-
user,
|
|
77
|
-
tokenOrProvider,
|
|
78
|
-
);
|
|
91
|
+
return this.streamClient.connectUser(user, token);
|
|
79
92
|
};
|
|
80
93
|
this.connectionPromise = this.disconnectionPromise
|
|
81
94
|
? this.disconnectionPromise.then(() => connectUser())
|
|
@@ -83,7 +96,10 @@ export class StreamVideoClient {
|
|
|
83
96
|
|
|
84
97
|
this.connectionPromise?.finally(() => (this.connectionPromise = undefined));
|
|
85
98
|
const connectUserResponse = await this.connectionPromise;
|
|
86
|
-
|
|
99
|
+
// connectUserResponse will be void if connectUser called twice for the same user
|
|
100
|
+
if (connectUserResponse?.me) {
|
|
101
|
+
this.writeableStateStore.setConnectedUser(connectUserResponse.me);
|
|
102
|
+
}
|
|
87
103
|
|
|
88
104
|
this.eventHandlersToUnregister.push(
|
|
89
105
|
this.on('connection.changed', (e) => {
|
|
@@ -162,27 +178,7 @@ export class StreamVideoClient {
|
|
|
162
178
|
);
|
|
163
179
|
|
|
164
180
|
return connectUserResponse;
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
/**
|
|
168
|
-
* Connects the given anonymous user to the client.
|
|
169
|
-
*
|
|
170
|
-
* @param user the user to connect.
|
|
171
|
-
* @param tokenOrProvider a token or a function that returns a token.
|
|
172
|
-
*/
|
|
173
|
-
connectAnonymousUser = async (
|
|
174
|
-
user: User,
|
|
175
|
-
tokenOrProvider: TokenOrProvider,
|
|
176
|
-
) => {
|
|
177
|
-
const connectAnonymousUser = () =>
|
|
178
|
-
// @ts-expect-error
|
|
179
|
-
this.streamClient.connectAnonymousUser(user, tokenOrProvider);
|
|
180
|
-
this.connectionPromise = this.disconnectionPromise
|
|
181
|
-
? this.disconnectionPromise.then(() => connectAnonymousUser())
|
|
182
|
-
: connectAnonymousUser();
|
|
183
|
-
this.connectionPromise.finally(() => (this.connectionPromise = undefined));
|
|
184
|
-
return this.connectionPromise;
|
|
185
|
-
};
|
|
181
|
+
}
|
|
186
182
|
|
|
187
183
|
/**
|
|
188
184
|
* Disconnects the currently connected user from the client.
|
|
@@ -250,10 +246,10 @@ export class StreamVideoClient {
|
|
|
250
246
|
* @param data the data for the guest user.
|
|
251
247
|
*/
|
|
252
248
|
createGuestUser = async (data: CreateGuestRequest) => {
|
|
253
|
-
return this.streamClient.
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
);
|
|
249
|
+
return this.streamClient.doAxiosRequest<
|
|
250
|
+
CreateGuestResponse,
|
|
251
|
+
CreateGuestRequest
|
|
252
|
+
>('post', '/guest', data, { publicEndpoint: true });
|
|
257
253
|
};
|
|
258
254
|
|
|
259
255
|
/**
|
|
@@ -411,4 +407,23 @@ export class StreamVideoClient {
|
|
|
411
407
|
) {
|
|
412
408
|
return this.streamClient.createToken(userID, exp, iat, call_cids);
|
|
413
409
|
}
|
|
410
|
+
|
|
411
|
+
/**
|
|
412
|
+
* Connects the given anonymous user to the client.
|
|
413
|
+
*
|
|
414
|
+
* @param user the user to connect.
|
|
415
|
+
* @param tokenOrProvider a token or a function that returns a token.
|
|
416
|
+
*/
|
|
417
|
+
private connectAnonymousUser = async (
|
|
418
|
+
user: UserWithId,
|
|
419
|
+
tokenOrProvider: TokenOrProvider,
|
|
420
|
+
) => {
|
|
421
|
+
const connectAnonymousUser = () =>
|
|
422
|
+
this.streamClient.connectAnonymousUser(user, tokenOrProvider);
|
|
423
|
+
this.connectionPromise = this.disconnectionPromise
|
|
424
|
+
? this.disconnectionPromise.then(() => connectAnonymousUser())
|
|
425
|
+
: connectAnonymousUser();
|
|
426
|
+
this.connectionPromise.finally(() => (this.connectionPromise = undefined));
|
|
427
|
+
return this.connectionPromise;
|
|
428
|
+
};
|
|
414
429
|
}
|
|
@@ -27,15 +27,15 @@ import {
|
|
|
27
27
|
ErrorFromResponse,
|
|
28
28
|
EventHandler,
|
|
29
29
|
Logger,
|
|
30
|
-
OwnUserResponse,
|
|
31
30
|
StreamClientOptions,
|
|
32
31
|
StreamVideoEvent,
|
|
33
32
|
TokenOrProvider,
|
|
33
|
+
UserWithId,
|
|
34
34
|
} from './types';
|
|
35
35
|
import { InsightMetrics, postInsights } from './insights';
|
|
36
36
|
|
|
37
37
|
export class StreamClient {
|
|
38
|
-
_user?:
|
|
38
|
+
_user?: UserWithId;
|
|
39
39
|
anonymous: boolean;
|
|
40
40
|
persistUserOnConnectionFailure?: boolean;
|
|
41
41
|
axiosInstance: AxiosInstance;
|
|
@@ -52,7 +52,7 @@ export class StreamClient {
|
|
|
52
52
|
secret?: string;
|
|
53
53
|
setUserPromise: ConnectAPIResponse | null;
|
|
54
54
|
tokenManager: TokenManager;
|
|
55
|
-
user?:
|
|
55
|
+
user?: UserWithId;
|
|
56
56
|
userAgent?: string;
|
|
57
57
|
userID?: string;
|
|
58
58
|
wsBaseURL?: string;
|
|
@@ -183,13 +183,13 @@ export class StreamClient {
|
|
|
183
183
|
/**
|
|
184
184
|
* connectUser - Set the current user and open a WebSocket connection
|
|
185
185
|
*
|
|
186
|
-
* @param
|
|
186
|
+
* @param user Data about this user. IE {name: "john"}
|
|
187
187
|
* @param {TokenOrProvider} userTokenOrProvider Token or provider
|
|
188
188
|
*
|
|
189
189
|
* @return {ConnectAPIResponse} Returns a promise that resolves when the connection is setup
|
|
190
190
|
*/
|
|
191
191
|
connectUser = async (
|
|
192
|
-
user:
|
|
192
|
+
user: UserWithId,
|
|
193
193
|
userTokenOrProvider: TokenOrProvider,
|
|
194
194
|
) => {
|
|
195
195
|
if (!user.id) {
|
|
@@ -253,7 +253,7 @@ export class StreamClient {
|
|
|
253
253
|
};
|
|
254
254
|
|
|
255
255
|
_setToken = (
|
|
256
|
-
user:
|
|
256
|
+
user: UserWithId,
|
|
257
257
|
userTokenOrProvider: TokenOrProvider,
|
|
258
258
|
isAnonymous: boolean,
|
|
259
259
|
) =>
|
|
@@ -263,7 +263,7 @@ export class StreamClient {
|
|
|
263
263
|
isAnonymous,
|
|
264
264
|
);
|
|
265
265
|
|
|
266
|
-
_setUser(user:
|
|
266
|
+
_setUser(user: UserWithId) {
|
|
267
267
|
/**
|
|
268
268
|
* This one is used by the frontend. This is a copy of the current user object stored on backend.
|
|
269
269
|
* It contains reserved properties and own user properties which are not present in `this._user`.
|
|
@@ -306,7 +306,7 @@ export class StreamClient {
|
|
|
306
306
|
openConnection = async () => {
|
|
307
307
|
if (!this.userID) {
|
|
308
308
|
throw Error(
|
|
309
|
-
'
|
|
309
|
+
'UserWithId is not set on client, use client.connectUser or client.connectAnonymousUser instead',
|
|
310
310
|
);
|
|
311
311
|
}
|
|
312
312
|
|
|
@@ -382,7 +382,7 @@ export class StreamClient {
|
|
|
382
382
|
* connectAnonymousUser - Set an anonymous user and open a WebSocket connection
|
|
383
383
|
*/
|
|
384
384
|
connectAnonymousUser = async (
|
|
385
|
-
user:
|
|
385
|
+
user: UserWithId,
|
|
386
386
|
tokenOrProvider: TokenOrProvider,
|
|
387
387
|
) => {
|
|
388
388
|
this.anonymous = true;
|
|
@@ -493,9 +493,11 @@ export class StreamClient {
|
|
|
493
493
|
data?: D,
|
|
494
494
|
options: AxiosRequestConfig & {
|
|
495
495
|
config?: AxiosRequestConfig & { maxBodyLength?: number };
|
|
496
|
-
} = {},
|
|
496
|
+
} & { publicEndpoint?: boolean } = {},
|
|
497
497
|
): Promise<T> => {
|
|
498
|
-
|
|
498
|
+
if (!options.publicEndpoint || this.user) {
|
|
499
|
+
await this.tokenManager.tokenReady();
|
|
500
|
+
}
|
|
499
501
|
const requestConfig = this._enrichAxiosOptions(options);
|
|
500
502
|
try {
|
|
501
503
|
let response: AxiosResponse<T>;
|
|
@@ -739,13 +741,16 @@ export class StreamClient {
|
|
|
739
741
|
_isUsingServerAuth = () => !!this.secret;
|
|
740
742
|
|
|
741
743
|
_enrichAxiosOptions(
|
|
742
|
-
options: AxiosRequestConfig & { config?: AxiosRequestConfig }
|
|
744
|
+
options: AxiosRequestConfig & { config?: AxiosRequestConfig } & {
|
|
745
|
+
publicEndpoint?: boolean;
|
|
746
|
+
} = {
|
|
743
747
|
params: {},
|
|
744
748
|
headers: {},
|
|
745
749
|
config: {},
|
|
746
750
|
},
|
|
747
751
|
): AxiosRequestConfig {
|
|
748
|
-
const token =
|
|
752
|
+
const token =
|
|
753
|
+
options.publicEndpoint && !this.user ? undefined : this._getToken();
|
|
749
754
|
const authorization = token ? { Authorization: token } : undefined;
|
|
750
755
|
let signal: AbortSignal | null = null;
|
|
751
756
|
if (this.nextRequestAbortController !== null) {
|
|
@@ -769,7 +774,10 @@ export class StreamClient {
|
|
|
769
774
|
},
|
|
770
775
|
headers: {
|
|
771
776
|
...authorization,
|
|
772
|
-
'stream-auth-type':
|
|
777
|
+
'stream-auth-type':
|
|
778
|
+
options.publicEndpoint && !this.user
|
|
779
|
+
? 'anonymous'
|
|
780
|
+
: this.getAuthType(),
|
|
773
781
|
'X-Stream-Client': this.getUserAgent(),
|
|
774
782
|
...options.headers,
|
|
775
783
|
},
|
|
@@ -809,7 +817,7 @@ export class StreamClient {
|
|
|
809
817
|
* createToken - Creates a token to authenticate this user. This function is used server side.
|
|
810
818
|
* The resulting token should be passed to the client side when the users registers or logs in.
|
|
811
819
|
*
|
|
812
|
-
* @param {string} userID The
|
|
820
|
+
* @param {string} userID The UserWithId ID
|
|
813
821
|
* @param {number} [exp] The expiration time for the token expressed in the number of seconds since the epoch
|
|
814
822
|
* @param call_cids for anonymous tokens you have to provide the call cids the use can join
|
|
815
823
|
*
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Secret } from 'jsonwebtoken';
|
|
2
2
|
import { JWTServerToken, JWTUserToken, UserFromToken } from './signing';
|
|
3
3
|
import { isFunction } from './utils';
|
|
4
|
-
import type {
|
|
4
|
+
import type { TokenOrProvider, UserWithId } from './types';
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* TokenManager
|
|
@@ -14,7 +14,7 @@ export class TokenManager {
|
|
|
14
14
|
secret?: Secret;
|
|
15
15
|
token?: string;
|
|
16
16
|
tokenProvider?: TokenOrProvider;
|
|
17
|
-
user?:
|
|
17
|
+
user?: UserWithId;
|
|
18
18
|
/**
|
|
19
19
|
* Constructor
|
|
20
20
|
*
|
|
@@ -43,7 +43,7 @@ export class TokenManager {
|
|
|
43
43
|
*/
|
|
44
44
|
setTokenOrProvider = async (
|
|
45
45
|
tokenOrProvider: TokenOrProvider,
|
|
46
|
-
user:
|
|
46
|
+
user: UserWithId,
|
|
47
47
|
isAnonymous: boolean,
|
|
48
48
|
) => {
|
|
49
49
|
this.validateToken(tokenOrProvider, user, isAnonymous);
|
|
@@ -80,7 +80,7 @@ export class TokenManager {
|
|
|
80
80
|
// Validates the user token.
|
|
81
81
|
validateToken = (
|
|
82
82
|
tokenOrProvider: TokenOrProvider,
|
|
83
|
-
user:
|
|
83
|
+
user: UserWithId,
|
|
84
84
|
isAnonymous: boolean,
|
|
85
85
|
) => {
|
|
86
86
|
// allow empty token for anon user
|
|
@@ -88,7 +88,7 @@ export class TokenManager {
|
|
|
88
88
|
|
|
89
89
|
// Don't allow empty token for non-server side client.
|
|
90
90
|
if (!this.secret && !tokenOrProvider) {
|
|
91
|
-
throw new Error('
|
|
91
|
+
throw new Error('UserWithId token can not be empty');
|
|
92
92
|
}
|
|
93
93
|
|
|
94
94
|
if (
|
|
@@ -1,18 +1,24 @@
|
|
|
1
1
|
import { AxiosRequestConfig, AxiosResponse } from 'axios';
|
|
2
2
|
import { StableWSConnection } from './connection';
|
|
3
|
-
import { ConnectedEvent, VideoEvent } from '../../gen/coordinator';
|
|
3
|
+
import { ConnectedEvent, UserRequest, VideoEvent } from '../../gen/coordinator';
|
|
4
4
|
|
|
5
5
|
export type UR = Record<string, unknown>;
|
|
6
6
|
|
|
7
|
-
export type User =
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
7
|
+
export type User =
|
|
8
|
+
| (UserRequest & { type?: 'authenticated' })
|
|
9
|
+
| (UserRequest & { type: 'guest' })
|
|
10
|
+
| (Omit<UserRequest, 'id'> & {
|
|
11
|
+
id?: '!anon';
|
|
12
|
+
type: 'anonymous';
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
export type UserWithId =
|
|
16
|
+
| (UserRequest & { type?: 'authenticated' })
|
|
17
|
+
| (UserRequest & { type: 'guest' })
|
|
18
|
+
| (UserRequest & {
|
|
19
|
+
id: '!anon';
|
|
20
|
+
type: 'anonymous';
|
|
21
|
+
});
|
|
16
22
|
|
|
17
23
|
export type { OwnUserResponse } from '../../gen/coordinator';
|
|
18
24
|
|
|
@@ -282,6 +282,12 @@ const fakeCall = ({ ring = true, currentUserId = 'test-user-id' } = {}) => {
|
|
|
282
282
|
const store = new StreamVideoWriteableStateStore();
|
|
283
283
|
store.setConnectedUser({
|
|
284
284
|
id: currentUserId,
|
|
285
|
+
created_at: '',
|
|
286
|
+
updated_at: '',
|
|
287
|
+
role: '',
|
|
288
|
+
custom: {},
|
|
289
|
+
teams: [],
|
|
290
|
+
devices: [],
|
|
285
291
|
});
|
|
286
292
|
const client = new StreamClient('api-key');
|
|
287
293
|
return new Call({
|