148 lines
3.4 KiB
TypeScript
148 lines
3.4 KiB
TypeScript
import { Channel } from '@supabase/phoenix'
|
|
import { CHANNEL_STATES, MAX_PUSH_BUFFER_SIZE } from '../lib/constants'
|
|
import type { RealtimeChannelOptions } from '../RealtimeChannel'
|
|
import SocketAdapter from './socketAdapter'
|
|
import type {
|
|
ChannelBindingCallback,
|
|
ChannelOnMessage,
|
|
ChannelOnErrorCallback,
|
|
ChannelFilterBindings,
|
|
Params,
|
|
ChannelState,
|
|
Push,
|
|
Timer,
|
|
} from './types'
|
|
|
|
export default class ChannelAdapter {
|
|
private channel: Channel
|
|
private socket: SocketAdapter
|
|
|
|
constructor(socket: SocketAdapter, topic: string, params: RealtimeChannelOptions) {
|
|
const phoenixParams = phoenixChannelParams(params)
|
|
this.channel = socket.getSocket().channel(topic, phoenixParams)
|
|
this.socket = socket
|
|
}
|
|
|
|
get state(): ChannelState {
|
|
return this.channel.state
|
|
}
|
|
|
|
set state(state: ChannelState) {
|
|
this.channel.state = state
|
|
}
|
|
|
|
get joinedOnce(): boolean {
|
|
return this.channel.joinedOnce
|
|
}
|
|
|
|
get joinPush(): Push {
|
|
return this.channel.joinPush
|
|
}
|
|
|
|
get rejoinTimer(): Timer {
|
|
return this.channel.rejoinTimer
|
|
}
|
|
|
|
on(event: string, callback: ChannelBindingCallback): number {
|
|
return this.channel.on(event, callback)
|
|
}
|
|
|
|
off(event: string, refNumber?: number) {
|
|
this.channel.off(event, refNumber)
|
|
}
|
|
|
|
subscribe(timeout?: number): Push {
|
|
return this.channel.join(timeout)
|
|
}
|
|
|
|
unsubscribe(timeout?: number): Push {
|
|
return this.channel.leave(timeout)
|
|
}
|
|
|
|
teardown() {
|
|
this.channel.teardown()
|
|
}
|
|
|
|
onClose(callback: ChannelBindingCallback) {
|
|
this.channel.onClose(callback)
|
|
}
|
|
|
|
onError(callback: ChannelOnErrorCallback): number {
|
|
return this.channel.onError(callback)
|
|
}
|
|
|
|
push(event: string, payload: { [key: string]: any }, timeout?: number): Push {
|
|
let push: Push
|
|
|
|
try {
|
|
push = this.channel.push(event, payload, timeout)
|
|
} catch (error) {
|
|
throw `tried to push '${event}' to '${this.channel.topic}' before joining. Use channel.subscribe() before pushing events`
|
|
}
|
|
|
|
if (this.channel.pushBuffer.length > MAX_PUSH_BUFFER_SIZE) {
|
|
const removedPush = this.channel.pushBuffer.shift()!
|
|
removedPush.cancelTimeout()
|
|
this.socket.log(
|
|
'channel',
|
|
`discarded push due to buffer overflow: ${removedPush.event}`,
|
|
removedPush.payload()
|
|
)
|
|
}
|
|
return push
|
|
}
|
|
|
|
updateJoinPayload(payload: Record<string, any>) {
|
|
const oldPayload = this.channel.joinPush.payload()
|
|
this.channel.joinPush.payload = () => ({ ...oldPayload, ...payload })
|
|
}
|
|
|
|
canPush() {
|
|
return this.socket.isConnected() && this.state === CHANNEL_STATES.joined
|
|
}
|
|
|
|
isJoined() {
|
|
return this.state === CHANNEL_STATES.joined
|
|
}
|
|
|
|
isJoining() {
|
|
return this.state === CHANNEL_STATES.joining
|
|
}
|
|
|
|
isClosed() {
|
|
return this.state === CHANNEL_STATES.closed
|
|
}
|
|
|
|
isLeaving() {
|
|
return this.state === CHANNEL_STATES.leaving
|
|
}
|
|
|
|
updateFilterBindings(filterBindings: ChannelFilterBindings) {
|
|
this.channel.filterBindings = filterBindings
|
|
}
|
|
|
|
updatePayloadTransform(callback: ChannelOnMessage) {
|
|
this.channel.onMessage = callback
|
|
}
|
|
|
|
/**
|
|
* @internal
|
|
*/
|
|
getChannel() {
|
|
return this.channel
|
|
}
|
|
}
|
|
|
|
function phoenixChannelParams(options: RealtimeChannelOptions): Params {
|
|
return {
|
|
config: {
|
|
...{
|
|
broadcast: { ack: false, self: false },
|
|
presence: { key: '', enabled: false },
|
|
private: false,
|
|
},
|
|
...options.config,
|
|
},
|
|
}
|
|
}
|