Skip to content

Commit 4b818c3

Browse files
committed
feat: convert TokenSource to be stateless again
1 parent 5d9a3f1 commit 4b818c3

File tree

2 files changed

+43
-42
lines changed

2 files changed

+43
-42
lines changed

packages/react/src/TokenSource.ts

Lines changed: 25 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -33,11 +33,10 @@ type RoomConfigurationPayload = NonNullable<ConstructorParameters<typeof RoomCon
3333

3434

3535

36-
export abstract class TokenSourceBase {
37-
abstract generate(): Promise<TokenSourceResponseObject>;
36+
export abstract class TokenSourceFixed {
37+
abstract getToken(): Promise<TokenSourceResponseObject>;
3838
}
3939

40-
export abstract class TokenSourceFixed extends TokenSourceBase {}
4140
export type TokenSourceOptions = {
4241
roomName?: string;
4342
participantName?: string;
@@ -48,11 +47,13 @@ export type TokenSourceOptions = {
4847
agentName?: string;
4948
};
5049

51-
export abstract class TokenSourceConfigurable extends TokenSourceBase {
52-
abstract setOptions(options: TokenSourceOptions): void;
53-
abstract clearOptions(): void;
50+
export abstract class TokenSourceConfigurable {
51+
abstract getToken(options: TokenSourceOptions): Promise<TokenSourceResponseObject>;
5452
}
5553

54+
export type TokenSource = TokenSourceFixed | TokenSourceConfigurable;
55+
56+
5657

5758

5859

@@ -131,33 +132,35 @@ export abstract class TokenSourceRefreshable extends TokenSourceConfigurable {
131132
return true;
132133
}
133134

134-
getJwtPayload() {
135+
protected shouldUseCachedValue(options: TokenSourceOptions) {
135136
if (!this.cachedResponse) {
136-
return null;
137+
return false;
137138
}
138-
return decodeTokenPayload(this.cachedResponse.participantToken);
139-
}
140-
141-
setOptions(options: TokenSourceOptions) {
142-
if (!this.isSameAsCachedOptions(options)) {
143-
this.cachedResponse = null;
139+
if (isResponseExpired(this.cachedResponse)) {
140+
return false;
144141
}
145-
this.options = options;
146-
}
142+
if (this.isSameAsCachedOptions(options)) {
143+
return false;
144+
}
145+
return true;
146+
}
147147

148-
clearOptions() {
149-
this.options = {};
150-
this.cachedResponse = null;
148+
getCachedResponseJwtPayload() {
149+
if (!this.cachedResponse) {
150+
return null;
151+
}
152+
return decodeTokenPayload(this.cachedResponse.participantToken);
151153
}
152154

153-
async getToken(): Promise<TokenSourceResponseObject> {
155+
async getToken(options: TokenSourceOptions): Promise<TokenSourceResponseObject> {
154156
const unlock = await this.fetchMutex.lock();
155157
try {
156-
if (this.cachedResponse && !isResponseExpired(this.cachedResponse)) {
158+
if (this.shouldUseCachedValue(options)) {
157159
return this.cachedResponse!.toJson() as TokenSourceResponseObject;
158160
}
161+
this.cachedOptions = options;
159162

160-
const tokenResponse = await this.update(this.options);
163+
const tokenResponse = await this.update(options);
161164
this.cachedResponse = tokenResponse;
162165
return tokenResponse;
163166
} finally {

packages/react/src/hooks/useSession.ts

Lines changed: 18 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { EventEmitter } from 'events';
44
import { useCallback, useEffect, useMemo, useState } from 'react';
55

66
import {
7-
TokenSourceBase,
7+
TokenSource,
88
TokenSourceConfigurable,
99
TokenSourceFixed,
1010
TokenSourceOptions,
@@ -52,7 +52,7 @@ type SessionStateCommon = {
5252
subtle: {
5353
emitter: TypedEventEmitter<SessionCallbacks>;
5454
room: Room;
55-
tokenSource: TokenSourceBase,
55+
tokenSource: TokenSource,
5656
agentConnectTimeoutMilliseconds?: number;
5757
};
5858
};
@@ -137,19 +137,6 @@ export function useSession(
137137

138138
const emitter = useMemo(() => new EventEmitter() as TypedEventEmitter<SessionCallbacks>, []);
139139

140-
// Flexible `TokenSource`s can have options injected
141-
useEffect(() => {
142-
const isConfigurable = tokenSource instanceof TokenSourceConfigurable;
143-
if (!isConfigurable) {
144-
return;
145-
}
146-
147-
tokenSource.setOptions(tokenSourceOptions);
148-
return () => {
149-
tokenSource.clearOptions();
150-
};
151-
}, [tokenSource, tokenSourceOptions]);
152-
153140
const generateDerivedConnectionStateValues = useCallback(<State extends UseSessionReturn["connectionState"]>(connectionState: State) => ({
154141
isConnected: (
155142
connectionState === ConnectionState.Connected ||
@@ -330,6 +317,15 @@ export function useSession(
330317
},
331318
}), [conversationState, emitter, room, tokenSource]));
332319

320+
const tokenSourceGetToken = useCallback(() => {
321+
const isConfigurable = tokenSource instanceof TokenSourceConfigurable;
322+
if (isConfigurable) {
323+
return tokenSource.getToken(tokenSourceOptions);
324+
} else {
325+
return tokenSource.getToken();
326+
}
327+
}, [tokenSource]);
328+
333329
const start = useCallback(async (connectOptions: SessionConnectOptions = {}) => {
334330
const {
335331
signal,
@@ -345,8 +341,8 @@ export function useSession(
345341

346342
await Promise.all([
347343
// FIXME: swap the below line in once the new `livekit-client` changes are published
348-
// room.connect(options.credentials),
349-
tokenSource.getToken().then(({ serverUrl, participantToken }) => (
344+
// room.connect(tokenSource),
345+
tokenSourceGetToken().then(({ serverUrl, participantToken }) => (
350346
room.connect(serverUrl, participantToken)
351347
)),
352348

@@ -360,16 +356,18 @@ export function useSession(
360356
await agent.waitUntilAvailable(signal);
361357

362358
signal?.removeEventListener('abort', onSignalAbort);
363-
}, [room, waitUntilDisconnected, tokenSource, waitUntilConnected, agent.waitUntilAvailable]);
359+
}, [room, waitUntilDisconnected, tokenSourceGetToken, waitUntilConnected, agent.waitUntilAvailable]);
364360

365361
const end = useCallback(async () => {
366362
await room.disconnect();
367363
}, [room]);
368364

369365
const prepareConnection = useCallback(async () => {
370-
const credentials = await tokenSource.getToken();
366+
const credentials = await tokenSourceGetToken();
367+
// FIXME: swap the below line in once the new `livekit-client` changes are published
368+
// room.prepareConnection(tokenSource),
371369
await room.prepareConnection(credentials.serverUrl, credentials.participantToken);
372-
}, [tokenSource, room]);
370+
}, [tokenSourceGetToken, room]);
373371
useEffect(() => {
374372
prepareConnection().catch(err => {
375373
// FIXME: figure out a better logging solution?

0 commit comments

Comments
 (0)