Browse Source

add more linter rules & lint

merge-requests/2/head
Paul Tirk 1 year ago
parent
commit
354552bfda
  1. 120
      .eslintrc.json
  2. 10
      src/classes/AbstractWebRtcServerHelper.ts
  3. 8
      src/classes/BackendApiRequestHelper.ts
  4. 187
      src/classes/RoomApiHandler.ts
  5. 164
      src/classes/Session.ts
  6. 68
      src/classes/SessionManager.ts
  7. 87
      src/classes/SignalingMessageHelper.ts
  8. 40
      src/classes/WebRtcServerHelpers/JanusWebRtcServerHelper.ts
  9. 1
      tsconfig.json

120
.eslintrc.json

@ -1,4 +1,3 @@
//these rules are based on the aurelia-tools standard and modified for recordIt use
{
"root": true,
"parser": "@typescript-eslint/parser",
@ -43,8 +42,8 @@
// "never"
// ],
// "no-var": "error",
// "prefer-const": "warn",
"no-var": "error",
"prefer-const": "warn",
// "no-shadow": "error",
// "no-shadow-restricted-names": "error",
@ -55,12 +54,43 @@
"args": "none"
}
],
"@typescript-eslint/explicit-function-return-type": [
"error"
],
"@typescript-eslint/explicit-member-accessibility": [
"error",
{
"accessibility": "explicit",
"overrides": {
"constructors": "no-public"
}
}
],
"@typescript-eslint/member-delimiter-style": [
"error",
{
"multiline": {
"delimiter": "comma",
"requireLast": false
},
"singleline": {
"delimiter": "comma",
"requireLast": false
}
}
],
"@typescript-eslint/interface-name-prefix": [
"error",
"always"
],
"@typescript-eslint/semi": "error",
"@typescript-eslint/no-empty-interface": "warn",
// "no-use-before-define": "off",
// "comma-dangle": [
// "error",
// "never"
// ],
"comma-dangle": [
"error",
"never"
],
// "no-cond-assign": [
// "error",
// "except-parens"
@ -75,7 +105,7 @@
// "no-empty": "error",
// "no-ex-assign": "error",
// "no-extra-boolean-cast": "off",
// "no-extra-semi": "error",
"no-extra-semi": "error",
// "no-func-assign": "error",
// "no-inner-declarations": "error",
// "no-invalid-regexp": "error",
@ -86,9 +116,9 @@
// "use-isnan": "error",
// "block-scoped-var": "off",
// /**
// * Best practices
// */
/**
* Best practices
*/
// "consistent-return": "off",
// "curly": [
// "error",
@ -139,9 +169,9 @@
// ],
// "yoda": "error",
// /**
// * Style
// */
/**
* Style
*/
"indent": [
"error",
2,
@ -156,13 +186,13 @@
// }
}
],
// "brace-style": [
// "error",
// "1tbs",
// {
// "allowSingleLine": true
// }
// ],
"brace-style": [
"error",
"1tbs",
{
"allowSingleLine": true
}
],
"quotes": [
"error",
"single",
@ -176,19 +206,19 @@
"after": true
}
],
// "comma-style": [
// "error",
// "last"
// ],
"comma-style": [
"error",
"last"
],
// "eol-last": "error",
// "func-names": "off",
// "key-spacing": [
// "error",
// {
// "beforeColon": false,
// "afterColon": true
// }
// ],
"key-spacing": [
"error",
{
"beforeColon": false,
"afterColon": true
}
],
// "new-cap": [
// "error",
// {
@ -201,7 +231,7 @@
// "max": 2
// }
// ],
// "no-nested-ternary": "error",
"no-nested-ternary": "error",
// "no-new-object": "error",
// "no-spaced-func": "error",
"no-trailing-spaces": "error",
@ -224,13 +254,13 @@
"error",
"always"
],
// "semi-spacing": [
// "error",
// {
// "before": false,
// "after": true
// }
// ],
"semi-spacing": [
"error",
{
"before": false,
"after": true
}
],
"keyword-spacing": [
"error",
{
@ -254,11 +284,11 @@
}
],
// "space-before-blocks": "error",
// "space-before-function-paren": ["error", {
// "anonymous": "never",
// "named": "never",
// "asyncArrow": "always"
// }],
"space-before-function-paren": ["error", {
"anonymous": "never",
"named": "never",
"asyncArrow": "always"
}],
// "space-infix-ops": "error",
"spaced-comment": [
"error",

10
src/classes/AbstractWebRtcServerHelper.ts

@ -1,4 +1,4 @@
abstract class AbstractWebRtcServerHelper {
export abstract class AbstractWebRtcServerHelper {
abstract async createSession(): Promise<string>;
abstract async destroySession(sessionId: string): Promise<void>;
@ -16,9 +16,9 @@ abstract class AbstractWebRtcServerHelper {
abstract async unpublish(sessionId: string): Promise<void>;
abstract async unsubscribe(sessionId: string, sessionIdToUnsubscribe: string): Promise<void>;
abstract async trickleCandidate(sessionId: string, candidate: Candidate): Promise<void>;
abstract async trickleCandidate(sessionId: string, candidate: ICandidate): Promise<void>;
async trickleCandidates(sessionId: string, candidates: Array<Candidate>): Promise<void> {
public async trickleCandidates(sessionId: string, candidates: Array<ICandidate>): Promise<void> {
for(const candidate of candidates) {
await this.trickleCandidate(sessionId, candidate);
}
@ -28,13 +28,13 @@ abstract class AbstractWebRtcServerHelper {
}
interface RoomInfo {
interface IRoomInfo {
// TODO
}
type Offer = string
type Answer = string
interface Candidate {
interface ICandidate {
// TODO
}

8
src/classes/BackendApiRequestHelper.ts

@ -8,11 +8,11 @@ export class BackendApiRequestHelper {
private url: string = '';
setUrl(url: string) {
public setUrl(url: string): void {
this.url = url;
}
async sendAuthRequest(data: AuthRequestData): Promise<AuthResponseData> {
public async sendAuthRequest(data: AuthRequestData): Promise<AuthResponseData> {
const requestBody: AuthRequest = {
type: BackendApiRequestType.AUTH,
auth: {
@ -26,7 +26,7 @@ export class BackendApiRequestHelper {
return backendResponse.auth;
}
async sendRoomRequest(data: RoomRequestData): Promise<RoomResponseData> {
public async sendRoomRequest(data: RoomRequestData): Promise<RoomResponseData> {
const requestBody: RoomRequest = {
type: BackendApiRequestType.ROOM,
room: {
@ -43,7 +43,7 @@ export class BackendApiRequestHelper {
return backendResponse.room;
}
async sendPingRequest(data: PingRequestData): Promise<PingResponseData> {
public async sendPingRequest(data: PingRequestData): Promise<PingResponseData> {
// TODO - find out what and why?
const requestBody: PingRequest = {
type: BackendApiRequestType.PING,

187
src/classes/RoomApiHandler.ts

@ -14,15 +14,15 @@ export class RoomApiHandler {
this.setUpRoutes();
}
getRouter(): Router {
public getRouter(): Router {
return this.router;
}
private setUpRoutes() {
private setUpRoutes(): void {
this.router.post('/api/v1/room/:roomId', this.handleRoomApiRequest.bind(this));
}
private handleRoomApiRequest(request: Request, response: Response) {
private handleRoomApiRequest(request: Request, response: Response): void {
const roomId = request.params.roomId;
const body: RoomApiRequestBody = request.body;
@ -63,7 +63,7 @@ export class RoomApiHandler {
}
// Room::EVENT_AFTER_USERS_ADD
private handleInviteRequest(roomId: string, data: RoomApiInviteRequestData) {
private handleInviteRequest(roomId: string, data: IRoomApiInviteRequestData): void {
this.log('INVITE:', data);
const sendData = {
roomid: roomId,
@ -74,8 +74,9 @@ export class RoomApiHandler {
// Room::EVENT_AFTER_USER_REMOVE
// Room::EVENT_AFTER_PARTICIPANT_REMOVE -> sessions
private handleDisinviteRequest(roomId: string, data: RoomApiDisinviteRequestData) {
private handleDisinviteRequest(roomId: string, data: RoomApiDisinviteRequestData): void {
this.log('DISINVITE:', data);
const sendData = {
roomid: roomId,
properties: data.properties
@ -92,8 +93,9 @@ export class RoomApiHandler {
// "participantsModified" once the clients no longer expect a
// "roomModified" message for participant type changes.
// Room::EVENT_AFTER_PARTICIPANT_TYPE_SET
private handleUpdateRequest(roomId: string, data: RoomApiUpdateRequestData) {
private handleUpdateRequest(roomId: string, data: IRoomApiUpdateRequestData): void {
this.log('UPDATE:', data);
const sendData = {
roomid: roomId,
properties: data.properties
@ -102,20 +104,20 @@ export class RoomApiHandler {
}
// Room::EVENT_BEFORE_ROOM_DELETE
private handleDeleteRequest(roomId: string, data: RoomApiDeleteRequestData) {
// TODO
private handleDeleteRequest(roomId: string, data: IRoomApiDeleteRequestData): void {
this.log('DELETE:', data);
const sendData = {
roomid: roomId
};
this.fireEvent('roomListEvent', { type: RoomListEventType.DISINVITE, userIds: data.userids, eventData: sendData });
this.fireEvent('roomDeleted', { roomId: roomId });
}
// Room::EVENT_AFTER_PARTICIPANT_TYPE_SET
// Room::EVENT_AFTER_GUESTS_CLEAN
// GuestManager::EVENT_AFTER_NAME_UPDATE
private handleParticipantsRequest(roomId: string, data: RoomApiParticipantsRequestData) {
private handleParticipantsRequest(roomId: string, data: IRoomApiParticipantsRequestData): void {
this.log('PARTICIPANTS:', data);
const sendData = {
roomid: roomId,
@ -127,7 +129,7 @@ export class RoomApiHandler {
// Room::EVENT_AFTER_SESSION_JOIN_CALL
// Room::EVENT_AFTER_SESSION_LEAVE_CALL
private handleIncallRequest(roomId: string, data: RoomApiIncallRequestData) {
private handleIncallRequest(roomId: string, data: IRoomApiIncallRequestData): void {
this.log('INCALL:', data);
const sendData = {
roomid: roomId,
@ -138,14 +140,14 @@ export class RoomApiHandler {
// ChatManager::EVENT_AFTER_MESSAGE_SEND
// ChatManager::EVENT_AFTER_SYSTEM_MESSAGE_SEND
private handleMessageRequest(roomId: string, data: RoomApiMessageRequestData) {
private handleMessageRequest(roomId: string, data: IRoomApiMessageRequestData): void {
this.log('MESSAGE:', data);
if(data.data && data.data.chat) {
this.fireEvent('roomMessage', { roomId: roomId, data: data.data });
}
}
on(eventName: string, eventHandler: EventHandler) {
public on<K extends EventName>(eventName: K, eventHandler: (v: IEvents[K]) => void): void {
const eventHandlers = this.eventHandlers.get(eventName);
if(!eventHandlers) {
this.eventHandlers.set(eventName, [ eventHandler ]);
@ -154,123 +156,119 @@ export class RoomApiHandler {
}
}
fireEvent(eventName: string, eventData) {
private fireEvent<K extends EventName>(eventName: K, eventData: IEvents[K]): void {
const eventHandlers = this.eventHandlers.get(eventName);
eventHandlers?.forEach(handler => {
handler(eventData);
});
}
log(message: string, data?: any) {
private log(message: string, data?: any): void {
console.log(`ROOM API: ${message}`, data || '');
}
}
interface EventHandler {
(data): void;
}
// export namespace RoomApiHandler {
type RoomApiRequestBody =
RoomApiInviteRequestBody |
RoomApiDisinviteRequestBody |
RoomApiUpdateRequestBody |
RoomApiDeleteRequestBody |
RoomApiParticipantsRequestBody |
RoomApiIncallRequestBody |
RoomApiMessageRequestBody;
interface RoomApiInviteRequestBody {
type: RoomApiRequestType.INVITE;
invite: RoomApiInviteRequestData
IRoomApiInviteRequestBody |
IRoomApiDisinviteRequestBody |
IRoomApiUpdateRequestBody |
IRoomApiDeleteRequestBody |
IRoomApiParticipantsRequestBody |
IRoomApiIncallRequestBody |
IRoomApiMessageRequestBody;
interface IRoomApiInviteRequestBody {
type: RoomApiRequestType.INVITE,
invite: IRoomApiInviteRequestData
}
interface RoomApiInviteRequestData {
userids: Array<string>;
alluserids: Array<string>;
properties: RoomApiRequestDataProperties;
interface IRoomApiInviteRequestData {
userids: Array<string>,
alluserids: Array<string>,
properties: IRoomApiRequestDataProperties
}
interface RoomApiDisinviteRequestBody {
type: RoomApiRequestType.DISINVITE;
disinvite: RoomApiDisinviteRequestData;
interface IRoomApiDisinviteRequestBody {
type: RoomApiRequestType.DISINVITE,
disinvite: RoomApiDisinviteRequestData
}
type RoomApiDisinviteRequestData = RoomApiDisinviteUserIdsRequestData | RoomApiDisinviteSessionIdsRequestData;
interface RoomApiDisinviteRequestDataCommon {
alluserids: Array<string>;
properties: RoomApiRequestDataProperties;
interface IRoomApiDisinviteRequestDataCommon {
alluserids: Array<string>,
properties: IRoomApiRequestDataProperties
}
type RoomApiDisinviteUserIdsRequestData = RoomApiDisinviteRequestDataCommon & {
userids: Array<string>;
}
type RoomApiDisinviteUserIdsRequestData = IRoomApiDisinviteRequestDataCommon & {
userids: Array<string>
};
type RoomApiDisinviteSessionIdsRequestData = RoomApiDisinviteRequestDataCommon & {
sessionids: Array<string>;
}
type RoomApiDisinviteSessionIdsRequestData = IRoomApiDisinviteRequestDataCommon & {
sessionids: Array<string>
};
interface RoomApiUpdateRequestBody {
type: RoomApiRequestType.UPDATE;
update: RoomApiUpdateRequestData;
interface IRoomApiUpdateRequestBody {
type: RoomApiRequestType.UPDATE,
update: IRoomApiUpdateRequestData
}
interface RoomApiUpdateRequestData {
userids: Array<string>;
properties: RoomApiRequestDataProperties;
interface IRoomApiUpdateRequestData {
userids: Array<string>,
properties: IRoomApiRequestDataProperties
}
interface RoomApiDeleteRequestBody {
type: RoomApiRequestType.DELETE;
delete: RoomApiDeleteRequestData;
interface IRoomApiDeleteRequestBody {
type: RoomApiRequestType.DELETE,
delete: IRoomApiDeleteRequestData
}
interface RoomApiDeleteRequestData {
userids: Array<string>;
interface IRoomApiDeleteRequestData {
userids: Array<string>
}
interface RoomApiParticipantsRequestBody {
type: RoomApiRequestType.PARTICIPANTS;
participants: RoomApiParticipantsRequestData;
interface IRoomApiParticipantsRequestBody {
type: RoomApiRequestType.PARTICIPANTS,
participants: IRoomApiParticipantsRequestData
}
interface RoomApiParticipantsRequestData {
changed: Array<Participant>;
users: Array<Participant>;
interface IRoomApiParticipantsRequestData {
changed: Array<IParticipant>,
users: Array<IParticipant>
}
interface RoomApiIncallRequestBody {
type: RoomApiRequestType.INCALL;
incall: RoomApiIncallRequestData;
interface IRoomApiIncallRequestBody {
type: RoomApiRequestType.INCALL,
incall: IRoomApiIncallRequestData
}
interface RoomApiIncallRequestData {
incall: number; // TODO Flags
changed: Array<Participant>;
users: Array<Participant>;
interface IRoomApiIncallRequestData {
incall: number, // TODO Flags
changed: Array<IParticipant>,
users: Array<IParticipant>
}
interface RoomApiMessageRequestBody {
type: RoomApiRequestType.MESSAGE;
message: RoomApiMessageRequestData;
interface IRoomApiMessageRequestBody {
type: RoomApiRequestType.MESSAGE,
message: IRoomApiMessageRequestData
}
interface RoomApiMessageRequestData {
interface IRoomApiMessageRequestData {
data: {
chat: { refresh: true };
chat: { refresh: true }
}
}
export interface RoomApiRequestDataProperties {
name: string;
type: RoomType;
'lobby-state': LobbyState;
'lobby-timer': RoomApiDateObject|null;
'read-only': ReadOnly;
'active-since': RoomApiDateObject|null;
export interface IRoomApiRequestDataProperties {
name: string,
type: RoomType,
'lobby-state': LobbyState,
'lobby-timer': IRoomApiDateObject|null,
'read-only': ReadOnly,
'active-since': IRoomApiDateObject|null
}
enum RoomApiRequestType {
@ -301,12 +299,12 @@ enum ReadOnly {
READ_ONLY
}
export interface Participant {
inCall: number; // Combination of ParticipantFlags
lastPing: number;
sessionId: string;
participantType: ParticipantType;
userId: string | undefined; // for guests
export interface IParticipant {
inCall: number, // Combination of ParticipantFlags
lastPing: number,
sessionId: string,
participantType: ParticipantType,
userId: string | undefined // for guests
}
enum ParticipantType {
@ -325,10 +323,21 @@ enum ParticipantFlags {
WITH_VIDEO = 4
}
interface RoomApiDateObject {
interface IRoomApiDateObject {
date: string,
timezone: string,
timezone_type: number
}
// }
interface IEvents {
roomListEvent: { type: RoomListEventType, userIds: Array<string>, sessionIds: Array<string>, eventData },
roomMessage: { roomId: string, data },
roomDeleted: { roomId: string },
participantsListEvent: { sessionIds: Array<string>, roomId: string, eventData }
}
type EventName = keyof IEvents;
type EventHandler<K extends EventName> = (v: IEvents[K]) => void;

164
src/classes/Session.ts

@ -22,7 +22,7 @@ export class Session {
private backendApiRequestHelper: BackendApiRequestHelper;
private webRtcServerHelper?: AbstractWebRtcServerHelper;
constructor(options: ConstructorOptions, services: ConstructorServices) {
constructor(options: IConstructorOptions, services: IConstructorServices) {
this.id = options.sessionId;
this.socket = options.socket;
@ -34,50 +34,50 @@ export class Session {
this.setupSocket();
}
destructor() {
public destructor(): void {
this.webRtcServerHelper?.unpublish(this.id);
this.subscriberIds.forEach(id => {
this.webRtcServerHelper?.unsubscribe(this.id, id);
});
}
getId() {
public getId(): string {
return this.id;
}
getResumeId() {
public getResumeId(): string {
return this.resumeId;
}
getUserId() {
return this.ncUserId;
public getUserId(): string|null {
return this.ncUserId || null;
}
getRoomId() {
return this.ncRoomId;
public getRoomId(): string|null {
return this.ncRoomId || null;
}
getNcSessionId() {
return this.ncSessionId;
public getNcSessionId(): string|null {
return this.ncSessionId || null;
}
setUserId(userId: string) {
public setUserId(userId: string): void {
this.ncUserId = userId;
}
private setupSocket() {
private setupSocket(): void {
this.socket.on('message', this.handleSocketMessage.bind(this));
this.socket.on('close', this.handleSocketClosed.bind(this));
}
private handleSocketClosed() {
private handleSocketClosed(): void {
this.log('socket closed');
this.sessionClosedTimeout = setTimeout(() => {
this.fireEvent('socketClosed');
}, 10000);
}
resumeSession(socket: WebSocket) {
public resumeSession(socket: WebSocket): void {
this.log('resume session');
if(this.sessionClosedTimeout) {
clearTimeout(this.sessionClosedTimeout);
@ -89,11 +89,11 @@ export class Session {
this.resumeId = uuid();
}
sendSocketMessage(data: Object) {
public sendSocketMessage(data: Object): void {
this.socket.send(JSON.stringify(data));
}
private handleSocketMessage(message: string) {
private handleSocketMessage(message: string): void {
const data = JSON.parse(message);
switch(data.type) {
@ -113,7 +113,7 @@ export class Session {
}
}
private async handleRoomMessage(id: string, data: RoomMessageData) {
private async handleRoomMessage(id: string, data: IRoomMessageData): Promise<void> {
this.log('ROOM:', data);
const sessionId = data.sessionid || this.ncSessionId;
@ -158,12 +158,12 @@ export class Session {
}
}
private async handleControlMessage(data: ControlMessageData) {
private async handleControlMessage(data: IControlMessageData): Promise<void> {
this.log('CONTROL:', data);
await this.handleMessageMessage(data);
}
private async handleMessageMessage(data: MessageMessageData) {
private async handleMessageMessage(data: IMessageMessageData): Promise<void> {
this.log('MESSAGE:', data);
const recipient = data.recipient;
@ -188,8 +188,8 @@ export class Session {
}
}
sendMessageMessageResponse(recipient: MessageRecipientData, response) {
const messageResponse: MessageMessageResponse = {
public sendMessageMessageResponse(recipient: MessageRecipientData, response): void {
const messageResponse: IMessageMessageResponse = {
type: MessageType.MESSAGE,
message: {
sender: {
@ -204,19 +204,19 @@ export class Session {
this.sendSocketMessage(messageResponse);
}
private async handleMessageToSession(senderSessionId: string, recipient: MessageRecipientData, data) {
private async handleMessageToSession(senderSessionId: string, recipient: MessageRecipientData, data): void {
this.fireEvent('sessionMessage', { recipient, senderSessionId, data });
}
private handleMessageToUser(userId: string, data) {
private handleMessageToUser(userId: string, data): void {
this.fireEvent('userMessage', { userId, data });
}
private handleMessageToRoom(roomId: string, data) {
private handleMessageToRoom(roomId: string, data): void {
this.fireEvent('roomMessage', { roomId, data });
}
on(eventName: string, eventHandler: EventHandler) {
public on<K extends EventName>(eventName: K, eventHandler: (v: IEvents[K]) => void): void {
const eventHandlers = this.eventHandlers.get(eventName);
if(!eventHandlers) {
this.eventHandlers.set(eventName, [ eventHandler ]);
@ -225,90 +225,92 @@ export class Session {
}
}
fireEvent(eventName: string, eventData?) {
private fireEvent<K extends EventName>(eventName: K, eventData: IEvents[K]): void {
const eventHandlers = this.eventHandlers.get(eventName);
eventHandlers?.forEach(handler => {
handler(eventData);
});
}
private log(message: string, data?: any) {
private log(message: string, data?: any): void {
console.log(`SESSION ${this.id}: ${message}`, data || '');
}
}
interface ConstructorOptions {
sessionId: string;
socket: WebSocket;
interface IConstructorOptions {
sessionId: string,
socket: WebSocket
}
interface ConstructorServices {
backendApiRequestHelper: BackendApiRequestHelper;
webRtcServerHelper?: AbstractWebRtcServerHelper;
interface IConstructorServices {
backendApiRequestHelper: BackendApiRequestHelper,
webRtcServerHelper?: AbstractWebRtcServerHelper
}
interface EventHandler {
(data?): void;
}
interface MessageCommon {
id: string
interface IMessageCommon {
id: string,
type: MessageType
}
type Message = RoomMessage|ControlMessage|MessageMessage;
type Message = IRoomMessage|IControlMessage|IMessageMessage;
interface RoomMessage extends MessageCommon {
type: MessageType.ROOM
room: RoomMessageData
interface IRoomMessage extends IMessageCommon {
type: MessageType.ROOM,
room: IRoomMessageData
}
interface RoomMessageData {
roomid?: string;
interface IRoomMessageData {
roomid?: string,
// Pass the Nextcloud session id to the signaling server. The
// session id will be passed through to Nextcloud to check if
// the (Nextcloud) user is allowed to join the room.
sessionid?: string;
sessionid?: string
}
interface ControlMessage extends MessageCommon {
type: MessageType.CONTROL
control: ControlMessageData
interface IControlMessage extends IMessageCommon {
type: MessageType.CONTROL,
control: IControlMessageData
}
interface ControlMessageData {
recipient: MessageRecipientData; // currently only to sessions?
data;
interface IControlMessageData {
recipient: MessageRecipientData, // currently only to sessions?
data
}
interface MessageMessage extends MessageCommon {
type: MessageType.MESSAGE
message: MessageMessageData
interface IMessageMessage extends IMessageCommon {
type: MessageType.MESSAGE,
message: IMessageMessageData
}
interface MessageMessageData {
recipient: MessageRecipientData
interface IMessageMessageData {
recipient: MessageRecipientData,
data: {
type: MessageMessageDataType,
roomType: RoomType;
};
roomType: RoomType
}
}
export type MessageRecipientData = MessageSessionRecipientData | MessageRoomRecipientData | MessageUserRecipientData;
export type MessageRecipientData = IMessageSessionRecipientData | IMessageRoomRecipientData | IMessageUserRecipientData;
interface MessageSessionRecipientData {
type: MessageMessageRecipientType.SESSION;
sessionid: string;
interface IMessageSessionRecipientData {
type: MessageMessageRecipientType.SESSION,
sessionid: string
}
interface MessageRoomRecipientData {
interface IMessageRoomRecipientData {
type: MessageMessageRecipientType.ROOM
}
interface MessageUserRecipientData {
type: MessageMessageRecipientType.USER
userid: string;
interface IMessageUserRecipientData {
type: MessageMessageRecipientType.USER,
userid: string
}
interface IMessageResponseRecipientData {
type: MessageMessageRecipientType,
sessionid: string,
userid?: string
}
enum MessageMessageDataType {
@ -316,14 +318,14 @@ enum MessageMessageDataType {
SENDOFFER = 'sendoffer'
}
interface MessageMessageResponse {
type: MessageType.MESSAGE;
message: MessageMessageResponseData
interface IMessageMessageResponse {
type: MessageType.MESSAGE,
message: IMessageMessageResponseData
}
interface MessageMessageResponseData {
sender: MessageRecipientData;
data;
interface IMessageMessageResponseData {
sender: IMessageResponseRecipientData,
data: any
}
enum MessageType {
@ -347,7 +349,7 @@ export enum RoomListEventType {
UPDATE = 'update'
}
enum MessageMessageRecipientType {
export enum MessageMessageRecipientType {
SESSION = 'session',
ROOM = 'room',
USER = 'user'
@ -357,3 +359,17 @@ enum RoomType {
VIDEO = 'video',
SCREEN = 'screen'
}
interface IEvents {
socketClosed: null,
roomEvent: { roomId: string, type: RoomEventType, eventData: any },
sessionMessage: { recipient: MessageRecipientData, senderSessionId: string, data: any },
userMessage: { userId: string, data: any },
roomMessage: { roomId: string, data: any },
roomJoined: { roomId: string },
roomLeft: null
}
type EventName = keyof IEvents;
type EventHandler<K extends EventName> = (v: IEvents[K]) => void;

68
src/classes/SessionManager.ts

@ -10,7 +10,7 @@ export class SessionManager {
private webRtcServerHelper?: AbstractWebRtcServerHelper;
private roomApiHandler: RoomApiHandler;
constructor({ webRtcServerHelper, roomApiHandler }: ConstructorServices) {
constructor({ webRtcServerHelper, roomApiHandler }: IConstructorServices) {
this.sessions = [];
this.webRtcServerHelper = webRtcServerHelper;
this.roomApiHandler = roomApiHandler;
@ -20,31 +20,31 @@ export class SessionManager {
this.roomApiHandler.on('roomMessage', this.onRoomMessage.bind(this));
}
getSessionById(sessionId: string): Session|null {
public getSessionById(sessionId: string): Session|null {
return this.sessions.find(session => session.getId() === sessionId) || null;
}
getSessionsByIds(sessionIds: Array<string>): Array<Session> {
public getSessionsByIds(sessionIds: Array<string>): Array<Session> {
return this.sessions.filter(session => sessionIds.includes(session.getId()));
}
getSessionByResumeId(resumeId: string): Session|null {
public getSessionByResumeId(resumeId: string): Session|null {
return this.sessions.find(session => session.getResumeId() === resumeId) || null;
}
getSessionByNcId(ncSessionId: string): Session|null {
public getSessionByNcSessionId(ncSessionId: string): Session|null {
return this.sessions.find(session => session.getNcSessionId() === ncSessionId) || null;
}
getSessionsForRoomId(roomId: string): Array<Session> {
public getSessionsForRoomId(roomId: string): Array<Session> {
return this.sessions.filter(session => session.getRoomId() === roomId);
}
getSessionsForUserId(userId: string): Array<Session> {
public getSessionsForUserId(userId: string): Array<Session> {
return this.sessions.filter(session => session.getUserId() === userId);
}
getSessionsForUserIds(userIds: Array<string>): Array<Session> {
public getSessionsForUserIds(userIds: Array<string>): Array<Session> {
return this.sessions.filter(session => userIds.includes(session.getUserId() || ''));
}
@ -84,11 +84,11 @@ export class SessionManager {
}
}
deleteSession(session: Session) {
public deleteSession(session: Session): void {
this.deleteSessionById(session.getId());
}
deleteSessionById(sessionId: string) {
public deleteSessionById(sessionId: string): void {
const index = this.sessions.findIndex(session => session.getId() === sessionId);
if(index >= 0) {
@ -99,7 +99,7 @@ export class SessionManager {
}
}
private onRoomEvent({ roomId, type, eventData }: { roomId: string, type: RoomEventType, eventData: RoomEventData }) {
private onRoomEvent({ roomId, type, eventData }: { roomId: string, type: RoomEventType, eventData: IRoomEventData }): void {
const sendData = {
target: 'room',
type: type,
@ -111,7 +111,7 @@ export class SessionManager {
});
}
private onRoomListEvent({ type, userIds, sessionIds, eventData }: { type: RoomListEventType, userIds?: Array<string>, sessionIds?: Array<string>, eventData: RoomListEventData }) {
private onRoomListEvent({ type, userIds, sessionIds, eventData }: { type: RoomListEventType, userIds?: Array<string>, sessionIds?: Array<string>, eventData: IRoomListEventData }): void {
const sendData = {
target: 'roomlist',
type: type,
@ -123,7 +123,7 @@ export class SessionManager {
});
}
private onParticipantsListEvent({ sessionIds, roomId, eventData }: { sessionIds?: Array<string>, roomId?: string, eventData: ParticipantsListEventData }) {
private onParticipantsListEvent({ sessionIds, roomId, eventData }: { sessionIds?: Array<string>, roomId?: string, eventData: IParticipantsListEventData }): void {
const changedParticipants = eventData.users.map(item => {
const session = this.getSessionByNcId(item.sessionId);
if(!session) return item;
@ -160,7 +160,7 @@ export class SessionManager {
session.sendSocketMessage(sendData);
}
private async onSessionMessage({ recipient, senderSessionId, data }: { recipient: MessageRecipientData }) {
private async onSessionMessage({ recipient, senderSessionId, data }: { recipient: MessageRecipientData, senderSessionId: string, data }): Promise<void> {
this.log('MESSAGE:', data);
if(recipient.type !== 'session') return; // TODO check better?
@ -225,7 +225,7 @@ export class SessionManager {
}
}
private async handleOfferRequest(session: Session, senderSessionId: string) {
private async handleOfferRequest(session: Session, senderSessionId: string): Promise<void> {
if(this.webRtcServerHelper) {
session.subscriberIds.set(senderSessionId, true);
return await this.webRtcServerHelper.subscribeToFeedOfRoom(senderSessionId, session.getRoomId(), session.id);
@ -234,7 +234,7 @@ export class SessionManager {
}
}
private async handleAnswer(session: Session, senderSessionId: string, payload) {
private async handleAnswer(session: Session, senderSessionId: string, payload): Promise<void> {
if(this.webRtcServerHelper) {
await this.webRtcServerHelper.setAnswerToSubscription(senderSessionId, session.getId(), payload.sdp);
} else {
@ -242,53 +242,53 @@ export class SessionManager {
}
}
private onUserMessage({ userId, data }) {
private onUserMessage({ userId, data }: { userId: string, data }): void {
const sessions = this.getSessionsForUserId(userId);
sessions.forEach((session) => {
session.sendSocketMessage(data);
});
}
private onRoomMessage({ roomId, data }) {
private onRoomMessage({ roomId, data }: { roomId: string, data }): void {
const sessions = this.getSessionsForRoomId(roomId);
sessions.forEach((session) => {
session.sendSocketMessage(data);
});
}
private log(message: string, data?: any) {
private log(message: string, data?: any): void {
console.log(`SESSION MANAGER: ${message}`, data || '');
}
}
interface ConstructorServices {
webRtcServerHelper?: AbstractWebRtcServerHelper;
roomApiHandler: RoomApiHandler;
interface IConstructorServices {
webRtcServerHelper?: AbstractWebRtcServerHelper,
roomApiHandler: RoomApiHandler
}
interface SessionCreationData {
ncUserId?: string;
socket: WebSocket;
backendApiRequestHelper: BackendApiRequestHelper;
webRtcServerHelper?: AbstractWebRtcServerHelper;
interface ISessionCreationData {
ncUserId?: string,
socket: WebSocket,
backendApiRequestHelper: BackendApiRequestHelper,
webRtcServerHelper?: AbstractWebRtcServerHelper
}
interface RoomEventData {
interface IRoomEventData {
}
interface RoomListEventData {
roomid: string;
properties?: RoomApiRequestDataProperties; // not available in 'disinvite' message
interface IRoomListEventData {
roomid: string,
properties?: IRoomApiRequestDataProperties // not available in 'disinvite' message
}
interface ParticipantsListEventData {
interface IParticipantsListEventData {
roomid: string,
users: Array<Participant>
users: Array<IParticipant>
}
interface MessageEventData {
interface IMessageEventData {
}

87
src/classes/SignalingMessageHelper.ts

@ -19,7 +19,7 @@ export class SignalingMessageHelper {
webSocketServer.on('close', this.onDisconnect.bind(this));
}
private onConnection(socket: WebSocket) {
private onConnection(socket: WebSocket): void {
this.log('user connected...');
socket.on('message', (message: string) => {
@ -31,11 +31,11 @@ export class SignalingMessageHelper {
});
}
private onDisconnect() {
private onDisconnect(): void {
this.log('user disconnected (server)');
}
private handleMessage(socket: WebSocket, message: string) {
private handleMessage(socket: WebSocket, message: string): void {
const data: Message = JSON.parse(message);
switch(data.type) {
@ -51,7 +51,7 @@ export class SignalingMessageHelper {
}
}
private async handleHelloMessage(socket: WebSocket, data: HelloMessage) {
private async handleHelloMessage(socket: WebSocket, data: IHelloMessage): void {
this.log('HELLO:', data.hello);
if('resumeid' in data.hello) {
@ -92,7 +92,7 @@ export class SignalingMessageHelper {
const features = [];
if(this.webRtcServerHelper) features.push('mcu');
const response: HelloMessageResponse = {
const response: IHelloMessageResponse = {
id: data.id,
type: MessageType.HELLO,
hello: {
@ -125,26 +125,11 @@ export class SignalingMessageHelper {
// ********** MESSAGE ANSWER **********
private sendAnswerMessage(sender, data) {
// this._sendSocketMessage(socket, {
// type: 'message',
// message: {
// sender: sender,
// data: data
// }
// });
}
// ********** EVENTS **********
private sendSocketMessage(socket: WebSocket, data: Object) {
private sendSocketMessage(socket: WebSocket, data: Object): void {
socket.send(JSON.stringify(data));
}
private sendErrorMessage(socket: WebSocket, error, messageId?: string) {
private sendErrorMessage(socket: WebSocket, error, messageId?: string): void {
const errorMessageData = {
id: messageId,
type: 'error',
@ -153,65 +138,65 @@ export class SignalingMessageHelper {
this.sendSocketMessage(socket, errorMessageData);
}
private log(message: string, data?: any) {
private log(message: string, data?: any): void {
console.log(`SIGNALING: ${message}`, data || '');
}
}
interface MessageCommon {
id: string
interface IMessageCommon {
id: string,
type: MessageType
}
type Message = HelloMessage|ByeMessage;
type Message = IHelloMessage|IByeMessage;
interface HelloMessage extends MessageCommon {
type: MessageType.HELLO
interface IHelloMessage extends IMessageCommon {
type: MessageType.HELLO,
hello: HelloMessageData
}
type HelloMessageData = ResumeHelloMessageData | AuthHelloMessageData;
type HelloMessageData = IResumeHelloMessageData | IAuthHelloMessageData;
interface ResumeHelloMessageData {
version: '1.0';
resumeid: string;
interface IResumeHelloMessageData {
version: '1.0',
resumeid: string
}
interface AuthHelloMessageData {
version: '1.0';
auth: AuthMessageData;
interface IAuthHelloMessageData {
version: '1.0',
auth: IAuthMessageData
}
interface AuthMessageData {
url: string;
params: AuthParams;
interface IAuthMessageData {
url: string,
params: AuthParams
}
interface HelloMessageResponse {
id: string
type: MessageType.HELLO
hello: HelloMessageResponseData
interface IHelloMessageResponse {
id: string,
type: MessageType.HELLO,
hello: IHelloMessageResponseData
}
interface HelloMessageResponseData {
sessionid: string
resumeid: string
userid?: string
version: '1.0'
interface IHelloMessageResponseData {
sessionid: string,
resumeid: string,
userid?: string,
version: '1.0',
server: {
features: Array<string>
}
}
interface ByeMessage extends MessageCommon {
interface IByeMessage extends IMessageCommon {
type: MessageType.BYE,
bye: {}
}
interface ByeMessageResponse {
id: string;
type: MessageType.BYE;
interface IByeMessageResponse {
id: string,
type: MessageType.BYE,
bye: {}
}

40
src/classes/WebRtcServerHelpers/JanusWebRtcServerHelper.ts

@ -4,9 +4,9 @@ export class JanusWebRtcServerHelper implements AbstractWebRtcServerHelper {
private janusClient: Janus;
private sessions: Map<number, Session> = new Map();
private sessions: Map<number, ISession> = new Map();
constructor(options: JanusOptions) {
constructor(options: IJanusOptions) {
this.janusClient = new Janus(options);
this.janusClient.onConnected(this.onConnectedHandler.bind(this));
@ -18,28 +18,28 @@ export class JanusWebRtcServerHelper implements AbstractWebRtcServerHelper {
this.connect();
}
private onConnectedHandler() {
private onConnectedHandler(): void {
console.log('Janus: connected');
}
private onDisconnectedHandler() {
private onDisconnectedHandler(): void {
console.log('Janus: disconnected, reconnecting...');
this.connect();
}
private onErrorHandler() {
private onErrorHandler(): void {
throw new Error('Janus: could not connect!');
}
private onEventHandler(event) {
private onEventHandler(event): void {
console.log('JANUS EVENT:', event);
}
private connect() {
private connect(): void {
this.janusClient.connect();
}
async createSession(): Promise<string> {
public async createSession(): Promise<string> {
const session = await this.janusClient.createSession();
this.sessions.set(session.getId(), {
janusSession: session,
@ -49,7 +49,7 @@ export class JanusWebRtcServerHelper implements AbstractWebRtcServerHelper {
return session.getId().toFixed();
}
async destroySession(sessionId: string): Promise<void> {
public async destroySession(sessionId: string): Promise<void> {
return await this.janusClient.destroySession(Number(sessionId));
}
@ -100,7 +100,7 @@ export class JanusWebRtcServerHelper implements AbstractWebRtcServerHelper {
defaultHandle.destroy({ room: roomInfo.room });
}
async publishInRoom(sessionId: string, roomId: string, offerSdp: string) {
public async publishInRoom(sessionId: string, roomId: string, offerSdp: string): Promise<string> {
const session = this.getSession(sessionId);
const room = await this.getRoomInfo(sessionId, roomId);
@ -112,7 +112,7 @@ export class JanusWebRtcServerHelper implements AbstractWebRtcServerHelper {
return publisherHandle.getAnswer();
}
async getFeedsOfRoom(sessionId: string, roomId: string) {
private async getFeedsOfRoom(sessionId: string, roomId: string): Promise<Array<number>> {
const session = this.getSession(sessionId);
const room = await this.getRoomInfo(sessionId, roomId);
@ -121,7 +121,7 @@ export class JanusWebRtcServerHelper implements AbstractWebRtcServerHelper {
return await session.janusSession.videoRoom().getFeeds(room.room);
}
async subscribeToFeedOfRoom(sessionId: string, roomId: string, sessionIdToSubscribe: string) {
public async subscribeToFeedOfRoom(sessionId: string, roomId: string, sessionIdToSubscribe: string): Promise<string> {
const session = this.getSession(sessionId);
const room = await this.getRoomInfo(sessionId, roomId);
@ -136,7 +136,7 @@ export class JanusWebRtcServerHelper implements AbstractWebRtcServerHelper {
return listenerHandle.getOffer();
}
async setAnswerToSubscription(sessionId: string, sessionIdToSubscribe: string, answerSdp: string) {
public async setAnswerToSubscription(sessionId: string, sessionIdToSubscribe: string, answerSdp: string): Promise<void> {
const session = this.getSession(sessionId);
const feedId = this.getFeedIdFromSessionId(sessionIdToSubscribe);
if(!feedId) throw new Error('feed does not exist!');
@ -154,7 +154,7 @@ export class JanusWebRtcServerHelper implements AbstractWebRtcServerHelper {
}
}
async unsubscribe(sessionId: string, sessionIdToUnsubscribe: string) {
public async unsubscribe(sessionId: string, sessionIdToUnsubscribe: string): Promise<void> {
const session = this.getSession(sessionId);
const feedId = this.getFeedIdFromSessionId(sessionIdToUnsubscribe);
if(!feedId) throw new Error('feed does not exist');
@ -178,7 +178,7 @@ export class JanusWebRtcServerHelper implements AbstractWebRtcServerHelper {
handle.trickleCompleted();
}
private getSession(sessionId: string): Session {
private getSession(sessionId: string): ISession {
const session = this.sessions.get(Number(sessionId));
if(!session) throw new SessionError();
@ -197,13 +197,13 @@ export class JanusWebRtcServerHelper implements AbstractWebRtcServerHelper {
}
interface Session {
janusSession: JanusSession;
publisherHandle: VideoRoomPluginPublisherHandle|null;
interface ISession {
janusSession: JanusSession,
publisherHandle: VideoRoomPluginPublisherHandle|null,
listenerHandles: Map<number, VideoRoomPluginListenerHandle>
}
interface JanusOptions {
interface IJanusOptions {
url: string,
apiSecret: string|null
}
@ -222,7 +222,7 @@ class RoomError extends Error {
this._roomId = roomId;
}
getRoomId() {
public getRoomId(): string {
return this._roomId;
}

1
tsconfig.json

@ -1,7 +1,6 @@
{
"compilerOptions": {
"outDir": "dist",
"allowJs": true,
"target": "ES6",
"sourceMap": true,
"module": "CommonJS",

Loading…
Cancel
Save