livekit-server-sdk 2.3.0 → 2.5.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.
Files changed (66) hide show
  1. package/README.md +80 -95
  2. package/dist/AccessToken.d.ts +15 -3
  3. package/dist/AccessToken.d.ts.map +1 -0
  4. package/dist/AccessToken.js +32 -3
  5. package/dist/AccessToken.js.map +1 -1
  6. package/dist/EgressClient.d.ts +1 -0
  7. package/dist/EgressClient.d.ts.map +1 -0
  8. package/dist/EgressClient.js +5 -2
  9. package/dist/EgressClient.js.map +1 -1
  10. package/dist/IngressClient.d.ts +1 -0
  11. package/dist/IngressClient.d.ts.map +1 -0
  12. package/dist/IngressClient.js +3 -0
  13. package/dist/IngressClient.js.map +1 -1
  14. package/dist/RoomServiceClient.d.ts +4 -2
  15. package/dist/RoomServiceClient.d.ts.map +1 -0
  16. package/dist/RoomServiceClient.js.map +1 -1
  17. package/dist/ServiceBase.d.ts +3 -2
  18. package/dist/ServiceBase.d.ts.map +1 -0
  19. package/dist/ServiceBase.js +7 -1
  20. package/dist/ServiceBase.js.map +1 -1
  21. package/dist/SipClient.d.ts +43 -1
  22. package/dist/SipClient.d.ts.map +1 -0
  23. package/dist/SipClient.js +111 -11
  24. package/dist/SipClient.js.map +1 -1
  25. package/dist/TwirpRPC.d.ts +1 -0
  26. package/dist/TwirpRPC.d.ts.map +1 -0
  27. package/dist/TwirpRPC.js.map +1 -1
  28. package/dist/WebhookReceiver.d.ts +2 -1
  29. package/dist/WebhookReceiver.d.ts.map +1 -0
  30. package/dist/WebhookReceiver.js.map +1 -1
  31. package/dist/grants.d.ts +12 -2
  32. package/dist/grants.d.ts.map +1 -0
  33. package/dist/grants.js +3 -0
  34. package/dist/grants.js.map +1 -1
  35. package/dist/index.d.ts +1 -0
  36. package/dist/index.d.ts.map +1 -0
  37. package/dist/index.js +3 -0
  38. package/dist/index.js.map +1 -1
  39. package/package.json +7 -8
  40. package/src/AccessToken.test.ts +100 -0
  41. package/src/AccessToken.ts +184 -0
  42. package/src/EgressClient.ts +617 -0
  43. package/src/IngressClient.ts +257 -0
  44. package/src/RoomServiceClient.ts +359 -0
  45. package/src/ServiceBase.ts +38 -0
  46. package/src/SipClient.ts +427 -0
  47. package/src/TwirpRPC.ts +54 -0
  48. package/src/WebhookReceiver.test.ts +44 -0
  49. package/src/WebhookReceiver.ts +85 -0
  50. package/src/grants.test.ts +30 -0
  51. package/src/grants.ts +107 -0
  52. package/src/index.ts +53 -0
  53. package/.changeset/README.md +0 -8
  54. package/.changeset/config.json +0 -11
  55. package/.eslintrc.cjs +0 -17
  56. package/.github/banner_dark.png +0 -0
  57. package/.github/banner_light.png +0 -0
  58. package/.github/workflows/release.yaml +0 -46
  59. package/.github/workflows/test.yaml +0 -46
  60. package/.gitmodules +0 -3
  61. package/.prettierignore +0 -8
  62. package/CHANGELOG.md +0 -87
  63. package/NOTICE +0 -13
  64. package/renovate.json +0 -18
  65. package/tsconfig.eslint.json +0 -5
  66. package/vite.config.js +0 -8
@@ -0,0 +1,257 @@
1
+ // SPDX-FileCopyrightText: 2024 LiveKit, Inc.
2
+ //
3
+ // SPDX-License-Identifier: Apache-2.0
4
+ import {
5
+ CreateIngressRequest,
6
+ DeleteIngressRequest,
7
+ IngressAudioOptions,
8
+ IngressInfo,
9
+ IngressInput,
10
+ IngressVideoOptions,
11
+ ListIngressRequest,
12
+ ListIngressResponse,
13
+ UpdateIngressRequest,
14
+ } from '@livekit/protocol';
15
+ import ServiceBase from './ServiceBase.js';
16
+ import { Rpc, TwirpRpc, livekitPackage } from './TwirpRPC.js';
17
+
18
+ const svc = 'Ingress';
19
+
20
+ export interface CreateIngressOptions {
21
+ /**
22
+ * ingress name. optional
23
+ */
24
+ name?: string;
25
+ /**
26
+ * name of the room to send media to. optional
27
+ */
28
+ roomName?: string;
29
+ /**
30
+ * unique identity of the participant. optional
31
+ */
32
+ participantIdentity?: string;
33
+ /**
34
+ * participant display name
35
+ */
36
+ participantName?: string;
37
+ /**
38
+ * metadata to attach to the participant
39
+ */
40
+ participantMetadata?: string;
41
+ /**
42
+ * @deprecated use `enableTranscoding` instead.
43
+ * whether to skip transcoding and forward the input media directly. Only supported by WHIP
44
+ */
45
+ bypassTranscoding?: boolean;
46
+ /**
47
+ * whether to enable transcoding or forward the input media directly.
48
+ * Transcoding is required for all input types except WHIP. For WHIP, the default is to not transcode.
49
+ */
50
+ enableTranscoding?: boolean | undefined;
51
+ /**
52
+ * url of the media to pull for ingresses of type URL
53
+ */
54
+ url?: string;
55
+ /**
56
+ * custom audio encoding parameters. optional
57
+ */
58
+ audio?: IngressAudioOptions;
59
+ /**
60
+ * custom video encoding parameters. optional
61
+ */
62
+ video?: IngressVideoOptions;
63
+ }
64
+
65
+ export interface UpdateIngressOptions {
66
+ /**
67
+ * ingress name. optional
68
+ */
69
+ name: string;
70
+ /**
71
+ * name of the room to send media to. optional
72
+ */
73
+ roomName?: string;
74
+ /**
75
+ * unique identity of the participant. optional
76
+ */
77
+ participantIdentity?: string;
78
+ /**
79
+ * participant display name
80
+ */
81
+ participantName?: string;
82
+ /**
83
+ * metadata to attach to the participant
84
+ */
85
+ participantMetadata?: string;
86
+ /**
87
+ * @deprecated use `enableTranscoding` instead
88
+ * whether to skip transcoding and forward the input media directly. Only supported by WHIP
89
+ */
90
+ bypassTranscoding?: boolean | undefined;
91
+ /**
92
+ * whether to enable transcoding or forward the input media directly.
93
+ * Transcoding is required for all input types except WHIP. For WHIP, the default is to not transcode.
94
+ */
95
+ enableTranscoding?: boolean | undefined;
96
+ /**
97
+ * custom audio encoding parameters. optional
98
+ */
99
+ audio?: IngressAudioOptions;
100
+ /**
101
+ * custom video encoding parameters. optional
102
+ */
103
+ video?: IngressVideoOptions;
104
+ }
105
+
106
+ export interface ListIngressOptions {
107
+ /**
108
+ * list ingress for one room only
109
+ */
110
+ roomName?: string;
111
+
112
+ /**
113
+ * list ingress by ID
114
+ */
115
+ ingressId?: string;
116
+ }
117
+
118
+ /**
119
+ * Client to access Ingress APIs
120
+ */
121
+ export class IngressClient extends ServiceBase {
122
+ private readonly rpc: Rpc;
123
+
124
+ /**
125
+ * @param host hostname including protocol. i.e. 'https://cluster.livekit.io'
126
+ * @param apiKey API Key, can be set in env var LIVEKIT_API_KEY
127
+ * @param secret API Secret, can be set in env var LIVEKIT_API_SECRET
128
+ */
129
+ constructor(host: string, apiKey?: string, secret?: string) {
130
+ super(apiKey, secret);
131
+ this.rpc = new TwirpRpc(host, livekitPackage);
132
+ }
133
+
134
+ /**
135
+ * @param inputType protocol for the ingress
136
+ * @param opts CreateIngressOptions
137
+ */
138
+ async createIngress(inputType: IngressInput, opts?: CreateIngressOptions): Promise<IngressInfo> {
139
+ let name: string = '';
140
+ let roomName: string = '';
141
+ let participantName: string = '';
142
+ let participantIdentity: string = '';
143
+ let participantMetadata: string | undefined;
144
+ let bypassTranscoding: boolean = false;
145
+ let enableTranscoding: boolean | undefined;
146
+ let url: string = '';
147
+ let audio: IngressAudioOptions | undefined;
148
+ let video: IngressVideoOptions | undefined;
149
+
150
+ if (opts !== undefined) {
151
+ name = opts.name || '';
152
+ roomName = opts.roomName || '';
153
+ participantName = opts.participantName || '';
154
+ participantIdentity = opts.participantIdentity || '';
155
+ bypassTranscoding = opts.bypassTranscoding || false;
156
+ enableTranscoding = opts.enableTranscoding;
157
+ url = opts.url || '';
158
+ audio = opts.audio;
159
+ video = opts.video;
160
+ participantMetadata = opts.participantMetadata;
161
+ }
162
+
163
+ const req = new CreateIngressRequest({
164
+ inputType,
165
+ name,
166
+ roomName,
167
+ participantIdentity,
168
+ participantMetadata,
169
+ participantName,
170
+ bypassTranscoding,
171
+ enableTranscoding,
172
+ url,
173
+ audio,
174
+ video,
175
+ }).toJson();
176
+
177
+ const data = await this.rpc.request(
178
+ svc,
179
+ 'CreateIngress',
180
+ req,
181
+ await this.authHeader({ ingressAdmin: true }),
182
+ );
183
+ return IngressInfo.fromJson(data, { ignoreUnknownFields: true });
184
+ }
185
+
186
+ /**
187
+ * @param ingressId ID of the ingress to update
188
+ * @param opts UpdateIngressOptions
189
+ */
190
+ async updateIngress(ingressId: string, opts: UpdateIngressOptions): Promise<IngressInfo> {
191
+ const name: string = opts.name || '';
192
+ const roomName: string = opts.roomName || '';
193
+ const participantName: string = opts.participantName || '';
194
+ const participantIdentity: string = opts.participantIdentity || '';
195
+ const { participantMetadata } = opts;
196
+ const { audio, video, bypassTranscoding, enableTranscoding } = opts;
197
+
198
+ const req = new UpdateIngressRequest({
199
+ ingressId,
200
+ name,
201
+ roomName,
202
+ participantIdentity,
203
+ participantName,
204
+ participantMetadata,
205
+ bypassTranscoding,
206
+ enableTranscoding,
207
+ audio,
208
+ video,
209
+ }).toJson();
210
+
211
+ const data = await this.rpc.request(
212
+ svc,
213
+ 'UpdateIngress',
214
+ req,
215
+ await this.authHeader({ ingressAdmin: true }),
216
+ );
217
+ return IngressInfo.fromJson(data, { ignoreUnknownFields: true });
218
+ }
219
+
220
+ /**
221
+ * @deprecated use listIngress(opts) instead
222
+ * @param roomName list ingress for one room only
223
+ */
224
+ async listIngress(roomName?: string): Promise<Array<IngressInfo>>;
225
+ /**
226
+ * @param opts list options
227
+ */
228
+ async listIngress(opts?: ListIngressOptions): Promise<Array<IngressInfo>>;
229
+ async listIngress(arg?: string | ListIngressOptions): Promise<Array<IngressInfo>> {
230
+ let req: Partial<ListIngressRequest> = {};
231
+ if (typeof arg === 'string') {
232
+ req.roomName = arg;
233
+ } else if (arg) {
234
+ req = arg;
235
+ }
236
+ const data = await this.rpc.request(
237
+ svc,
238
+ 'ListIngress',
239
+ new ListIngressRequest(req).toJson(),
240
+ await this.authHeader({ ingressAdmin: true }),
241
+ );
242
+ return ListIngressResponse.fromJson(data, { ignoreUnknownFields: true }).items ?? [];
243
+ }
244
+
245
+ /**
246
+ * @param ingressId ingress to delete
247
+ */
248
+ async deleteIngress(ingressId: string): Promise<IngressInfo> {
249
+ const data = await this.rpc.request(
250
+ svc,
251
+ 'DeleteIngress',
252
+ new DeleteIngressRequest({ ingressId }).toJson(),
253
+ await this.authHeader({ ingressAdmin: true }),
254
+ );
255
+ return IngressInfo.fromJson(data, { ignoreUnknownFields: true });
256
+ }
257
+ }
@@ -0,0 +1,359 @@
1
+ // SPDX-FileCopyrightText: 2024 LiveKit, Inc.
2
+ //
3
+ // SPDX-License-Identifier: Apache-2.0
4
+ import type { DataPacket_Kind, RoomEgress, TrackInfo } from '@livekit/protocol';
5
+ import {
6
+ CreateRoomRequest,
7
+ DeleteRoomRequest,
8
+ ListParticipantsRequest,
9
+ ListParticipantsResponse,
10
+ ListRoomsRequest,
11
+ ListRoomsResponse,
12
+ MuteRoomTrackRequest,
13
+ MuteRoomTrackResponse,
14
+ ParticipantInfo,
15
+ ParticipantPermission,
16
+ Room,
17
+ RoomParticipantIdentity,
18
+ SendDataRequest,
19
+ UpdateParticipantRequest,
20
+ UpdateRoomMetadataRequest,
21
+ UpdateSubscriptionsRequest,
22
+ } from '@livekit/protocol';
23
+ import ServiceBase from './ServiceBase.js';
24
+ import type { Rpc } from './TwirpRPC.js';
25
+ import { TwirpRpc, livekitPackage } from './TwirpRPC.js';
26
+
27
+ /**
28
+ * Options for when creating a room
29
+ */
30
+ export interface CreateOptions {
31
+ /**
32
+ * name of the room. required
33
+ */
34
+ name: string;
35
+
36
+ /**
37
+ * number of seconds to keep the room open before any participant joins
38
+ */
39
+ emptyTimeout?: number;
40
+
41
+ /**
42
+ * number of seconds to keep the room open after the last participant leaves
43
+ * this option is helpful to give a grace period for participants to re-join
44
+ */
45
+ departureTimeout?: number;
46
+
47
+ /**
48
+ * limit to the number of participants in a room at a time
49
+ */
50
+ maxParticipants?: number;
51
+
52
+ /**
53
+ * initial room metadata
54
+ */
55
+ metadata?: string;
56
+
57
+ /**
58
+ * add egress options
59
+ */
60
+ egress?: RoomEgress;
61
+
62
+ /**
63
+ * minimum playout delay in milliseconds
64
+ */
65
+ minPlayoutDelay?: number;
66
+
67
+ /**
68
+ * maximum playout delay in milliseconds
69
+ */
70
+ maxPlayoutDelay?: number;
71
+
72
+ /**
73
+ * improves A/V sync when min_playout_delay set to a value larger than 200ms.
74
+ * It will disables transceiver re-use -- this option is not recommended
75
+ * for rooms with frequent subscription changes
76
+ */
77
+ syncStreams?: boolean;
78
+
79
+ /**
80
+ * override the node room is allocated to, for debugging
81
+ * does not work with Cloud
82
+ */
83
+ nodeId?: string;
84
+ }
85
+
86
+ export type SendDataOptions = {
87
+ /** If set, only deliver to listed participant identities */
88
+ destinationIdentities?: string[];
89
+ destinationSids?: string[];
90
+ topic?: string;
91
+ };
92
+
93
+ const svc = 'RoomService';
94
+
95
+ /**
96
+ * Client to access Room APIs
97
+ */
98
+ export class RoomServiceClient extends ServiceBase {
99
+ private readonly rpc: Rpc;
100
+
101
+ /**
102
+ *
103
+ * @param host hostname including protocol. i.e. 'https://cluster.livekit.io'
104
+ * @param apiKey API Key, can be set in env var LIVEKIT_API_KEY
105
+ * @param secret API Secret, can be set in env var LIVEKIT_API_SECRET
106
+ */
107
+ constructor(host: string, apiKey?: string, secret?: string) {
108
+ super(apiKey, secret);
109
+ this.rpc = new TwirpRpc(host, livekitPackage);
110
+ }
111
+
112
+ /**
113
+ * Creates a new room. Explicit room creation is not required, since rooms will
114
+ * be automatically created when the first participant joins. This method can be
115
+ * used to customize room settings.
116
+ * @param options
117
+ */
118
+ async createRoom(options: CreateOptions): Promise<Room> {
119
+ const data = await this.rpc.request(
120
+ svc,
121
+ 'CreateRoom',
122
+ new CreateRoomRequest(options).toJson(),
123
+ await this.authHeader({ roomCreate: true }),
124
+ );
125
+ return Room.fromJson(data, { ignoreUnknownFields: true });
126
+ }
127
+
128
+ /**
129
+ * List active rooms
130
+ * @param names when undefined or empty, list all rooms.
131
+ * otherwise returns rooms with matching names
132
+ * @returns
133
+ */
134
+ async listRooms(names?: string[]): Promise<Room[]> {
135
+ const data = await this.rpc.request(
136
+ svc,
137
+ 'ListRooms',
138
+ new ListRoomsRequest({ names: names ?? [] }).toJson(),
139
+ await this.authHeader({ roomList: true }),
140
+ );
141
+ const res = ListRoomsResponse.fromJson(data, { ignoreUnknownFields: true });
142
+ return res.rooms ?? [];
143
+ }
144
+
145
+ async deleteRoom(room: string): Promise<void> {
146
+ await this.rpc.request(
147
+ svc,
148
+ 'DeleteRoom',
149
+ new DeleteRoomRequest({ room }).toJson(),
150
+ await this.authHeader({ roomCreate: true }),
151
+ );
152
+ }
153
+
154
+ /**
155
+ * Update metadata of a room
156
+ * @param room name of the room
157
+ * @param metadata the new metadata for the room
158
+ */
159
+ async updateRoomMetadata(room: string, metadata: string) {
160
+ const data = await this.rpc.request(
161
+ svc,
162
+ 'UpdateRoomMetadata',
163
+ new UpdateRoomMetadataRequest({ room, metadata }).toJson(),
164
+ await this.authHeader({ roomAdmin: true, room }),
165
+ );
166
+ return Room.fromJson(data, { ignoreUnknownFields: true });
167
+ }
168
+
169
+ /**
170
+ * List participants in a room
171
+ * @param room name of the room
172
+ */
173
+ async listParticipants(room: string): Promise<ParticipantInfo[]> {
174
+ const data = await this.rpc.request(
175
+ svc,
176
+ 'ListParticipants',
177
+ new ListParticipantsRequest({ room }).toJson(),
178
+ await this.authHeader({ roomAdmin: true, room }),
179
+ );
180
+ const res = ListParticipantsResponse.fromJson(data, { ignoreUnknownFields: true });
181
+ return res.participants ?? [];
182
+ }
183
+
184
+ /**
185
+ * Get information on a specific participant, including the tracks that participant
186
+ * has published
187
+ * @param room name of the room
188
+ * @param identity identity of the participant to return
189
+ */
190
+ async getParticipant(room: string, identity: string): Promise<ParticipantInfo> {
191
+ const data = await this.rpc.request(
192
+ svc,
193
+ 'GetParticipant',
194
+ new RoomParticipantIdentity({ room, identity }).toJson(),
195
+ await this.authHeader({ roomAdmin: true, room }),
196
+ );
197
+
198
+ return ParticipantInfo.fromJson(data, { ignoreUnknownFields: true });
199
+ }
200
+
201
+ /**
202
+ * Removes a participant in the room. This will disconnect the participant
203
+ * and will emit a Disconnected event for that participant.
204
+ * Even after being removed, the participant can still re-join the room.
205
+ * @param room
206
+ * @param identity
207
+ */
208
+ async removeParticipant(room: string, identity: string): Promise<void> {
209
+ await this.rpc.request(
210
+ svc,
211
+ 'RemoveParticipant',
212
+ new RoomParticipantIdentity({ room, identity }).toJson(),
213
+ await this.authHeader({ roomAdmin: true, room }),
214
+ );
215
+ }
216
+
217
+ /**
218
+ * Mutes a track that the participant has published.
219
+ * @param room
220
+ * @param identity
221
+ * @param trackSid sid of the track to be muted
222
+ * @param muted true to mute, false to unmute
223
+ */
224
+ async mutePublishedTrack(
225
+ room: string,
226
+ identity: string,
227
+ trackSid: string,
228
+ muted: boolean,
229
+ ): Promise<TrackInfo> {
230
+ const req = new MuteRoomTrackRequest({
231
+ room,
232
+ identity,
233
+ trackSid,
234
+ muted,
235
+ }).toJson();
236
+ const data = await this.rpc.request(
237
+ svc,
238
+ 'MutePublishedTrack',
239
+ req,
240
+ await this.authHeader({ roomAdmin: true, room }),
241
+ );
242
+ const res = MuteRoomTrackResponse.fromJson(data, { ignoreUnknownFields: true });
243
+ return res.track!;
244
+ }
245
+
246
+ /**
247
+ * Updates a participant's metadata or permissions
248
+ * @param room
249
+ * @param identity
250
+ * @param metadata optional, metadata to update
251
+ * @param permission optional, new permissions to assign to participant
252
+ * @param name optional, new name for participant
253
+ */
254
+ async updateParticipant(
255
+ room: string,
256
+ identity: string,
257
+ metadata?: string,
258
+ permission?: Partial<ParticipantPermission>,
259
+ name?: string,
260
+ ): Promise<ParticipantInfo> {
261
+ const req = new UpdateParticipantRequest({
262
+ room,
263
+ identity,
264
+ metadata: metadata || '',
265
+ name: name || '',
266
+ });
267
+ if (permission) {
268
+ req.permission = new ParticipantPermission(permission);
269
+ }
270
+ const data = await this.rpc.request(
271
+ svc,
272
+ 'UpdateParticipant',
273
+ req.toJson(),
274
+ await this.authHeader({ roomAdmin: true, room }),
275
+ );
276
+ return ParticipantInfo.fromJson(data, { ignoreUnknownFields: true });
277
+ }
278
+
279
+ /**
280
+ * Updates a participant's subscription to tracks
281
+ * @param room
282
+ * @param identity
283
+ * @param trackSids
284
+ * @param subscribe true to subscribe, false to unsubscribe
285
+ */
286
+ async updateSubscriptions(
287
+ room: string,
288
+ identity: string,
289
+ trackSids: string[],
290
+ subscribe: boolean,
291
+ ): Promise<void> {
292
+ const req = new UpdateSubscriptionsRequest({
293
+ room,
294
+ identity,
295
+ trackSids,
296
+ subscribe,
297
+ participantTracks: [],
298
+ }).toJson();
299
+ await this.rpc.request(
300
+ svc,
301
+ 'UpdateSubscriptions',
302
+ req,
303
+ await this.authHeader({ roomAdmin: true, room }),
304
+ );
305
+ }
306
+
307
+ /**
308
+ * Sends data message to participants in the room
309
+ * @param room
310
+ * @param data opaque payload to send
311
+ * @param kind delivery reliability
312
+ * @param options optionally specify a topic and destinationSids (when destinationSids is empty, message is sent to everyone)
313
+ */
314
+ async sendData(
315
+ room: string,
316
+ data: Uint8Array,
317
+ kind: DataPacket_Kind,
318
+ options: SendDataOptions,
319
+ ): Promise<void>;
320
+ /**
321
+ * Sends data message to participants in the room
322
+ * @deprecated use sendData(room, data, kind, options) instead
323
+ * @param room
324
+ * @param data opaque payload to send
325
+ * @param kind delivery reliability
326
+ * @param destinationSids optional. when empty, message is sent to everyone
327
+ */
328
+ async sendData(
329
+ room: string,
330
+ data: Uint8Array,
331
+ kind: DataPacket_Kind,
332
+ destinationSids?: string[],
333
+ ): Promise<void>;
334
+ async sendData(
335
+ room: string,
336
+ data: Uint8Array,
337
+ kind: DataPacket_Kind,
338
+ options: SendDataOptions | string[] = {},
339
+ ): Promise<void> {
340
+ const destinationSids = Array.isArray(options) ? options : options.destinationSids;
341
+ const topic = Array.isArray(options) ? undefined : options.topic;
342
+ const req = new SendDataRequest({
343
+ room,
344
+ data,
345
+ kind,
346
+ destinationSids: destinationSids ?? [],
347
+ topic,
348
+ });
349
+ if (!Array.isArray(options) && options.destinationIdentities) {
350
+ req.destinationIdentities = options.destinationIdentities;
351
+ }
352
+ await this.rpc.request(
353
+ svc,
354
+ 'SendData',
355
+ req.toJson(),
356
+ await this.authHeader({ roomAdmin: true, room }),
357
+ );
358
+ }
359
+ }
@@ -0,0 +1,38 @@
1
+ // SPDX-FileCopyrightText: 2024 LiveKit, Inc.
2
+ //
3
+ // SPDX-License-Identifier: Apache-2.0
4
+ import { AccessToken } from './AccessToken.js';
5
+ import { SIPGrant, VideoGrant } from './grants.js';
6
+
7
+ /**
8
+ * Utilities to handle authentication
9
+ */
10
+ export default class ServiceBase {
11
+ private readonly apiKey?: string;
12
+
13
+ private readonly secret?: string;
14
+
15
+ private readonly ttl: string;
16
+
17
+ /**
18
+ * @param apiKey API Key.
19
+ * @param secret API Secret.
20
+ * @param ttl token TTL
21
+ */
22
+ constructor(apiKey?: string, secret?: string, ttl?: string) {
23
+ this.apiKey = apiKey;
24
+ this.secret = secret;
25
+ this.ttl = ttl || '10m';
26
+ }
27
+
28
+ async authHeader(grant: VideoGrant, sip?: SIPGrant): Promise<any> {
29
+ const at = new AccessToken(this.apiKey, this.secret, { ttl: this.ttl });
30
+ at.addGrant(grant);
31
+ if (sip) {
32
+ at.addSIPGrant(sip);
33
+ }
34
+ return {
35
+ Authorization: `Bearer ${await at.toJwt()}`,
36
+ };
37
+ }
38
+ }