From e8491aa89775db6429df7142f935c1cd4695f1ed Mon Sep 17 00:00:00 2001 From: Dennis Prudlo Date: Sun, 3 Nov 2024 22:04:46 +0100 Subject: [PATCH] Fix types for the echo library (#403) * Fix wrong channel types * Add generic types * Throw an error when attempting to use encrypted channels with socket.io * Fix types for the function broadcaster * Add generic to channel types * Fix function types * Make connectors generic * Remove new keyword for function broadcasters * Fix tests * Specify return type for function broadcasters * Clean up generics * Remove unnecessary cast * Update quotes * Use NullChannel return type explicitly --- src/channel/channel.ts | 14 ++-- src/channel/index.ts | 1 + src/channel/null-channel.ts | 12 +-- src/channel/null-encrypted-private-channel.ts | 13 +++ src/channel/null-presence-channel.ts | 12 +-- src/channel/null-private-channel.ts | 2 +- src/channel/presence-channel.ts | 8 +- src/channel/pusher-channel.ts | 14 ++-- .../pusher-encrypted-private-channel.ts | 2 +- src/channel/pusher-presence-channel.ts | 12 +-- src/channel/pusher-private-channel.ts | 2 +- src/channel/socketio-channel.ts | 10 +-- src/channel/socketio-presence-channel.ts | 8 +- src/channel/socketio-private-channel.ts | 2 +- src/connector/connector.ts | 10 +-- src/connector/null-connector.ts | 10 +-- src/connector/pusher-connector.ts | 22 +++--- src/connector/socketio-connector.ts | 8 +- src/echo.ts | 79 ++++++++++++++++--- tests/echo.test.ts | 2 + 20 files changed, 157 insertions(+), 86 deletions(-) create mode 100644 src/channel/null-encrypted-private-channel.ts diff --git a/src/channel/channel.ts b/src/channel/channel.ts index 4cb441a6..aeb3b03b 100644 --- a/src/channel/channel.ts +++ b/src/channel/channel.ts @@ -10,41 +10,41 @@ export abstract class Channel { /** * Listen for an event on the channel instance. */ - abstract listen(event: string, callback: Function): Channel; + abstract listen(event: string, callback: Function): this; /** * Listen for a whisper event on the channel instance. */ - listenForWhisper(event: string, callback: Function): Channel { + listenForWhisper(event: string, callback: Function): this { return this.listen('.client-' + event, callback); } /** * Listen for an event on the channel instance. */ - notification(callback: Function): Channel { + notification(callback: Function): this { return this.listen('.Illuminate\\Notifications\\Events\\BroadcastNotificationCreated', callback); } /** * Stop listening to an event on the channel instance. */ - abstract stopListening(event: string, callback?: Function): Channel; + abstract stopListening(event: string, callback?: Function): this; /** * Stop listening for a whisper event on the channel instance. */ - stopListeningForWhisper(event: string, callback?: Function): Channel { + stopListeningForWhisper(event: string, callback?: Function): this { return this.stopListening('.client-' + event, callback); } /** * Register a callback to be called anytime a subscription succeeds. */ - abstract subscribed(callback: Function): Channel; + abstract subscribed(callback: Function): this; /** * Register a callback to be called anytime an error occurs. */ - abstract error(callback: Function): Channel; + abstract error(callback: Function): this; } diff --git a/src/channel/index.ts b/src/channel/index.ts index 2e719848..668f6385 100644 --- a/src/channel/index.ts +++ b/src/channel/index.ts @@ -9,4 +9,5 @@ export * from './socketio-private-channel'; export * from './socketio-presence-channel'; export * from './null-channel'; export * from './null-private-channel'; +export * from './null-encrypted-private-channel'; export * from './null-presence-channel'; diff --git a/src/channel/null-channel.ts b/src/channel/null-channel.ts index c1db4783..e79b1fa4 100644 --- a/src/channel/null-channel.ts +++ b/src/channel/null-channel.ts @@ -21,42 +21,42 @@ export class NullChannel extends Channel { /** * Listen for an event on the channel instance. */ - listen(event: string, callback: Function): NullChannel { + listen(event: string, callback: Function): this { return this; } /** * Listen for all events on the channel instance. */ - listenToAll(callback: Function): NullChannel { + listenToAll(callback: Function): this { return this; } /** * Stop listening for an event on the channel instance. */ - stopListening(event: string, callback?: Function): NullChannel { + stopListening(event: string, callback?: Function): this { return this; } /** * Register a callback to be called anytime a subscription succeeds. */ - subscribed(callback: Function): NullChannel { + subscribed(callback: Function): this { return this; } /** * Register a callback to be called anytime an error occurs. */ - error(callback: Function): NullChannel { + error(callback: Function): this { return this; } /** * Bind a channel to an event. */ - on(event: string, callback: Function): NullChannel { + on(event: string, callback: Function): this { return this; } } diff --git a/src/channel/null-encrypted-private-channel.ts b/src/channel/null-encrypted-private-channel.ts new file mode 100644 index 00000000..fc918117 --- /dev/null +++ b/src/channel/null-encrypted-private-channel.ts @@ -0,0 +1,13 @@ +import { NullChannel } from './null-channel'; + +/** + * This class represents a null private channel. + */ +export class NullEncryptedPrivateChannel extends NullChannel { + /** + * Send a whisper event to other clients in the channel. + */ + whisper(eventName: string, data: any): this { + return this; + } +} diff --git a/src/channel/null-presence-channel.ts b/src/channel/null-presence-channel.ts index 18ca9b94..7bf64cb9 100644 --- a/src/channel/null-presence-channel.ts +++ b/src/channel/null-presence-channel.ts @@ -1,35 +1,35 @@ -import { NullChannel } from './null-channel'; +import { NullPrivateChannel } from './null-private-channel'; import { PresenceChannel } from './presence-channel'; /** * This class represents a null presence channel. */ -export class NullPresenceChannel extends NullChannel implements PresenceChannel { +export class NullPresenceChannel extends NullPrivateChannel implements PresenceChannel { /** * Register a callback to be called anytime the member list changes. */ - here(callback: Function): NullPresenceChannel { + here(callback: Function): this { return this; } /** * Listen for someone joining the channel. */ - joining(callback: Function): NullPresenceChannel { + joining(callback: Function): this { return this; } /** * Send a whisper event to other clients in the channel. */ - whisper(eventName: string, data: any): NullPresenceChannel { + whisper(eventName: string, data: any): this { return this; } /** * Listen for someone leaving the channel. */ - leaving(callback: Function): NullPresenceChannel { + leaving(callback: Function): this { return this; } } diff --git a/src/channel/null-private-channel.ts b/src/channel/null-private-channel.ts index e6221779..862ac5c2 100644 --- a/src/channel/null-private-channel.ts +++ b/src/channel/null-private-channel.ts @@ -7,7 +7,7 @@ export class NullPrivateChannel extends NullChannel { /** * Send a whisper event to other clients in the channel. */ - whisper(eventName: string, data: any): NullPrivateChannel { + whisper(eventName: string, data: any): this { return this; } } diff --git a/src/channel/presence-channel.ts b/src/channel/presence-channel.ts index 1b0ec302..2b2063e2 100644 --- a/src/channel/presence-channel.ts +++ b/src/channel/presence-channel.ts @@ -7,20 +7,20 @@ export interface PresenceChannel extends Channel { /** * Register a callback to be called anytime the member list changes. */ - here(callback: Function): PresenceChannel; + here(callback: Function): this; /** * Listen for someone joining the channel. */ - joining(callback: Function): PresenceChannel; + joining(callback: Function): this; /** * Send a whisper event to other clients in the channel. */ - whisper(eventName: string, data: any): PresenceChannel; + whisper(eventName: string, data: any): this; /** * Listen for someone leaving the channel. */ - leaving(callback: Function): PresenceChannel; + leaving(callback: Function): this; } diff --git a/src/channel/pusher-channel.ts b/src/channel/pusher-channel.ts index e59606fb..07234239 100644 --- a/src/channel/pusher-channel.ts +++ b/src/channel/pusher-channel.ts @@ -61,7 +61,7 @@ export class PusherChannel extends Channel { /** * Listen for an event on the channel instance. */ - listen(event: string, callback: Function): PusherChannel { + listen(event: string, callback: Function): this { this.on(this.eventFormatter.format(event), callback); return this; @@ -70,7 +70,7 @@ export class PusherChannel extends Channel { /** * Listen for all events on the channel instance. */ - listenToAll(callback: Function): PusherChannel { + listenToAll(callback: Function): this { this.subscription.bind_global((event, data) => { if (event.startsWith('pusher:')) { return; @@ -89,7 +89,7 @@ export class PusherChannel extends Channel { /** * Stop listening for an event on the channel instance. */ - stopListening(event: string, callback?: Function): PusherChannel { + stopListening(event: string, callback?: Function): this { if (callback) { this.subscription.unbind(this.eventFormatter.format(event), callback); } else { @@ -102,7 +102,7 @@ export class PusherChannel extends Channel { /** * Stop listening for all events on the channel instance. */ - stopListeningToAll(callback?: Function): PusherChannel { + stopListeningToAll(callback?: Function): this { if (callback) { this.subscription.unbind_global(callback); } else { @@ -115,7 +115,7 @@ export class PusherChannel extends Channel { /** * Register a callback to be called anytime a subscription succeeds. */ - subscribed(callback: Function): PusherChannel { + subscribed(callback: Function): this { this.on('pusher:subscription_succeeded', () => { callback(); }); @@ -126,7 +126,7 @@ export class PusherChannel extends Channel { /** * Register a callback to be called anytime a subscription error occurs. */ - error(callback: Function): PusherChannel { + error(callback: Function): this { this.on('pusher:subscription_error', (status) => { callback(status); }); @@ -137,7 +137,7 @@ export class PusherChannel extends Channel { /** * Bind a channel to an event. */ - on(event: string, callback: Function): PusherChannel { + on(event: string, callback: Function): this { this.subscription.bind(event, callback); return this; diff --git a/src/channel/pusher-encrypted-private-channel.ts b/src/channel/pusher-encrypted-private-channel.ts index edc82c4c..299e8da9 100644 --- a/src/channel/pusher-encrypted-private-channel.ts +++ b/src/channel/pusher-encrypted-private-channel.ts @@ -7,7 +7,7 @@ export class PusherEncryptedPrivateChannel extends PusherChannel { /** * Send a whisper event to other clients in the channel. */ - whisper(eventName: string, data: any): PusherEncryptedPrivateChannel { + whisper(eventName: string, data: any): this { this.pusher.channels.channels[this.name].trigger(`client-${eventName}`, data); return this; diff --git a/src/channel/pusher-presence-channel.ts b/src/channel/pusher-presence-channel.ts index 7c70c523..a1fc8cf6 100644 --- a/src/channel/pusher-presence-channel.ts +++ b/src/channel/pusher-presence-channel.ts @@ -1,14 +1,14 @@ -import { PusherChannel } from './pusher-channel'; import { PresenceChannel } from './presence-channel'; +import { PusherPrivateChannel } from './pusher-private-channel'; /** * This class represents a Pusher presence channel. */ -export class PusherPresenceChannel extends PusherChannel implements PresenceChannel { +export class PusherPresenceChannel extends PusherPrivateChannel implements PresenceChannel { /** * Register a callback to be called anytime the member list changes. */ - here(callback: Function): PusherPresenceChannel { + here(callback: Function): this { this.on('pusher:subscription_succeeded', (data) => { callback(Object.keys(data.members).map((k) => data.members[k])); }); @@ -19,7 +19,7 @@ export class PusherPresenceChannel extends PusherChannel implements PresenceChan /** * Listen for someone joining the channel. */ - joining(callback: Function): PusherPresenceChannel { + joining(callback: Function): this { this.on('pusher:member_added', (member) => { callback(member.info); }); @@ -30,7 +30,7 @@ export class PusherPresenceChannel extends PusherChannel implements PresenceChan /** * Send a whisper event to other clients in the channel. */ - whisper(eventName: string, data: any): PusherPresenceChannel { + whisper(eventName: string, data: any): this { this.pusher.channels.channels[this.name].trigger(`client-${eventName}`, data); return this; @@ -39,7 +39,7 @@ export class PusherPresenceChannel extends PusherChannel implements PresenceChan /** * Listen for someone leaving the channel. */ - leaving(callback: Function): PusherPresenceChannel { + leaving(callback: Function): this { this.on('pusher:member_removed', (member) => { callback(member.info); }); diff --git a/src/channel/pusher-private-channel.ts b/src/channel/pusher-private-channel.ts index 9158449d..7952886d 100644 --- a/src/channel/pusher-private-channel.ts +++ b/src/channel/pusher-private-channel.ts @@ -7,7 +7,7 @@ export class PusherPrivateChannel extends PusherChannel { /** * Send a whisper event to other clients in the channel. */ - whisper(eventName: string, data: any): PusherPrivateChannel { + whisper(eventName: string, data: any): this { this.pusher.channels.channels[this.name].trigger(`client-${eventName}`, data); return this; diff --git a/src/channel/socketio-channel.ts b/src/channel/socketio-channel.ts index 1911f3e4..47dc00c1 100644 --- a/src/channel/socketio-channel.ts +++ b/src/channel/socketio-channel.ts @@ -74,7 +74,7 @@ export class SocketIoChannel extends Channel { /** * Listen for an event on the channel instance. */ - listen(event: string, callback: Function): SocketIoChannel { + listen(event: string, callback: Function): this { this.on(this.eventFormatter.format(event), callback); return this; @@ -83,7 +83,7 @@ export class SocketIoChannel extends Channel { /** * Stop listening for an event on the channel instance. */ - stopListening(event: string, callback?: Function): SocketIoChannel { + stopListening(event: string, callback?: Function): this { this.unbindEvent(this.eventFormatter.format(event), callback); return this; @@ -92,7 +92,7 @@ export class SocketIoChannel extends Channel { /** * Register a callback to be called anytime a subscription succeeds. */ - subscribed(callback: Function): SocketIoChannel { + subscribed(callback: Function): this { this.on('connect', (socket) => { callback(socket); }); @@ -103,14 +103,14 @@ export class SocketIoChannel extends Channel { /** * Register a callback to be called anytime an error occurs. */ - error(callback: Function): SocketIoChannel { + error(callback: Function): this { return this; } /** * Bind the channel's socket to an event and store the callback. */ - on(event: string, callback: Function): SocketIoChannel { + on(event: string, callback: Function): this { this.listeners[event] = this.listeners[event] || []; if (!this.events[event]) { diff --git a/src/channel/socketio-presence-channel.ts b/src/channel/socketio-presence-channel.ts index 96e46dd5..cf0110fb 100644 --- a/src/channel/socketio-presence-channel.ts +++ b/src/channel/socketio-presence-channel.ts @@ -8,7 +8,7 @@ export class SocketIoPresenceChannel extends SocketIoPrivateChannel implements P /** * Register a callback to be called anytime the member list changes. */ - here(callback: Function): SocketIoPresenceChannel { + here(callback: Function): this { this.on('presence:subscribed', (members: any[]) => { callback(members.map((m) => m.user_info)); }); @@ -19,7 +19,7 @@ export class SocketIoPresenceChannel extends SocketIoPrivateChannel implements P /** * Listen for someone joining the channel. */ - joining(callback: Function): SocketIoPresenceChannel { + joining(callback: Function): this { this.on('presence:joining', (member) => callback(member.user_info)); return this; @@ -28,7 +28,7 @@ export class SocketIoPresenceChannel extends SocketIoPrivateChannel implements P /** * Send a whisper event to other clients in the channel. */ - whisper(eventName: string, data: any): SocketIoPresenceChannel { + whisper(eventName: string, data: any): this { this.socket.emit('client event', { channel: this.name, event: `client-${eventName}`, @@ -41,7 +41,7 @@ export class SocketIoPresenceChannel extends SocketIoPrivateChannel implements P /** * Listen for someone leaving the channel. */ - leaving(callback: Function): SocketIoPresenceChannel { + leaving(callback: Function): this { this.on('presence:leaving', (member) => callback(member.user_info)); return this; diff --git a/src/channel/socketio-private-channel.ts b/src/channel/socketio-private-channel.ts index 102da067..aa66ed3b 100644 --- a/src/channel/socketio-private-channel.ts +++ b/src/channel/socketio-private-channel.ts @@ -7,7 +7,7 @@ export class SocketIoPrivateChannel extends SocketIoChannel { /** * Send a whisper event to other clients in the channel. */ - whisper(eventName: string, data: any): SocketIoChannel { + whisper(eventName: string, data: any): this { this.socket.emit('client event', { channel: this.name, event: `client-${eventName}`, diff --git a/src/connector/connector.ts b/src/connector/connector.ts index fab8de5f..0291ef70 100644 --- a/src/connector/connector.ts +++ b/src/connector/connector.ts @@ -1,6 +1,6 @@ -import { Channel, PresenceChannel } from './../channel'; +import { Channel, PresenceChannel } from '../channel'; -export abstract class Connector { +export abstract class Connector { /** * Default connector options. */ @@ -86,17 +86,17 @@ export abstract class Connector { /** * Get a channel instance by name. */ - abstract channel(channel: string): Channel; + abstract channel(channel: string): TPublic; /** * Get a private channel instance by name. */ - abstract privateChannel(channel: string): Channel; + abstract privateChannel(channel: string): TPrivate; /** * Get a presence channel instance by name. */ - abstract presenceChannel(channel: string): PresenceChannel; + abstract presenceChannel(channel: string): TPresence; /** * Leave the given channel, as well as its private and presence variants. diff --git a/src/connector/null-connector.ts b/src/connector/null-connector.ts index ceb5db35..091550d4 100644 --- a/src/connector/null-connector.ts +++ b/src/connector/null-connector.ts @@ -1,10 +1,10 @@ import { Connector } from './connector'; -import { NullChannel, NullPrivateChannel, NullPresenceChannel, PresenceChannel } from './../channel'; +import { NullChannel, NullPrivateChannel, NullPresenceChannel, NullEncryptedPrivateChannel } from './../channel'; /** * This class creates a null connector. */ -export class NullConnector extends Connector { +export class NullConnector extends Connector { /** * All of the subscribed channel names. */ @@ -41,14 +41,14 @@ export class NullConnector extends Connector { /** * Get a private encrypted channel instance by name. */ - encryptedPrivateChannel(name: string): NullPrivateChannel { - return new NullPrivateChannel(); + encryptedPrivateChannel(name: string): NullEncryptedPrivateChannel { + return new NullEncryptedPrivateChannel(); } /** * Get a presence channel instance by name. */ - presenceChannel(name: string): PresenceChannel { + presenceChannel(name: string): NullPresenceChannel { return new NullPresenceChannel(); } diff --git a/src/connector/pusher-connector.ts b/src/connector/pusher-connector.ts index c50707db..121bf65e 100644 --- a/src/connector/pusher-connector.ts +++ b/src/connector/pusher-connector.ts @@ -1,16 +1,12 @@ import { Connector } from './connector'; -import { - PusherChannel, - PusherPrivateChannel, - PusherEncryptedPrivateChannel, - PusherPresenceChannel, - PresenceChannel, -} from './../channel'; +import { PusherChannel, PusherPrivateChannel, PusherEncryptedPrivateChannel, PusherPresenceChannel } from './../channel'; + +type AnyPusherChannel = PusherChannel | PusherPrivateChannel | PusherEncryptedPrivateChannel | PusherPresenceChannel; /** * This class creates a connector to Pusher. */ -export class PusherConnector extends Connector { +export class PusherConnector extends Connector { /** * The Pusher instance. */ @@ -44,14 +40,14 @@ export class PusherConnector extends Connector { /** * Listen for an event on a channel instance. */ - listen(name: string, event: string, callback: Function): PusherChannel { + listen(name: string, event: string, callback: Function): AnyPusherChannel { return this.channel(name).listen(event, callback); } /** * Get a channel instance by name. */ - channel(name: string): PusherChannel { + channel(name: string): AnyPusherChannel { if (!this.channels[name]) { this.channels[name] = new PusherChannel(this.pusher, name, this.options); } @@ -62,7 +58,7 @@ export class PusherConnector extends Connector { /** * Get a private channel instance by name. */ - privateChannel(name: string): PusherChannel { + privateChannel(name: string): PusherPrivateChannel { if (!this.channels['private-' + name]) { this.channels['private-' + name] = new PusherPrivateChannel(this.pusher, 'private-' + name, this.options); } @@ -73,7 +69,7 @@ export class PusherConnector extends Connector { /** * Get a private encrypted channel instance by name. */ - encryptedPrivateChannel(name: string): PusherChannel { + encryptedPrivateChannel(name: string): PusherEncryptedPrivateChannel { if (!this.channels['private-encrypted-' + name]) { this.channels['private-encrypted-' + name] = new PusherEncryptedPrivateChannel( this.pusher, @@ -88,7 +84,7 @@ export class PusherConnector extends Connector { /** * Get a presence channel instance by name. */ - presenceChannel(name: string): PresenceChannel { + presenceChannel(name: string): PusherPresenceChannel { if (!this.channels['presence-' + name]) { this.channels['presence-' + name] = new PusherPresenceChannel( this.pusher, diff --git a/src/connector/socketio-connector.ts b/src/connector/socketio-connector.ts index 26fdddd1..11d038cf 100644 --- a/src/connector/socketio-connector.ts +++ b/src/connector/socketio-connector.ts @@ -1,10 +1,12 @@ import { Connector } from './connector'; import { SocketIoChannel, SocketIoPrivateChannel, SocketIoPresenceChannel } from './../channel'; +type AnySocketIoChannel = SocketIoChannel | SocketIoPrivateChannel | SocketIoPresenceChannel; + /** * This class creates a connnector to a Socket.io server. */ -export class SocketIoConnector extends Connector { +export class SocketIoConnector extends Connector { /** * The Socket.io connection instance. */ @@ -50,14 +52,14 @@ export class SocketIoConnector extends Connector { /** * Listen for an event on a channel instance. */ - listen(name: string, event: string, callback: Function): SocketIoChannel { + listen(name: string, event: string, callback: Function): AnySocketIoChannel { return this.channel(name).listen(event, callback); } /** * Get a channel instance by name. */ - channel(name: string): SocketIoChannel { + channel(name: string): AnySocketIoChannel { if (!this.channels[name]) { this.channels[name] = new SocketIoChannel(this.socket, name, this.options); } diff --git a/src/echo.ts b/src/echo.ts index f47c1b42..f6853515 100644 --- a/src/echo.ts +++ b/src/echo.ts @@ -1,24 +1,24 @@ -import { Channel, PresenceChannel } from './channel'; +import { Channel, NullChannel, NullEncryptedPrivateChannel, NullPresenceChannel, NullPrivateChannel, PresenceChannel, PusherChannel, PusherEncryptedPrivateChannel, PusherPresenceChannel, PusherPrivateChannel, SocketIoChannel, SocketIoPresenceChannel, SocketIoPrivateChannel } from './channel'; import { Connector, PusherConnector, SocketIoConnector, NullConnector } from './connector'; /** * This class is the primary API for interacting with broadcasting. */ -export default class Echo { +export default class Echo { /** * The broadcasting connector. */ - connector: any; + connector: Broadcaster[T]['connector']; /** * The Echo options. */ - options: any; + options: EchoOptions; /** * Create a new class instance. */ - constructor(options: any) { + constructor(options: EchoOptions) { this.options = options; this.connect(); @@ -30,7 +30,7 @@ export default class Echo { /** * Get a channel instance by name. */ - channel(channel: string): Channel { + channel(channel: string): Broadcaster[T]['public'] { return this.connector.channel(channel); } @@ -47,7 +47,7 @@ export default class Echo { } else if (this.options.broadcaster == 'null') { this.connector = new NullConnector(this.options); } else if (typeof this.options.broadcaster == 'function') { - this.connector = new this.options.broadcaster(this.options); + this.connector = this.options.broadcaster(this.options as EchoOptions<'function'>); } else { throw new Error( `Broadcaster ${typeof this.options.broadcaster} ${this.options.broadcaster} is not supported.` @@ -65,7 +65,7 @@ export default class Echo { /** * Get a presence channel instance by name. */ - join(channel: string): PresenceChannel { + join(channel: string): Broadcaster[T]['presence'] { return this.connector.presenceChannel(channel); } @@ -95,21 +95,27 @@ export default class Echo { /** * Listen for an event on a channel instance. */ - listen(channel: string, event: string, callback: Function): Channel { + listen(channel: string, event: string, callback: Function): Broadcaster[T]['public'] { return this.connector.listen(channel, event, callback); } /** * Get a private channel instance by name. */ - private(channel: string): Channel { + private(channel: string): Broadcaster[T]['private'] { return this.connector.privateChannel(channel); } /** * Get a private encrypted channel instance by name. */ - encryptedPrivate(channel: string): Channel { + encryptedPrivate(channel: string): Broadcaster[T]['encrypted'] { + if ((this.connector as any) instanceof SocketIoConnector) { + throw new Error( + `Broadcaster ${typeof this.options.broadcaster} ${this.options.broadcaster} does not support encrypted private channels.` + ); + } + return this.connector.encryptedPrivateChannel(channel); } @@ -197,3 +203,54 @@ export default class Echo { export { Connector, Channel, PresenceChannel }; export { EventFormatter } from './util'; + +/** + * Specifies the broadcaster + */ +type Broadcaster = { + 'reverb': { + connector: PusherConnector, + public: PusherChannel, + private: PusherPrivateChannel, + encrypted: PusherEncryptedPrivateChannel, + presence: PusherPresenceChannel, + }, + 'pusher': { + connector: PusherConnector, + public: PusherChannel, + private: PusherPrivateChannel, + encrypted: PusherEncryptedPrivateChannel, + presence: PusherPresenceChannel, + }, + 'socket.io': { + connector: SocketIoConnector, + public: SocketIoChannel, + private: SocketIoPrivateChannel, + encrypted: never, + presence: SocketIoPresenceChannel, + }, + 'null': { + connector: NullConnector, + public: NullChannel, + private: NullPrivateChannel, + encrypted: NullEncryptedPrivateChannel, + presence: NullPresenceChannel, + }, + 'function': { + connector: any, + public: any, + private: any, + encrypted: any, + presence: any, + } +}; + +type EchoOptions = { + + /** + * The broadcast connector. + */ + broadcaster: T extends 'function' ? ((options: EchoOptions) => any) : T, + + [key: string]: any, +}; diff --git a/tests/echo.test.ts b/tests/echo.test.ts index 6f15d415..910d7533 100644 --- a/tests/echo.test.ts +++ b/tests/echo.test.ts @@ -21,6 +21,8 @@ describe('Echo', () => { }); test('it will throw error for unsupported driver', () => { + // eslint-disable-next-line + // @ts-ignore expect(() => new Echo({ broadcaster: 'foo' })).toThrowError('Broadcaster string foo is not supported.'); }); });