{"version":3,"sources":["../src/RoomServiceClient.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2024 LiveKit, Inc.\n//\n// SPDX-License-Identifier: Apache-2.0\nimport type { DataPacket_Kind, RoomAgentDispatch, RoomEgress, TrackInfo } from '@livekit/protocol';\nimport {\n  CreateRoomRequest,\n  DeleteRoomRequest,\n  ForwardParticipantRequest,\n  ListParticipantsRequest,\n  ListParticipantsResponse,\n  ListRoomsRequest,\n  ListRoomsResponse,\n  MoveParticipantRequest,\n  MuteRoomTrackRequest,\n  MuteRoomTrackResponse,\n  ParticipantInfo,\n  ParticipantPermission,\n  Room,\n  RoomParticipantIdentity,\n  SendDataRequest,\n  UpdateParticipantRequest,\n  UpdateRoomMetadataRequest,\n  UpdateSubscriptionsRequest,\n} from '@livekit/protocol';\nimport type { ClientOptions } from './ClientOptions.js';\nimport { ServiceBase } from './ServiceBase.js';\nimport type { Rpc } from './TwirpRPC.js';\nimport { TwirpRpc, livekitPackage } from './TwirpRPC.js';\nimport { getRandomBytes } from './crypto/uuid.js';\n\n/**\n * Options for when creating a room\n */\nexport interface CreateOptions {\n  /**\n   * name of the room. required\n   */\n  name: string;\n\n  /**\n   * number of seconds to keep the room open before any participant joins\n   */\n  emptyTimeout?: number;\n\n  /**\n   * number of seconds to keep the room open after the last participant leaves\n   * this option is helpful to give a grace period for participants to re-join\n   */\n  departureTimeout?: number;\n\n  /**\n   * limit to the number of participants in a room at a time\n   */\n  maxParticipants?: number;\n\n  /**\n   * initial room metadata\n   */\n  metadata?: string;\n\n  /**\n   * add egress options\n   */\n  egress?: RoomEgress;\n\n  /**\n   * minimum playout delay in milliseconds\n   */\n  minPlayoutDelay?: number;\n\n  /**\n   * maximum playout delay in milliseconds\n   */\n  maxPlayoutDelay?: number;\n\n  /**\n   * improves A/V sync when min_playout_delay set to a value larger than 200ms.\n   * It will disables transceiver re-use -- this option is not recommended\n   * for rooms with frequent subscription changes\n   */\n  syncStreams?: boolean;\n\n  /**\n   * agents that should be dispatched to this room\n   */\n  agents?: RoomAgentDispatch[];\n\n  /**\n   * override the node room is allocated to, for debugging\n   * does not work with Cloud\n   */\n  nodeId?: string;\n}\n\nexport type SendDataOptions = {\n  /** If set, only deliver to listed participant identities */\n  destinationIdentities?: string[];\n  destinationSids?: string[];\n  topic?: string;\n};\n\nexport type UpdateParticipantOptions = {\n  /** only attributes you'd want to update should be set, set value to empty string to remove it */\n  attributes?: { [key: string]: string };\n  metadata?: string;\n  /** permissions are updated atomically - all desired permissions would need to be set */\n  permission?: Partial<ParticipantPermission>;\n  name?: string;\n};\n\nconst svc = 'RoomService';\n\n/**\n * Client to access Room APIs\n */\nexport class RoomServiceClient extends ServiceBase {\n  private readonly rpc: Rpc;\n\n  /**\n   *\n   * @param host - hostname including protocol. i.e. 'https://<project>.livekit.cloud'\n   * @param apiKey - API Key, can be set in env var LIVEKIT_API_KEY\n   * @param secret - API Secret, can be set in env var LIVEKIT_API_SECRET\n   * @param options - client options\n   */\n  constructor(host: string, apiKey?: string, secret?: string, options?: ClientOptions) {\n    super(apiKey, secret);\n    const rpcOptions = options?.requestTimeout\n      ? { requestTimeout: options.requestTimeout }\n      : undefined;\n    this.rpc = new TwirpRpc(host, livekitPackage, rpcOptions);\n  }\n\n  /**\n   * Creates a new room. Explicit room creation is not required, since rooms will\n   * be automatically created when the first participant joins. This method can be\n   * used to customize room settings.\n   * @param options -\n   */\n  async createRoom(options: CreateOptions): Promise<Room> {\n    const data = await this.rpc.request(\n      svc,\n      'CreateRoom',\n      new CreateRoomRequest(options).toJson(),\n      await this.authHeader({ roomCreate: true }),\n    );\n    return Room.fromJson(data, { ignoreUnknownFields: true });\n  }\n\n  /**\n   * List active rooms\n   * @param names - when undefined or empty, list all rooms.\n   *                otherwise returns rooms with matching names\n   * @returns\n   */\n  async listRooms(names?: string[]): Promise<Room[]> {\n    const data = await this.rpc.request(\n      svc,\n      'ListRooms',\n      new ListRoomsRequest({ names: names ?? [] }).toJson(),\n      await this.authHeader({ roomList: true }),\n    );\n    const res = ListRoomsResponse.fromJson(data, { ignoreUnknownFields: true });\n    return res.rooms ?? [];\n  }\n\n  async deleteRoom(room: string): Promise<void> {\n    await this.rpc.request(\n      svc,\n      'DeleteRoom',\n      new DeleteRoomRequest({ room }).toJson(),\n      await this.authHeader({ roomCreate: true }),\n    );\n  }\n\n  /**\n   * Update metadata of a room\n   * @param room - name of the room\n   * @param metadata - the new metadata for the room\n   */\n  async updateRoomMetadata(room: string, metadata: string) {\n    const data = await this.rpc.request(\n      svc,\n      'UpdateRoomMetadata',\n      new UpdateRoomMetadataRequest({ room, metadata }).toJson(),\n      await this.authHeader({ roomAdmin: true, room }),\n    );\n    return Room.fromJson(data, { ignoreUnknownFields: true });\n  }\n\n  /**\n   * List participants in a room\n   * @param room - name of the room\n   */\n  async listParticipants(room: string): Promise<ParticipantInfo[]> {\n    const data = await this.rpc.request(\n      svc,\n      'ListParticipants',\n      new ListParticipantsRequest({ room }).toJson(),\n      await this.authHeader({ roomAdmin: true, room }),\n    );\n    const res = ListParticipantsResponse.fromJson(data, { ignoreUnknownFields: true });\n    return res.participants ?? [];\n  }\n\n  /**\n   * Get information on a specific participant, including the tracks that participant\n   * has published\n   * @param room - name of the room\n   * @param identity - identity of the participant to return\n   */\n  async getParticipant(room: string, identity: string): Promise<ParticipantInfo> {\n    const data = await this.rpc.request(\n      svc,\n      'GetParticipant',\n      new RoomParticipantIdentity({ room, identity }).toJson(),\n      await this.authHeader({ roomAdmin: true, room }),\n    );\n\n    return ParticipantInfo.fromJson(data, { ignoreUnknownFields: true });\n  }\n\n  /**\n   * Removes a participant in the room. This will disconnect the participant\n   * and will emit a Disconnected event for that participant.\n   * Even after being removed, the participant can still re-join the room.\n   * @param room -\n   * @param identity -\n   */\n  async removeParticipant(room: string, identity: string): Promise<void> {\n    await this.rpc.request(\n      svc,\n      'RemoveParticipant',\n      new RoomParticipantIdentity({ room, identity }).toJson(),\n      await this.authHeader({ roomAdmin: true, room }),\n    );\n  }\n\n  /**\n   * Forwards a participant's track to another room. This will create a\n   * participant to join the destination room that has same information\n   * with the source participant except the kind to be `Forwarded`. All\n   * changes to the source participant will be reflected to the forwarded\n   * participant. When the source participant disconnects or the\n   * `RemoveParticipant` method is called in the destination room, the\n   * forwarding will be stopped.\n   * @param room -\n   * @param identity -\n   * @param destinationRoom - the room to forward the participant to\n   */\n  async forwardParticipant(room: string, identity: string, destinationRoom: string): Promise<void> {\n    await this.rpc.request(\n      svc,\n      'ForwardParticipant',\n      new ForwardParticipantRequest({ room, identity, destinationRoom }).toJson(),\n      await this.authHeader({ roomAdmin: true, room, destinationRoom }),\n    );\n  }\n\n  /**\n   * Move a connected participant to a different room. Requires `roomAdmin` and `destinationRoom`.\n   * The participant will be removed from the current room and added to the destination room.\n   * From the other observers' perspective, the participant would've disconnected from the previous room and joined the new one.\n   * @param room -\n   * @param identity -\n   * @param destinationRoom - the room to move the participant to\n   */\n  async moveParticipant(room: string, identity: string, destinationRoom: string): Promise<void> {\n    await this.rpc.request(\n      svc,\n      'MoveParticipant',\n      new MoveParticipantRequest({ room, identity, destinationRoom }).toJson(),\n      await this.authHeader({ roomAdmin: true, room, destinationRoom }),\n    );\n  }\n\n  /**\n   * Mutes a track that the participant has published.\n   * @param room -\n   * @param identity -\n   * @param trackSid - sid of the track to be muted\n   * @param muted - true to mute, false to unmute\n   */\n  async mutePublishedTrack(\n    room: string,\n    identity: string,\n    trackSid: string,\n    muted: boolean,\n  ): Promise<TrackInfo> {\n    const req = new MuteRoomTrackRequest({\n      room,\n      identity,\n      trackSid,\n      muted,\n    }).toJson();\n    const data = await this.rpc.request(\n      svc,\n      'MutePublishedTrack',\n      req,\n      await this.authHeader({ roomAdmin: true, room }),\n    );\n    const res = MuteRoomTrackResponse.fromJson(data, { ignoreUnknownFields: true });\n    return res.track!;\n  }\n\n  /**\n   * Updates a participant's state or permissions\n   * @param room - target room\n   * @param identity - participant identity\n   * @param options - participant fields to update\n   */\n  async updateParticipant(\n    room: string,\n    identity: string,\n    options: UpdateParticipantOptions,\n  ): Promise<ParticipantInfo>;\n  /**\n   * Updates a participant's state or permissions\n   * @param room - target room\n   * @param identity - participant identity\n   * @param options - participant fields to update\n   */\n  async updateParticipant(\n    room: string,\n    identity: string,\n    metadata?: string,\n    permission?: Partial<ParticipantPermission>,\n    name?: string,\n  ): Promise<ParticipantInfo>;\n  async updateParticipant(\n    room: string,\n    identity: string,\n    metadataOrOptions?: string | UpdateParticipantOptions,\n    maybePermission?: Partial<ParticipantPermission>,\n    maybeName?: string,\n  ): Promise<ParticipantInfo> {\n    const hasOptions = typeof metadataOrOptions === 'object';\n    const metadata = hasOptions ? metadataOrOptions?.metadata : metadataOrOptions;\n    const permission = hasOptions ? metadataOrOptions.permission : maybePermission;\n    const name = hasOptions ? metadataOrOptions.name : maybeName;\n    const attributes: Record<string, string> | undefined = hasOptions\n      ? metadataOrOptions.attributes\n      : {};\n\n    const req = new UpdateParticipantRequest({\n      room,\n      identity,\n      attributes,\n      metadata,\n      name,\n    });\n    if (permission) {\n      req.permission = new ParticipantPermission(permission);\n    }\n    const data = await this.rpc.request(\n      svc,\n      'UpdateParticipant',\n      req.toJson(),\n      await this.authHeader({ roomAdmin: true, room }),\n    );\n    return ParticipantInfo.fromJson(data, { ignoreUnknownFields: true });\n  }\n\n  /**\n   * Updates a participant's subscription to tracks\n   * @param room -\n   * @param identity -\n   * @param trackSids -\n   * @param subscribe - true to subscribe, false to unsubscribe\n   */\n  async updateSubscriptions(\n    room: string,\n    identity: string,\n    trackSids: string[],\n    subscribe: boolean,\n  ): Promise<void> {\n    const req = new UpdateSubscriptionsRequest({\n      room,\n      identity,\n      trackSids,\n      subscribe,\n      participantTracks: [],\n    }).toJson();\n    await this.rpc.request(\n      svc,\n      'UpdateSubscriptions',\n      req,\n      await this.authHeader({ roomAdmin: true, room }),\n    );\n  }\n\n  /**\n   * Sends data message to participants in the room\n   * @param room -\n   * @param data - opaque payload to send\n   * @param kind - delivery reliability\n   * @param options - optionally specify a topic and destinationSids (when destinationSids is empty, message is sent to everyone)\n   */\n  async sendData(\n    room: string,\n    data: Uint8Array,\n    kind: DataPacket_Kind,\n    options: SendDataOptions,\n  ): Promise<void>;\n  /**\n   * Sends data message to participants in the room\n   * @deprecated use sendData(room, data, kind, options) instead\n   * @param room -\n   * @param data - opaque payload to send\n   * @param kind - delivery reliability\n   * @param destinationSids - optional. when empty, message is sent to everyone\n   */\n  async sendData(\n    room: string,\n    data: Uint8Array,\n    kind: DataPacket_Kind,\n    destinationSids?: string[],\n  ): Promise<void>;\n  async sendData(\n    room: string,\n    data: Uint8Array,\n    kind: DataPacket_Kind,\n    options: SendDataOptions | string[] = {},\n  ): Promise<void> {\n    const destinationSids = Array.isArray(options) ? options : options.destinationSids;\n    const topic = Array.isArray(options) ? undefined : options.topic;\n    const req = new SendDataRequest({\n      room,\n      data,\n      kind,\n      destinationSids: destinationSids ?? [],\n      topic,\n    });\n    if (!Array.isArray(options) && options.destinationIdentities) {\n      req.destinationIdentities = options.destinationIdentities;\n    }\n    req.nonce = await getRandomBytes(16);\n    await this.rpc.request(\n      svc,\n      'SendData',\n      req.toJson(),\n      await this.authHeader({ roomAdmin: true, room }),\n    );\n  }\n}\n"],"mappings":"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","names":[]}