Skip to content

Commit

Permalink
documentation for realtime-api entities (#296)
Browse files Browse the repository at this point in the history
* documentation for realtime-api entities

* recordings

* videoMember

* minor tweak

* value -> volume

* SameOf

* update typedoc-readme-api-theme

* fixes

* refactoring

* videoRoomSession

* RoomSession

* changeset

* remove date info

* misc

* rename SameOf -> AssertSameType

* typo
  • Loading branch information
danieleds authored Sep 20, 2021
1 parent 49b4aa9 commit 685e0a2
Show file tree
Hide file tree
Showing 14 changed files with 561 additions and 33 deletions.
6 changes: 6 additions & 0 deletions .changeset/violet-meals-retire.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
'@signalwire/core': patch
'@signalwire/realtime-api': patch
---

Updated the documentation [docs]
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
"@changesets/changelog-github": "^0.4.0",
"@changesets/cli": "^2.16.0",
"@manypkg/cli": "^0.18.0",
"@signalwire/typedoc-readme-api-theme": "^0.3.0",
"@signalwire/typedoc-readme-api-theme": "^0.4.0",
"@types/jest": "^26.0.24",
"babel-jest": "^27.0.6",
"concurrently": "^6.2.0",
Expand Down
3 changes: 3 additions & 0 deletions packages/core/src/rooms/RoomSessionRecording.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ import type {
VideoRecordingEventNames,
} from '../types/videoRecording'

/**
* Represents a specific recording of a room session.
*/
export interface RoomSessionRecording extends VideoRecordingContract {}

export type RoomSessionRecordingEventsHandlerMapping = Record<
Expand Down
48 changes: 48 additions & 0 deletions packages/core/src/types/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,54 @@ export type OnlyFunctionProperties<T> = Pick<T, OnlyFunctionPropertyNames<T>>

export type OnlyStateProperties<T> = Pick<T, OnlyStatePropertyNames<T>>

/**
* This type is `never` if the two type parameters don't match. If they match,
* it is equal to one of the two types.
*
* Motivation: we use this type for documentation purposes. Some of the types
* and interfaces that we want to publicly expose have several layers of
* indirection and are not detected correctly by TypeDoc. To workaround the
* problem, we additionally write a fully documented explicit type and we use
* `AssertSameType` to ensure that the two are equal at compile-time. Of the two
* input types, `AssertSameType` returns the documented one (which, apart from
* documentation, is indistinguishable from the other one).
*
* As an example, say we want to expose an interface named `RoomSession`, whose
* methods are not currently getting picked up by TypeDoc:
*
* ```typescript
* export interface RoomSession { ... }
* ```
*
* To make `RoomSession` documentable, we rename it (as a convention) into
* `RoomSessionMain` and we also add an equivalent `RoomSessionDocs` with
* explicit types:
*
* ```typescript
* interface RoomSessionMain { ... }
*
* interface RoomSessionDocs {
* // doc string ...
* audioMute(params: { memberId: string }): Promise<void>
*
* // doc string ...
* audioUnmute(params: { memberId: string }): Promise<void>
* }
* ```
*
* Then, we export a new interface which extends AssertSameType:
*
* ```typescript
* export interface RoomSession extends
* AssertSameType<RoomSessionMain, RoomSessionDocs> {}
* ```
*
* If `RoomSessionMain` and `RoomSessionDocs` are not equal, we get a
* compile-time error. If they are equal, `RoomSession` will refer to the
* documented version of the methods.
*/
export type AssertSameType<ExpectedType, Output> = ExpectedType extends Output ? Output extends ExpectedType ? Output : never : never

export interface ConstructableType<T> {
new (o?: any): T
}
Expand Down
34 changes: 31 additions & 3 deletions packages/core/src/types/videoMember.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import type {
ToInternalVideoEvent,
OnlyStateProperties,
OnlyFunctionProperties,
AssertSameType
} from './utils'
import * as Rooms from '../rooms'

Expand Down Expand Up @@ -37,10 +38,31 @@ export const INTERNAL_MEMBER_UPDATED_EVENTS = Object.keys(
}` as const
})

type VideoMemberUpdatableProps = {
type VideoMemberUpdatablePropsMain = {
[K in keyof InternalVideoMemberUpdatableProps as SnakeToCamelCase<K>]: InternalVideoMemberUpdatableProps[K]
}

type VideoMemberUpdatableProps = AssertSameType<VideoMemberUpdatablePropsMain, {
/** Whether the outbound audio is muted (e.g., from the microphone) */
audioMuted: boolean,
/** Whether the outbound video is muted */
videoMuted: boolean,
/** Whether the inbound audio is muted */
deaf: boolean,
/** Whether the member is on hold */
onHold: boolean,
/** Whether the member is visible */
visible: boolean,
/** Input volume (e.g., of the microphone). Values range from -50 to 50, with a default of 0. */
inputVolume: number,
/** Output volume (e.g., of the speaker). Values range from -50 to 50, with a default of 0. */
outputVolume: number,
/** Input level at which the participant is identified as currently speaking.
* The default value is 30 and the scale goes from 0 (lowest sensitivity,
* essentially muted) to 100 (highest sensitivity). */
inputSensitivity: number
}>

// @ts-expect-error
export const MEMBER_UPDATABLE_PROPS: VideoMemberUpdatableProps = toExternalJSON(
INTERNAL_MEMBER_UPDATABLE_PROPS
Expand Down Expand Up @@ -112,11 +134,17 @@ export type VideoMemberType = 'member' | 'screen' | 'device'
* Public Contract for a VideoMember
*/
export interface VideoMemberContract extends VideoMemberUpdatableProps {
/** Unique id of this member. */
id: string
/** Id of the room associated to this member. */
roomId: string
/** Id of the room session associated to this member. */
roomSessionId: string
/** Name of this member. */
name: string
/** Id of the parent video member, if it exists. */
parentId?: string
/** Type of this video member. Can be `'member'`, `'screen'`, or `'device'`. */
type: VideoMemberType

/**
Expand Down Expand Up @@ -196,9 +224,9 @@ export interface VideoMemberContract extends VideoMemberUpdatableProps {

/**
* Sets the speaker output level.
*
*
* @param params
* @param params.value desired volume. Values range from -50 to 50, with a
* @param params.volume desired volume. Values range from -50 to 50, with a
* default of 0.
*
* @example
Expand Down
16 changes: 16 additions & 0 deletions packages/core/src/types/videoRecording.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,15 +32,31 @@ export type InternalVideoRecordingEventNames =
* Public Contract for a VideoRecording
*/
export interface VideoRecordingContract {
/** The unique id of this recording */
id: string

/** The id of the room session associated to this recording */
roomSessionId: string

/** Current state */
state: 'recording' | 'paused' | 'completed'

/** Duration, if available */
duration?: number

/** Start time, if available */
startedAt?: number

/** End time, if available */
endedAt?: number

/** Pauses the recording. */
pause(): Promise<void>

/** Resumes the recording */
resume(): Promise<void>

/** Stops the recording */
stop(): Promise<void>
}

Expand Down
5 changes: 5 additions & 0 deletions packages/core/src/types/videoRoomSession.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,12 +44,17 @@ export type InternalVideoRoomSessionEventNames =
* Public Contract for a VideoRoomSession
*/
export interface VideoRoomSessionContract {
/** Unique id for this room session */
id: string
/** Id of the room associated to this room session */
roomId: string
/** @internal */
eventChannel: string
/** Name of this room */
name: string
/** Whether recording is active */
recording: boolean
/** Whether muted videos are shown in the room layout. See {@link setHideVideoMuted} */
hideVideoMuted: boolean

audioMute(params: MemberCommandParams): Rooms.AudioMuteMember
Expand Down
5 changes: 4 additions & 1 deletion packages/core/src/utils/interfaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,10 @@ export type SessionStatus =

export type SessionEvents = `session.${SessionStatus}`

/** List of all the events the client can listen to. */
/**
* List of all the events the client can listen to.
* @internal
*/
export type ClientEvents = Record<SessionEvents, () => void>

export type BaseConnectionState =
Expand Down
69 changes: 46 additions & 23 deletions packages/realtime-api/src/Client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,59 @@ import {
} from '@signalwire/core'
import { createVideoObject, Video } from './video/Video'

/**
* A real-time Client.
*
* To construct an instance of this class, please use {@link createClient}.
*
* Example usage:
* ```typescript
* import {createClient} from '@signalwire/realtime-api'
*
* // Obtain a client:
* const client = await createClient({project, token})
*
* // Listen on events:
* client.video.on('room.started', async (room) => { })
*
* // Connect:
* await client.connect()
* ```
*/
export interface RealtimeClient
extends ClientContract<RealtimeClient, ClientEvents> {

/**
* Connects this client to the SignalWire network.
*
* As a general best practice, it is suggested to connect the event listeners
* *before* connecting the client, so that no events are lost.
*
* @returns Upon connection, asynchronously returns an instance of this same
* object.
*
* @example
* ```typescript
* const client = await createClient({project, token})
* client.video.on('room.started', async (roomSession) => { }) // connect events
* await client.connect()
* ```
*/
connect(): Promise<RealtimeClient>

/**
* Disconnects this client from the SignalWire network.
*/
disconnect(): void

/**
* Access the Video API Consumer
*/
video: Video
}

type ClientNamespaces = Video

/**
* A real-time Client.
*
* To construct an instance of this class, please use {@link createClient}.
*/
export class Client extends BaseClient<ClientEvents> {
private _consumers: Map<EventsPrefix, ClientNamespaces> = new Map()

Expand All @@ -45,24 +86,6 @@ export class Client extends BaseClient<ClientEvents> {
}
}

/**
* Connects this client to the SignalWire network.
* @returns Upon connection, asynchronously returns an instance of this same object.
*
* @example
* ```typescript
* const client = await createClient({project, token})
* client.video.on('room.started', async (room) => { }) // connect events
* await client.connect()
* ```
*/
connect(): Promise<this> {
return super.connect()
}

/**
* Access the Video API Consumer
*/
get video(): Video {
if (this._consumers.has('video')) {
return this._consumers.get('video')!
Expand Down
1 change: 1 addition & 0 deletions packages/realtime-api/src/createClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
import { Client, RealtimeClient } from './Client'
import { Session } from './Session'

/** @internal */
export interface CreateClientOptions extends Omit<UserOptions, 'autoConnect'> {}
export type { RealtimeClient, ClientEvents }

Expand Down
31 changes: 31 additions & 0 deletions packages/realtime-api/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,33 @@
/**
* You can use the realtime SDK to listen for and react to events from
* SignalWire's RealTime APIs.
*
* To get started, create a realtime client with {@link createClient} and listen
* for events. For example:
*
* ```typescript
* import { createClient } from '@signalwire/realtime-api'
*
* const client = await createClient({
* project: '<project-id>',
* token: '<project-token>'
* })
*
* client.video.on('room.started', async (roomSession) => {
* console.log("Room started")
*
* roomSession.on('member.joined', async (member) => {
* await member.videoMute()
* })
*
* await roomSession.subscribe()
* }
*
* await client.connect()
* ```
*
* @module
*/

export * from './createClient'
export * as Video from './video/Video'
Loading

0 comments on commit 685e0a2

Please sign in to comment.