Use TypedEmitter for client socket connections
This commit is contained in:
parent
703c13f296
commit
7fa09fa6b8
@ -46,7 +46,7 @@ describe('CallActions', () => {
|
|||||||
|
|
||||||
it('calls handshake.init when connected & got camera stream', async () => {
|
it('calls handshake.init when connected & got camera stream', async () => {
|
||||||
const promise = callActions.init()
|
const promise = callActions.init()
|
||||||
socket.emit('connect')
|
socket.emit('connect', undefined)
|
||||||
await promise
|
await promise
|
||||||
expect(store.getState().allActions.slice(1)).toEqual([{
|
expect(store.getState().allActions.slice(1)).toEqual([{
|
||||||
type: constants.NOTIFY,
|
type: constants.NOTIFY,
|
||||||
@ -73,8 +73,8 @@ describe('CallActions', () => {
|
|||||||
|
|
||||||
it('calls dispatches disconnect message on disconnect', async () => {
|
it('calls dispatches disconnect message on disconnect', async () => {
|
||||||
const promise = callActions.init()
|
const promise = callActions.init()
|
||||||
socket.emit('connect')
|
socket.emit('connect', undefined)
|
||||||
socket.emit('disconnect')
|
socket.emit('disconnect', undefined)
|
||||||
expect(store.getState().allActions.slice(1)).toEqual([{
|
expect(store.getState().allActions.slice(1)).toEqual([{
|
||||||
type: constants.NOTIFY,
|
type: constants.NOTIFY,
|
||||||
payload: {
|
payload: {
|
||||||
@ -96,7 +96,7 @@ describe('CallActions', () => {
|
|||||||
it('dispatches alert when failed to get media stream', async () => {
|
it('dispatches alert when failed to get media stream', async () => {
|
||||||
(getUserMedia as any).fail(true)
|
(getUserMedia as any).fail(true)
|
||||||
const promise = callActions.init()
|
const promise = callActions.init()
|
||||||
socket.emit('connect')
|
socket.emit('connect', undefined)
|
||||||
await promise
|
await promise
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@ -2,6 +2,7 @@ import * as constants from '../constants'
|
|||||||
import socket from '../socket'
|
import socket from '../socket'
|
||||||
import { Dispatch, ThunkResult } from '../store'
|
import { Dispatch, ThunkResult } from '../store'
|
||||||
import { callId, getUserMedia } from '../window'
|
import { callId, getUserMedia } from '../window'
|
||||||
|
import { ClientSocket } from '../socket'
|
||||||
import * as NotifyActions from './NotifyActions'
|
import * as NotifyActions from './NotifyActions'
|
||||||
import * as SocketActions from './SocketActions'
|
import * as SocketActions from './SocketActions'
|
||||||
import * as StreamActions from './StreamActions'
|
import * as StreamActions from './StreamActions'
|
||||||
@ -34,7 +35,7 @@ async (dispatch, getState) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const connect = () => (dispatch: Dispatch) => {
|
export const connect = () => (dispatch: Dispatch) => {
|
||||||
return new Promise<SocketIOClient.Socket>(resolve => {
|
return new Promise<ClientSocket>(resolve => {
|
||||||
socket.once('connect', () => {
|
socket.once('connect', () => {
|
||||||
resolve(socket)
|
resolve(socket)
|
||||||
})
|
})
|
||||||
|
|||||||
@ -7,15 +7,16 @@ import { EventEmitter } from 'events'
|
|||||||
import { createStore, Store, GetState } from '../store'
|
import { createStore, Store, GetState } from '../store'
|
||||||
import { play } from '../window'
|
import { play } from '../window'
|
||||||
import { Dispatch } from 'redux'
|
import { Dispatch } from 'redux'
|
||||||
|
import { ClientSocket } from '../socket'
|
||||||
|
|
||||||
describe('PeerActions', () => {
|
describe('PeerActions', () => {
|
||||||
function createSocket () {
|
function createSocket () {
|
||||||
const socket = new EventEmitter() as unknown as SocketIOClient.Socket
|
const socket = new EventEmitter() as unknown as ClientSocket
|
||||||
socket.id = 'user1'
|
socket.id = 'user1'
|
||||||
return socket
|
return socket
|
||||||
}
|
}
|
||||||
|
|
||||||
let socket: SocketIOClient.Socket
|
let socket: ClientSocket
|
||||||
let stream: MediaStream
|
let stream: MediaStream
|
||||||
let user: { id: string }
|
let user: { id: string }
|
||||||
let store: Store
|
let store: Store
|
||||||
|
|||||||
@ -7,6 +7,7 @@ import forEach from 'lodash/forEach'
|
|||||||
import _debug from 'debug'
|
import _debug from 'debug'
|
||||||
import { play, iceServers } from '../window'
|
import { play, iceServers } from '../window'
|
||||||
import { Dispatch, GetState } from '../store'
|
import { Dispatch, GetState } from '../store'
|
||||||
|
import { ClientSocket } from '../socket'
|
||||||
|
|
||||||
const debug = _debug('peercalls')
|
const debug = _debug('peercalls')
|
||||||
|
|
||||||
@ -15,14 +16,14 @@ export interface Peers {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface PeerHandlerOptions {
|
export interface PeerHandlerOptions {
|
||||||
socket: SocketIOClient.Socket
|
socket: ClientSocket
|
||||||
user: { id: string }
|
user: { id: string }
|
||||||
dispatch: Dispatch
|
dispatch: Dispatch
|
||||||
getState: GetState
|
getState: GetState
|
||||||
}
|
}
|
||||||
|
|
||||||
class PeerHandler {
|
class PeerHandler {
|
||||||
socket: SocketIOClient.Socket
|
socket: ClientSocket
|
||||||
user: { id: string }
|
user: { id: string }
|
||||||
dispatch: Dispatch
|
dispatch: Dispatch
|
||||||
getState: GetState
|
getState: GetState
|
||||||
@ -94,7 +95,7 @@ class PeerHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface CreatePeerOptions {
|
export interface CreatePeerOptions {
|
||||||
socket: SocketIOClient.Socket
|
socket: ClientSocket
|
||||||
user: { id: string }
|
user: { id: string }
|
||||||
initiator: string
|
initiator: string
|
||||||
stream?: MediaStream
|
stream?: MediaStream
|
||||||
|
|||||||
@ -6,12 +6,13 @@ import * as constants from '../constants'
|
|||||||
import Peer from 'simple-peer'
|
import Peer from 'simple-peer'
|
||||||
import { EventEmitter } from 'events'
|
import { EventEmitter } from 'events'
|
||||||
import { createStore, Store, GetState } from '../store'
|
import { createStore, Store, GetState } from '../store'
|
||||||
|
import { ClientSocket } from '../socket'
|
||||||
import { Dispatch } from 'redux'
|
import { Dispatch } from 'redux'
|
||||||
|
|
||||||
describe('SocketActions', () => {
|
describe('SocketActions', () => {
|
||||||
const roomName = 'bla'
|
const roomName = 'bla'
|
||||||
|
|
||||||
let socket: SocketIOClient.Socket
|
let socket: ClientSocket
|
||||||
let store: Store
|
let store: Store
|
||||||
let dispatch: Dispatch
|
let dispatch: Dispatch
|
||||||
let getState: GetState
|
let getState: GetState
|
||||||
@ -67,7 +68,7 @@ describe('SocketActions', () => {
|
|||||||
it('should forward signal to peer', () => {
|
it('should forward signal to peer', () => {
|
||||||
socket.emit('signal', {
|
socket.emit('signal', {
|
||||||
userId: 'b',
|
userId: 'b',
|
||||||
data,
|
signal: data,
|
||||||
})
|
})
|
||||||
|
|
||||||
expect(instances.length).toBe(1)
|
expect(instances.length).toBe(1)
|
||||||
@ -77,7 +78,7 @@ describe('SocketActions', () => {
|
|||||||
it('does nothing if no peer', () => {
|
it('does nothing if no peer', () => {
|
||||||
socket.emit('signal', {
|
socket.emit('signal', {
|
||||||
userId: 'a',
|
userId: 'a',
|
||||||
data,
|
signal: data,
|
||||||
})
|
})
|
||||||
|
|
||||||
expect(instances.length).toBe(1)
|
expect(instances.length).toBe(1)
|
||||||
|
|||||||
@ -5,11 +5,12 @@ import keyBy from 'lodash/keyBy'
|
|||||||
import _debug from 'debug'
|
import _debug from 'debug'
|
||||||
import { SignalData } from 'simple-peer'
|
import { SignalData } from 'simple-peer'
|
||||||
import { Dispatch, GetState } from '../store'
|
import { Dispatch, GetState } from '../store'
|
||||||
|
import { ClientSocket } from '../socket'
|
||||||
|
|
||||||
const debug = _debug('peercalls')
|
const debug = _debug('peercalls')
|
||||||
|
|
||||||
export interface SocketHandlerOptions {
|
export interface SocketHandlerOptions {
|
||||||
socket: SocketIOClient.Socket
|
socket: ClientSocket
|
||||||
roomName: string
|
roomName: string
|
||||||
stream?: MediaStream
|
stream?: MediaStream
|
||||||
dispatch: Dispatch
|
dispatch: Dispatch
|
||||||
@ -27,7 +28,7 @@ export interface UsersOptions {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class SocketHandler {
|
class SocketHandler {
|
||||||
socket: SocketIOClient.Socket
|
socket: ClientSocket
|
||||||
roomName: string
|
roomName: string
|
||||||
stream?: MediaStream
|
stream?: MediaStream
|
||||||
dispatch: Dispatch
|
dispatch: Dispatch
|
||||||
@ -70,7 +71,7 @@ class SocketHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface HandshakeOptions {
|
export interface HandshakeOptions {
|
||||||
socket: SocketIOClient.Socket
|
socket: ClientSocket
|
||||||
roomName: string
|
roomName: string
|
||||||
stream?: MediaStream
|
stream?: MediaStream
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,3 +1,7 @@
|
|||||||
import SocketIOClient from 'socket.io-client'
|
import SocketIOClient from 'socket.io-client'
|
||||||
import { baseUrl } from './window'
|
import { baseUrl } from './window'
|
||||||
export default SocketIOClient('', { path: baseUrl + '/ws' })
|
import { TypedEmitterKeys, SocketEvent, TypedEmitter } from '../shared'
|
||||||
|
export type ClientSocket = Omit<SocketIOClient.Socket, TypedEmitterKeys> &
|
||||||
|
TypedEmitter<SocketEvent>
|
||||||
|
const socket: ClientSocket = SocketIOClient('', { path: baseUrl + '/ws' })
|
||||||
|
export default socket
|
||||||
|
|||||||
@ -11,10 +11,11 @@ export interface SocketEvent {
|
|||||||
}
|
}
|
||||||
signal: {
|
signal: {
|
||||||
userId: string
|
userId: string
|
||||||
signal: unknown
|
// eslint-disable-next-line
|
||||||
|
signal: any
|
||||||
}
|
}
|
||||||
connect: void
|
connect: undefined
|
||||||
disconnect: void
|
disconnect: undefined
|
||||||
ready: string
|
ready: string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -38,12 +38,12 @@ describe('TypedEmitter', () => {
|
|||||||
let emitter: TypedEmitter<Events>
|
let emitter: TypedEmitter<Events>
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
emitter = new EventEmitter()
|
emitter = new EventEmitter()
|
||||||
emitter.addListener('test1', listener1)
|
emitter.on('test1', listener1)
|
||||||
emitter.on('test2', listener2)
|
emitter.on('test2', listener2)
|
||||||
emitter.once('test3', listener3)
|
emitter.once('test3', listener3)
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('addListener & on', () => {
|
describe('on & on', () => {
|
||||||
it('adds an event emitter', () => {
|
it('adds an event emitter', () => {
|
||||||
emitter.emit('test1', 'value')
|
emitter.emit('test1', 'value')
|
||||||
emitter.emit('test2', 3)
|
emitter.emit('test2', 3)
|
||||||
|
|||||||
@ -1,21 +1,19 @@
|
|||||||
import { EventEmitter } from 'events'
|
|
||||||
|
|
||||||
type Callback<A> = (a: A) => void
|
type Callback<A> = (a: A) => void
|
||||||
|
|
||||||
// eslint-disable-next-line
|
// eslint-disable-next-line
|
||||||
type Events = Record<string | symbol, any>
|
type Events = Record<string | symbol, any>
|
||||||
|
|
||||||
export type TypedEmitterKeys =
|
export type TypedEmitterKeys =
|
||||||
'addListener' |
|
|
||||||
'removeListener' |
|
'removeListener' |
|
||||||
'on' |
|
'on' |
|
||||||
'once' |
|
'once' |
|
||||||
'off' |
|
'off' |
|
||||||
'emit'
|
'emit'
|
||||||
|
|
||||||
export interface TypedEmitter<E extends Events>
|
// Some methods might be missing and we do not extend EventEmitter because
|
||||||
extends EventEmitter {
|
// SocketIOClient.Socket does not inherit from EventEmitter, and the method
|
||||||
addListener<K extends keyof E>(t: K, callback: Callback<E[K]>): this
|
// signatures differ slightly.
|
||||||
|
export interface TypedEmitter<E extends Events> {
|
||||||
removeListener<K extends keyof E>(t: K, callback: Callback<E[K]>): this
|
removeListener<K extends keyof E>(t: K, callback: Callback<E[K]>): this
|
||||||
|
|
||||||
on<K extends keyof E>(t: K, callback: Callback<E[K]>): this
|
on<K extends keyof E>(t: K, callback: Callback<E[K]>): this
|
||||||
@ -23,5 +21,5 @@ extends EventEmitter {
|
|||||||
|
|
||||||
off<K extends keyof E>(t: K, callback: Callback<E[K]>): this
|
off<K extends keyof E>(t: K, callback: Callback<E[K]>): this
|
||||||
|
|
||||||
emit<K extends keyof E>(t: K, value: E[K]): boolean
|
emit<K extends keyof E>(t: K, value: E[K]): void
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user