From 90082949919d985e737cf056db07666e6f38d82f Mon Sep 17 00:00:00 2001 From: Dennis Prudlo Date: Sun, 27 Oct 2024 17:27:04 +0100 Subject: [PATCH 01/14] Fix wrong channel types --- src/connector/null-connector.ts | 2 +- src/connector/pusher-connector.ts | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/connector/null-connector.ts b/src/connector/null-connector.ts index ceb5db35..2cd801fe 100644 --- a/src/connector/null-connector.ts +++ b/src/connector/null-connector.ts @@ -48,7 +48,7 @@ export class NullConnector extends Connector { /** * 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..e2c620a1 100644 --- a/src/connector/pusher-connector.ts +++ b/src/connector/pusher-connector.ts @@ -62,7 +62,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 +73,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 +88,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, From 34c700f4d8d63f5dec8cd2c38998fdcec44bd0af Mon Sep 17 00:00:00 2001 From: Dennis Prudlo Date: Sun, 27 Oct 2024 20:10:09 +0100 Subject: [PATCH 02/14] Add generic types --- src/echo.ts | 64 +++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 55 insertions(+), 9 deletions(-) diff --git a/src/echo.ts b/src/echo.ts index f47c1b42..56cf4801 100644 --- a/src/echo.ts +++ b/src/echo.ts @@ -1,24 +1,24 @@ -import { Channel, PresenceChannel } from './channel'; +import { Channel, NullChannel, NullPresenceChannel, NullPrivateChannel, PresenceChannel, PusherChannel, 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 = new 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); } @@ -102,7 +102,7 @@ export default class Echo { /** * Get a private channel instance by name. */ - private(channel: string): Channel { + private(channel: string): Broadcaster[T]['private'] { return this.connector.privateChannel(channel); } @@ -197,3 +197,49 @@ export default class Echo { export { Connector, Channel, PresenceChannel }; export { EventFormatter } from './util'; + +/** + * Specifies the broadcaster + */ +type Broadcaster = { + 'reverb': { + connector: PusherConnector, + public: PusherChannel, + private: PusherPrivateChannel, + presence: PusherPresenceChannel, + }, + 'pusher': { + connector: PusherConnector, + public: PusherChannel, + private: PusherPrivateChannel, + presence: PusherPresenceChannel, + }, + 'socket.io': { + connector: SocketIoConnector, + public: SocketIoChannel, + private: SocketIoPrivateChannel, + presence: SocketIoPresenceChannel, + }, + 'null': { + connector: NullConnector, + public: NullChannel, + private: NullPrivateChannel, + presence: NullPresenceChannel, + }, + 'function': { + connector: any, + public: any, + private: any, + presence: any, + } +}; + +type EchoOptions = { + + /** + * The broadcast connector. + */ + broadcaster: T extends 'function' ? ((options: EchoOptions<'function'>) => void) : T, + + [key: string]: any, +}; From a6f769c0be12a83931f81f719db99f6bf14040a0 Mon Sep 17 00:00:00 2001 From: Dennis Prudlo Date: Sun, 27 Oct 2024 20:10:28 +0100 Subject: [PATCH 03/14] Throw an error when attempting to use encrypted channels with socket.io --- src/echo.ts | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/echo.ts b/src/echo.ts index 56cf4801..e47f6106 100644 --- a/src/echo.ts +++ b/src/echo.ts @@ -109,7 +109,13 @@ export default class Echo { /** * Get a private encrypted channel instance by name. */ - encryptedPrivate(channel: string): Channel { + encryptedPrivate(channel: string): Broadcaster[T]['private'] { + if ((this.connector as any) instanceof SocketIoChannel) { + throw new Error( + `Broadcaster ${typeof this.options.broadcaster} ${this.options.broadcaster} does not support encrypted private channels.` + ); + } + return this.connector.encryptedPrivateChannel(channel); } From b4e62846d6fdf697252ad28ca339514091de6706 Mon Sep 17 00:00:00 2001 From: Dennis Prudlo Date: Sun, 27 Oct 2024 20:41:19 +0100 Subject: [PATCH 04/14] Fix types for the function broadcaster --- src/echo.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/echo.ts b/src/echo.ts index e47f6106..8954a4ac 100644 --- a/src/echo.ts +++ b/src/echo.ts @@ -234,9 +234,9 @@ type Broadcaster = { }, 'function': { connector: any, - public: any, - private: any, - presence: any, + public: Channel, + private: Channel, + presence: Channel, } }; @@ -245,7 +245,7 @@ type EchoOptions = { /** * The broadcast connector. */ - broadcaster: T extends 'function' ? ((options: EchoOptions<'function'>) => void) : T, + broadcaster: T extends 'function' ? ((options: EchoOptions) => void) : T, [key: string]: any, }; From 9d06d5537c9e2eac9e8d6dd31e498f0fd8a99062 Mon Sep 17 00:00:00 2001 From: Dennis Prudlo Date: Tue, 29 Oct 2024 21:53:42 +0100 Subject: [PATCH 05/14] Add generic to channel types --- src/channel/channel.ts | 16 +++++----- src/channel/index.ts | 4 +++ src/channel/null-channel.ts | 26 ++++++++-------- src/channel/null-encrypted-private-channel.ts | 13 ++++++++ src/channel/null-presence-channel.ts | 3 +- src/channel/null-private-channel.ts | 2 +- src/channel/null-public-channel.ts | 8 +++++ src/channel/presence-channel.ts | 10 +++---- src/channel/pusher-channel.ts | 30 +++++++++---------- .../pusher-encrypted-private-channel.ts | 2 +- src/channel/pusher-presence-channel.ts | 3 +- src/channel/pusher-private-channel.ts | 2 +- src/channel/pusher-public-channel.ts | 8 +++++ src/channel/socketio-channel.ts | 22 +++++++------- src/channel/socketio-presence-channel.ts | 3 +- src/channel/socketio-private-channel.ts | 4 +-- src/channel/socketio-public-channel.ts | 8 +++++ src/echo.ts | 25 +++++++++------- 18 files changed, 119 insertions(+), 70 deletions(-) create mode 100644 src/channel/null-encrypted-private-channel.ts create mode 100644 src/channel/null-public-channel.ts create mode 100644 src/channel/pusher-public-channel.ts create mode 100644 src/channel/socketio-public-channel.ts diff --git a/src/channel/channel.ts b/src/channel/channel.ts index 4cb441a6..1ad671a4 100644 --- a/src/channel/channel.ts +++ b/src/channel/channel.ts @@ -1,7 +1,7 @@ /** * This class represents a basic channel. */ -export abstract class Channel { +export abstract class Channel { /** * The Echo options. */ @@ -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): T; /** * Listen for a whisper event on the channel instance. */ - listenForWhisper(event: string, callback: Function): Channel { + listenForWhisper(event: string, callback: Function): T { return this.listen('.client-' + event, callback); } /** * Listen for an event on the channel instance. */ - notification(callback: Function): Channel { + notification(callback: Function): T { 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): T; /** * Stop listening for a whisper event on the channel instance. */ - stopListeningForWhisper(event: string, callback?: Function): Channel { + stopListeningForWhisper(event: string, callback?: Function): T { 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): T; /** * Register a callback to be called anytime an error occurs. */ - abstract error(callback: Function): Channel; + abstract error(callback: Function): T; } diff --git a/src/channel/index.ts b/src/channel/index.ts index 2e719848..5f9720cc 100644 --- a/src/channel/index.ts +++ b/src/channel/index.ts @@ -1,12 +1,16 @@ export * from './channel'; export * from './presence-channel'; export * from './pusher-channel'; +export * from './pusher-public-channel'; export * from './pusher-private-channel'; export * from './pusher-encrypted-private-channel'; export * from './pusher-presence-channel'; export * from './socketio-channel'; +export * from './socketio-public-channel'; export * from './socketio-private-channel'; export * from './socketio-presence-channel'; export * from './null-channel'; +export * from './null-public-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..94e8b0d7 100644 --- a/src/channel/null-channel.ts +++ b/src/channel/null-channel.ts @@ -3,7 +3,7 @@ import { Channel } from './channel'; /** * This class represents a null channel. */ -export class NullChannel extends Channel { +export class NullChannel extends Channel { /** * Subscribe to a channel. */ @@ -21,42 +21,42 @@ export class NullChannel extends Channel { /** * Listen for an event on the channel instance. */ - listen(event: string, callback: Function): NullChannel { - return this; + listen(event: string, callback: Function): T { + return this as unknown as T; } /** * Listen for all events on the channel instance. */ - listenToAll(callback: Function): NullChannel { - return this; + listenToAll(callback: Function): T { + return this as unknown as T; } /** * Stop listening for an event on the channel instance. */ - stopListening(event: string, callback?: Function): NullChannel { - return this; + stopListening(event: string, callback?: Function): T { + return this as unknown as T; } /** * Register a callback to be called anytime a subscription succeeds. */ - subscribed(callback: Function): NullChannel { - return this; + subscribed(callback: Function): T { + return this as unknown as T; } /** * Register a callback to be called anytime an error occurs. */ - error(callback: Function): NullChannel { - return this; + error(callback: Function): T { + return this as unknown as T; } /** * Bind a channel to an event. */ - on(event: string, callback: Function): NullChannel { - return this; + on(event: string, callback: Function): T { + return this as unknown as T; } } diff --git a/src/channel/null-encrypted-private-channel.ts b/src/channel/null-encrypted-private-channel.ts new file mode 100644 index 00000000..fa984086 --- /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): NullEncryptedPrivateChannel { + return this; + } +} diff --git a/src/channel/null-presence-channel.ts b/src/channel/null-presence-channel.ts index 18ca9b94..5d9de43b 100644 --- a/src/channel/null-presence-channel.ts +++ b/src/channel/null-presence-channel.ts @@ -1,10 +1,11 @@ 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 NullChannel implements PresenceChannel { /** * Register a callback to be called anytime the member list changes. */ diff --git a/src/channel/null-private-channel.ts b/src/channel/null-private-channel.ts index e6221779..c7b5e0db 100644 --- a/src/channel/null-private-channel.ts +++ b/src/channel/null-private-channel.ts @@ -3,7 +3,7 @@ import { NullChannel } from './null-channel'; /** * This class represents a null private channel. */ -export class NullPrivateChannel extends NullChannel { +export class NullPrivateChannel extends NullChannel { /** * Send a whisper event to other clients in the channel. */ diff --git a/src/channel/null-public-channel.ts b/src/channel/null-public-channel.ts new file mode 100644 index 00000000..def66e1a --- /dev/null +++ b/src/channel/null-public-channel.ts @@ -0,0 +1,8 @@ +import { NullChannel } from './null-channel'; + +/** + * This class represents a null public channel. + */ +export class NullPublicChannel extends NullChannel { + +} diff --git a/src/channel/presence-channel.ts b/src/channel/presence-channel.ts index 1b0ec302..7ad2a703 100644 --- a/src/channel/presence-channel.ts +++ b/src/channel/presence-channel.ts @@ -3,24 +3,24 @@ import { Channel } from './channel'; /** * This interface represents a presence channel. */ -export interface PresenceChannel extends Channel { +export interface PresenceChannel extends Channel { /** * Register a callback to be called anytime the member list changes. */ - here(callback: Function): PresenceChannel; + here(callback: Function): T; /** * Listen for someone joining the channel. */ - joining(callback: Function): PresenceChannel; + joining(callback: Function): T; /** * Send a whisper event to other clients in the channel. */ - whisper(eventName: string, data: any): PresenceChannel; + whisper(eventName: string, data: any): T; /** * Listen for someone leaving the channel. */ - leaving(callback: Function): PresenceChannel; + leaving(callback: Function): T; } diff --git a/src/channel/pusher-channel.ts b/src/channel/pusher-channel.ts index e59606fb..a6a5ab72 100644 --- a/src/channel/pusher-channel.ts +++ b/src/channel/pusher-channel.ts @@ -4,7 +4,7 @@ import { Channel } from './channel'; /** * This class represents a Pusher channel. */ -export class PusherChannel extends Channel { +export abstract class PusherChannel extends Channel { /** * The Pusher client instance. */ @@ -61,16 +61,16 @@ export class PusherChannel extends Channel { /** * Listen for an event on the channel instance. */ - listen(event: string, callback: Function): PusherChannel { + listen(event: string, callback: Function): T { this.on(this.eventFormatter.format(event), callback); - return this; + return this as unknown as T; } /** * Listen for all events on the channel instance. */ - listenToAll(callback: Function): PusherChannel { + listenToAll(callback: Function): T { this.subscription.bind_global((event, data) => { if (event.startsWith('pusher:')) { return; @@ -83,63 +83,63 @@ export class PusherChannel extends Channel { callback(formattedEvent, data); }); - return this; + return this as unknown as T; } /** * Stop listening for an event on the channel instance. */ - stopListening(event: string, callback?: Function): PusherChannel { + stopListening(event: string, callback?: Function): T { if (callback) { this.subscription.unbind(this.eventFormatter.format(event), callback); } else { this.subscription.unbind(this.eventFormatter.format(event)); } - return this; + return this as unknown as T; } /** * Stop listening for all events on the channel instance. */ - stopListeningToAll(callback?: Function): PusherChannel { + stopListeningToAll(callback?: Function): T { if (callback) { this.subscription.unbind_global(callback); } else { this.subscription.unbind_global(); } - return this; + return this as unknown as T; } /** * Register a callback to be called anytime a subscription succeeds. */ - subscribed(callback: Function): PusherChannel { + subscribed(callback: Function): T { this.on('pusher:subscription_succeeded', () => { callback(); }); - return this; + return this as unknown as T; } /** * Register a callback to be called anytime a subscription error occurs. */ - error(callback: Function): PusherChannel { + error(callback: Function): T { this.on('pusher:subscription_error', (status) => { callback(status); }); - return this; + return this as unknown as T; } /** * Bind a channel to an event. */ - on(event: string, callback: Function): PusherChannel { + on(event: string, callback: Function): T { this.subscription.bind(event, callback); - return this; + return this as unknown as T; } } diff --git a/src/channel/pusher-encrypted-private-channel.ts b/src/channel/pusher-encrypted-private-channel.ts index edc82c4c..983d6d40 100644 --- a/src/channel/pusher-encrypted-private-channel.ts +++ b/src/channel/pusher-encrypted-private-channel.ts @@ -3,7 +3,7 @@ import { PusherChannel } from './pusher-channel'; /** * This class represents a Pusher private channel. */ -export class PusherEncryptedPrivateChannel extends PusherChannel { +export class PusherEncryptedPrivateChannel extends PusherChannel { /** * Send a whisper event to other clients in the channel. */ diff --git a/src/channel/pusher-presence-channel.ts b/src/channel/pusher-presence-channel.ts index 7c70c523..7cc886b2 100644 --- a/src/channel/pusher-presence-channel.ts +++ b/src/channel/pusher-presence-channel.ts @@ -1,10 +1,11 @@ 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 PusherChannel implements PresenceChannel { /** * Register a callback to be called anytime the member list changes. */ diff --git a/src/channel/pusher-private-channel.ts b/src/channel/pusher-private-channel.ts index 9158449d..1f9b2e80 100644 --- a/src/channel/pusher-private-channel.ts +++ b/src/channel/pusher-private-channel.ts @@ -3,7 +3,7 @@ import { PusherChannel } from './pusher-channel'; /** * This class represents a Pusher private channel. */ -export class PusherPrivateChannel extends PusherChannel { +export class PusherPrivateChannel extends PusherChannel { /** * Send a whisper event to other clients in the channel. */ diff --git a/src/channel/pusher-public-channel.ts b/src/channel/pusher-public-channel.ts new file mode 100644 index 00000000..5b076dd6 --- /dev/null +++ b/src/channel/pusher-public-channel.ts @@ -0,0 +1,8 @@ +import { PusherChannel } from './pusher-channel'; + +/** + * This class represents a Pusher public channel. + */ +export abstract class PusherPublicChannel extends PusherChannel { + +} diff --git a/src/channel/socketio-channel.ts b/src/channel/socketio-channel.ts index 1911f3e4..eab946eb 100644 --- a/src/channel/socketio-channel.ts +++ b/src/channel/socketio-channel.ts @@ -4,7 +4,7 @@ import { Channel } from './channel'; /** * This class represents a Socket.io channel. */ -export class SocketIoChannel extends Channel { +export class SocketIoChannel extends Channel { /** * The Socket.io client instance. */ @@ -74,43 +74,43 @@ export class SocketIoChannel extends Channel { /** * Listen for an event on the channel instance. */ - listen(event: string, callback: Function): SocketIoChannel { + listen(event: string, callback: Function): T { this.on(this.eventFormatter.format(event), callback); - return this; + return this as unknown as T; } /** * Stop listening for an event on the channel instance. */ - stopListening(event: string, callback?: Function): SocketIoChannel { + stopListening(event: string, callback?: Function): T { this.unbindEvent(this.eventFormatter.format(event), callback); - return this; + return this as unknown as T; } /** * Register a callback to be called anytime a subscription succeeds. */ - subscribed(callback: Function): SocketIoChannel { + subscribed(callback: Function): T { this.on('connect', (socket) => { callback(socket); }); - return this; + return this as unknown as T; } /** * Register a callback to be called anytime an error occurs. */ - error(callback: Function): SocketIoChannel { - return this; + error(callback: Function): T { + return this as unknown as T; } /** * Bind the channel's socket to an event and store the callback. */ - on(event: string, callback: Function): SocketIoChannel { + on(event: string, callback: Function): T { this.listeners[event] = this.listeners[event] || []; if (!this.events[event]) { @@ -125,7 +125,7 @@ export class SocketIoChannel extends Channel { this.listeners[event].push(callback); - return this; + return this as unknown as T; } /** diff --git a/src/channel/socketio-presence-channel.ts b/src/channel/socketio-presence-channel.ts index 96e46dd5..ba8be355 100644 --- a/src/channel/socketio-presence-channel.ts +++ b/src/channel/socketio-presence-channel.ts @@ -1,10 +1,11 @@ import { PresenceChannel } from './presence-channel'; +import { SocketIoChannel } from './socketio-channel'; import { SocketIoPrivateChannel } from './socketio-private-channel'; /** * This class represents a Socket.io presence channel. */ -export class SocketIoPresenceChannel extends SocketIoPrivateChannel implements PresenceChannel { +export class SocketIoPresenceChannel extends SocketIoChannel implements PresenceChannel { /** * Register a callback to be called anytime the member list changes. */ diff --git a/src/channel/socketio-private-channel.ts b/src/channel/socketio-private-channel.ts index 102da067..d92886d4 100644 --- a/src/channel/socketio-private-channel.ts +++ b/src/channel/socketio-private-channel.ts @@ -3,11 +3,11 @@ import { SocketIoChannel } from './socketio-channel'; /** * This class represents a Socket.io private channel. */ -export class SocketIoPrivateChannel extends SocketIoChannel { +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): SocketIoPrivateChannel { this.socket.emit('client event', { channel: this.name, event: `client-${eventName}`, diff --git a/src/channel/socketio-public-channel.ts b/src/channel/socketio-public-channel.ts new file mode 100644 index 00000000..2e350c17 --- /dev/null +++ b/src/channel/socketio-public-channel.ts @@ -0,0 +1,8 @@ +import { SocketIoChannel } from './socketio-channel'; + +/** + * This class represents a Socket.io public channel. + */ +export class SocketIoPublicChannel extends SocketIoChannel { + +} diff --git a/src/echo.ts b/src/echo.ts index 8954a4ac..fc262c76 100644 --- a/src/echo.ts +++ b/src/echo.ts @@ -1,4 +1,4 @@ -import { Channel, NullChannel, NullPresenceChannel, NullPrivateChannel, PresenceChannel, PusherChannel, PusherPresenceChannel, PusherPrivateChannel, SocketIoChannel, SocketIoPresenceChannel, SocketIoPrivateChannel } from './channel'; +import { Channel, NullChannel, NullEncryptedPrivateChannel, NullPresenceChannel, NullPrivateChannel, NullPublicChannel, PresenceChannel, PusherChannel, PusherEncryptedPrivateChannel, PusherPresenceChannel, PusherPrivateChannel, PusherPublicChannel, SocketIoChannel, SocketIoPresenceChannel, SocketIoPrivateChannel, SocketIoPublicChannel } from './channel'; import { Connector, PusherConnector, SocketIoConnector, NullConnector } from './connector'; /** @@ -95,7 +95,7 @@ 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); } @@ -109,7 +109,7 @@ export default class Echo { /** * Get a private encrypted channel instance by name. */ - encryptedPrivate(channel: string): Broadcaster[T]['private'] { + encryptedPrivate(channel: string): Broadcaster[T]['encrypted'] { if ((this.connector as any) instanceof SocketIoChannel) { throw new Error( `Broadcaster ${typeof this.options.broadcaster} ${this.options.broadcaster} does not support encrypted private channels.` @@ -210,33 +210,38 @@ export { EventFormatter } from './util'; type Broadcaster = { 'reverb': { connector: PusherConnector, - public: PusherChannel, + public: PusherPublicChannel, private: PusherPrivateChannel, + encrypted: PusherEncryptedPrivateChannel, presence: PusherPresenceChannel, }, 'pusher': { connector: PusherConnector, - public: PusherChannel, + public: PusherPublicChannel, private: PusherPrivateChannel, + encrypted: PusherEncryptedPrivateChannel, presence: PusherPresenceChannel, }, 'socket.io': { connector: SocketIoConnector, - public: SocketIoChannel, + public: SocketIoPublicChannel, private: SocketIoPrivateChannel, + encrypted: any, presence: SocketIoPresenceChannel, }, 'null': { connector: NullConnector, - public: NullChannel, + public: NullPublicChannel, private: NullPrivateChannel, + encrypted: NullEncryptedPrivateChannel, presence: NullPresenceChannel, }, 'function': { connector: any, - public: Channel, - private: Channel, - presence: Channel, + public: Channel, + private: Channel, + encrypted: Channel, + presence: Channel, } }; From 304c6c08ca4ef5a34715240f1bf1cd3945deebb0 Mon Sep 17 00:00:00 2001 From: Dennis Prudlo Date: Tue, 29 Oct 2024 22:02:09 +0100 Subject: [PATCH 06/14] Fix function types --- src/echo.ts | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/echo.ts b/src/echo.ts index fc262c76..f5be0255 100644 --- a/src/echo.ts +++ b/src/echo.ts @@ -1,4 +1,4 @@ -import { Channel, NullChannel, NullEncryptedPrivateChannel, NullPresenceChannel, NullPrivateChannel, NullPublicChannel, PresenceChannel, PusherChannel, PusherEncryptedPrivateChannel, PusherPresenceChannel, PusherPrivateChannel, PusherPublicChannel, SocketIoChannel, SocketIoPresenceChannel, SocketIoPrivateChannel, SocketIoPublicChannel } from './channel'; +import { Channel, NullEncryptedPrivateChannel, NullPresenceChannel, NullPrivateChannel, NullPublicChannel, PresenceChannel, PusherEncryptedPrivateChannel, PusherPresenceChannel, PusherPrivateChannel, PusherPublicChannel, SocketIoPresenceChannel, SocketIoPrivateChannel, SocketIoPublicChannel } from './channel'; import { Connector, PusherConnector, SocketIoConnector, NullConnector } from './connector'; /** @@ -110,7 +110,7 @@ export default class Echo { * Get a private encrypted channel instance by name. */ encryptedPrivate(channel: string): Broadcaster[T]['encrypted'] { - if ((this.connector as any) instanceof SocketIoChannel) { + if ((this.connector as any) instanceof SocketIoConnector) { throw new Error( `Broadcaster ${typeof this.options.broadcaster} ${this.options.broadcaster} does not support encrypted private channels.` ); @@ -238,10 +238,10 @@ type Broadcaster = { }, 'function': { connector: any, - public: Channel, - private: Channel, - encrypted: Channel, - presence: Channel, + public: any, + private: any, + encrypted: any, + presence: any, } }; From a382463814ed960e5b95e0e9b6d732190743cefa Mon Sep 17 00:00:00 2001 From: Dennis Prudlo Date: Tue, 29 Oct 2024 22:33:30 +0100 Subject: [PATCH 07/14] Make connectors generic --- src/channel/null-channel.ts | 6 ++++++ src/channel/pusher-channel.ts | 8 +++++++- src/channel/pusher-public-channel.ts | 2 +- src/channel/socketio-channel.ts | 5 +++++ src/connector/connector.ts | 10 ++++------ src/connector/null-connector.ts | 12 ++++++------ src/connector/pusher-connector.ts | 9 +++++---- src/connector/socketio-connector.ts | 10 +++++----- 8 files changed, 39 insertions(+), 23 deletions(-) diff --git a/src/channel/null-channel.ts b/src/channel/null-channel.ts index 94e8b0d7..62a5c67c 100644 --- a/src/channel/null-channel.ts +++ b/src/channel/null-channel.ts @@ -1,4 +1,10 @@ import { Channel } from './channel'; +import { NullEncryptedPrivateChannel } from './null-encrypted-private-channel'; +import { NullPresenceChannel } from './null-presence-channel'; +import { NullPrivateChannel } from './null-private-channel'; +import { NullPublicChannel } from './null-public-channel'; + +export type NullChannels = NullPublicChannel | NullPrivateChannel | NullEncryptedPrivateChannel | NullPresenceChannel; /** * This class represents a null channel. diff --git a/src/channel/pusher-channel.ts b/src/channel/pusher-channel.ts index a6a5ab72..8cf21d5e 100644 --- a/src/channel/pusher-channel.ts +++ b/src/channel/pusher-channel.ts @@ -1,10 +1,16 @@ import { EventFormatter } from '../util'; import { Channel } from './channel'; +import { PusherEncryptedPrivateChannel } from './pusher-encrypted-private-channel'; +import { PusherPresenceChannel } from './pusher-presence-channel'; +import { PusherPrivateChannel } from './pusher-private-channel'; +import { PusherPublicChannel } from './pusher-public-channel'; + +export type PusherChannels = PusherPublicChannel | PusherPrivateChannel | PusherEncryptedPrivateChannel | PusherPresenceChannel; /** * This class represents a Pusher channel. */ -export abstract class PusherChannel extends Channel { +export class PusherChannel extends Channel { /** * The Pusher client instance. */ diff --git a/src/channel/pusher-public-channel.ts b/src/channel/pusher-public-channel.ts index 5b076dd6..658ac9d3 100644 --- a/src/channel/pusher-public-channel.ts +++ b/src/channel/pusher-public-channel.ts @@ -3,6 +3,6 @@ import { PusherChannel } from './pusher-channel'; /** * This class represents a Pusher public channel. */ -export abstract class PusherPublicChannel extends PusherChannel { +export class PusherPublicChannel extends PusherChannel { } diff --git a/src/channel/socketio-channel.ts b/src/channel/socketio-channel.ts index eab946eb..803de06a 100644 --- a/src/channel/socketio-channel.ts +++ b/src/channel/socketio-channel.ts @@ -1,5 +1,10 @@ import { EventFormatter } from '../util'; import { Channel } from './channel'; +import { SocketIoPresenceChannel } from './socketio-presence-channel'; +import { SocketIoPrivateChannel } from './socketio-private-channel'; +import { SocketIoPublicChannel } from './socketio-public-channel'; + +export type SocketIoChannels = SocketIoPublicChannel | SocketIoPrivateChannel | SocketIoPresenceChannel; /** * This class represents a Socket.io channel. diff --git a/src/connector/connector.ts b/src/connector/connector.ts index fab8de5f..4b3edac8 100644 --- a/src/connector/connector.ts +++ b/src/connector/connector.ts @@ -1,6 +1,4 @@ -import { Channel, PresenceChannel } from './../channel'; - -export abstract class Connector { +export abstract class Connector { /** * Default connector options. */ @@ -86,17 +84,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 2cd801fe..a9211695 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, NullPublicChannel, NullEncryptedPrivateChannel, NullChannels } from './../channel'; /** * This class creates a null connector. */ -export class NullConnector extends Connector { +export class NullConnector extends Connector { /** * All of the subscribed channel names. */ @@ -20,14 +20,14 @@ export class NullConnector extends Connector { /** * Listen for an event on a channel instance. */ - listen(name: string, event: string, callback: Function): NullChannel { + listen(name: string, event: string, callback: Function): NullChannel { return new NullChannel(); } /** * Get a channel instance by name. */ - channel(name: string): NullChannel { + channel(name: string): NullChannel { return new NullChannel(); } @@ -41,8 +41,8 @@ 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(); } /** diff --git a/src/connector/pusher-connector.ts b/src/connector/pusher-connector.ts index e2c620a1..eb8de46b 100644 --- a/src/connector/pusher-connector.ts +++ b/src/connector/pusher-connector.ts @@ -4,13 +4,14 @@ import { PusherPrivateChannel, PusherEncryptedPrivateChannel, PusherPresenceChannel, - PresenceChannel, + PusherPublicChannel, + PusherChannels, } from './../channel'; /** * This class creates a connector to Pusher. */ -export class PusherConnector extends Connector { +export class PusherConnector extends Connector { /** * The Pusher instance. */ @@ -44,14 +45,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): PusherChannel { return this.channel(name).listen(event, callback); } /** * Get a channel instance by name. */ - channel(name: string): PusherChannel { + channel(name: string): PusherChannel { if (!this.channels[name]) { this.channels[name] = new PusherChannel(this.pusher, name, this.options); } diff --git a/src/connector/socketio-connector.ts b/src/connector/socketio-connector.ts index 26fdddd1..06cadca4 100644 --- a/src/connector/socketio-connector.ts +++ b/src/connector/socketio-connector.ts @@ -1,10 +1,10 @@ import { Connector } from './connector'; -import { SocketIoChannel, SocketIoPrivateChannel, SocketIoPresenceChannel } from './../channel'; +import { SocketIoChannel, SocketIoPrivateChannel, SocketIoPresenceChannel, SocketIoPublicChannel, SocketIoChannels } from './../channel'; /** * 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. */ @@ -13,7 +13,7 @@ export class SocketIoConnector extends Connector { /** * All of the subscribed channel names. */ - channels: { [name: string]: SocketIoChannel } = {}; + channels: { [name: string]: SocketIoChannels } = {}; /** * Create a fresh Socket.io connection. @@ -50,14 +50,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): SocketIoChannel { return this.channel(name).listen(event, callback); } /** * Get a channel instance by name. */ - channel(name: string): SocketIoChannel { + channel(name: string): SocketIoChannel { if (!this.channels[name]) { this.channels[name] = new SocketIoChannel(this.socket, name, this.options); } From 820ab6e130b24993294efef715adcfd5ff1c75fd Mon Sep 17 00:00:00 2001 From: Dennis Prudlo Date: Tue, 29 Oct 2024 23:06:17 +0100 Subject: [PATCH 08/14] Remove new keyword for function broadcasters --- src/echo.ts | 4 ++-- tests/echo.test.ts | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/echo.ts b/src/echo.ts index f5be0255..396eb54c 100644 --- a/src/echo.ts +++ b/src/echo.ts @@ -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 as EchoOptions<'function'>); + 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.` @@ -226,7 +226,7 @@ type Broadcaster = { connector: SocketIoConnector, public: SocketIoPublicChannel, private: SocketIoPrivateChannel, - encrypted: any, + encrypted: never, presence: SocketIoPresenceChannel, }, 'null': { diff --git a/tests/echo.test.ts b/tests/echo.test.ts index 6f15d415..7c9253d9 100644 --- a/tests/echo.test.ts +++ b/tests/echo.test.ts @@ -21,6 +21,7 @@ describe('Echo', () => { }); test('it will throw error for unsupported driver', () => { + // @ts-ignore expect(() => new Echo({ broadcaster: 'foo' })).toThrowError('Broadcaster string foo is not supported.'); }); }); From d9a333e470ce81dc8048ed64fc9ce7fc7caf1c25 Mon Sep 17 00:00:00 2001 From: Dennis Prudlo Date: Tue, 29 Oct 2024 23:08:03 +0100 Subject: [PATCH 09/14] Fix tests --- tests/echo.test.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/echo.test.ts b/tests/echo.test.ts index 7c9253d9..910d7533 100644 --- a/tests/echo.test.ts +++ b/tests/echo.test.ts @@ -21,6 +21,7 @@ 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.'); }); From ce92102afea2dc8ac75f8dbfc5db9a1771adce6a Mon Sep 17 00:00:00 2001 From: Dennis Prudlo Date: Tue, 29 Oct 2024 23:42:26 +0100 Subject: [PATCH 10/14] Specify return type for function broadcasters --- src/echo.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/echo.ts b/src/echo.ts index 396eb54c..a85622f1 100644 --- a/src/echo.ts +++ b/src/echo.ts @@ -250,7 +250,7 @@ type EchoOptions = { /** * The broadcast connector. */ - broadcaster: T extends 'function' ? ((options: EchoOptions) => void) : T, + broadcaster: T extends 'function' ? ((options: EchoOptions) => any) : T, [key: string]: any, }; From 9e571761880f87089f97e493b43836d3cf6e4d3a Mon Sep 17 00:00:00 2001 From: Dennis Prudlo Date: Fri, 1 Nov 2024 16:16:56 +0100 Subject: [PATCH 11/14] Clean up generics --- src/channel/channel.ts | 16 ++++----- src/channel/index.ts | 3 -- src/channel/null-channel.ts | 32 +++++++---------- src/channel/null-encrypted-private-channel.ts | 4 +-- src/channel/null-presence-channel.ts | 11 +++--- src/channel/null-private-channel.ts | 4 +-- src/channel/null-public-channel.ts | 8 ----- src/channel/presence-channel.ts | 10 +++--- src/channel/pusher-channel.ts | 36 ++++++++----------- .../pusher-encrypted-private-channel.ts | 4 +-- src/channel/pusher-presence-channel.ts | 11 +++--- src/channel/pusher-private-channel.ts | 4 +-- src/channel/pusher-public-channel.ts | 8 ----- src/channel/socketio-channel.ts | 27 ++++++-------- src/channel/socketio-presence-channel.ts | 11 +++--- src/channel/socketio-private-channel.ts | 4 +-- src/channel/socketio-public-channel.ts | 8 ----- src/connector/connector.ts | 4 ++- src/connector/null-connector.ts | 10 +++--- src/connector/pusher-connector.ts | 17 ++++----- src/connector/socketio-connector.ts | 12 ++++--- src/echo.ts | 10 +++--- 22 files changed, 104 insertions(+), 150 deletions(-) delete mode 100644 src/channel/null-public-channel.ts delete mode 100644 src/channel/pusher-public-channel.ts delete mode 100644 src/channel/socketio-public-channel.ts diff --git a/src/channel/channel.ts b/src/channel/channel.ts index 1ad671a4..aeb3b03b 100644 --- a/src/channel/channel.ts +++ b/src/channel/channel.ts @@ -1,7 +1,7 @@ /** * This class represents a basic channel. */ -export abstract class Channel { +export abstract class Channel { /** * The Echo options. */ @@ -10,41 +10,41 @@ export abstract class Channel { /** * Listen for an event on the channel instance. */ - abstract listen(event: string, callback: Function): T; + abstract listen(event: string, callback: Function): this; /** * Listen for a whisper event on the channel instance. */ - listenForWhisper(event: string, callback: Function): T { + listenForWhisper(event: string, callback: Function): this { return this.listen('.client-' + event, callback); } /** * Listen for an event on the channel instance. */ - notification(callback: Function): T { + 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): T; + abstract stopListening(event: string, callback?: Function): this; /** * Stop listening for a whisper event on the channel instance. */ - stopListeningForWhisper(event: string, callback?: Function): T { + 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): T; + abstract subscribed(callback: Function): this; /** * Register a callback to be called anytime an error occurs. */ - abstract error(callback: Function): T; + abstract error(callback: Function): this; } diff --git a/src/channel/index.ts b/src/channel/index.ts index 5f9720cc..668f6385 100644 --- a/src/channel/index.ts +++ b/src/channel/index.ts @@ -1,16 +1,13 @@ export * from './channel'; export * from './presence-channel'; export * from './pusher-channel'; -export * from './pusher-public-channel'; export * from './pusher-private-channel'; export * from './pusher-encrypted-private-channel'; export * from './pusher-presence-channel'; export * from './socketio-channel'; -export * from './socketio-public-channel'; export * from './socketio-private-channel'; export * from './socketio-presence-channel'; export * from './null-channel'; -export * from './null-public-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 62a5c67c..e79b1fa4 100644 --- a/src/channel/null-channel.ts +++ b/src/channel/null-channel.ts @@ -1,15 +1,9 @@ import { Channel } from './channel'; -import { NullEncryptedPrivateChannel } from './null-encrypted-private-channel'; -import { NullPresenceChannel } from './null-presence-channel'; -import { NullPrivateChannel } from './null-private-channel'; -import { NullPublicChannel } from './null-public-channel'; - -export type NullChannels = NullPublicChannel | NullPrivateChannel | NullEncryptedPrivateChannel | NullPresenceChannel; /** * This class represents a null channel. */ -export class NullChannel extends Channel { +export class NullChannel extends Channel { /** * Subscribe to a channel. */ @@ -27,42 +21,42 @@ export class NullChannel extends Channel { /** * Listen for an event on the channel instance. */ - listen(event: string, callback: Function): T { - return this as unknown as T; + listen(event: string, callback: Function): this { + return this; } /** * Listen for all events on the channel instance. */ - listenToAll(callback: Function): T { - return this as unknown as T; + listenToAll(callback: Function): this { + return this; } /** * Stop listening for an event on the channel instance. */ - stopListening(event: string, callback?: Function): T { - return this as unknown as T; + stopListening(event: string, callback?: Function): this { + return this; } /** * Register a callback to be called anytime a subscription succeeds. */ - subscribed(callback: Function): T { - return this as unknown as T; + subscribed(callback: Function): this { + return this; } /** * Register a callback to be called anytime an error occurs. */ - error(callback: Function): T { - return this as unknown as T; + error(callback: Function): this { + return this; } /** * Bind a channel to an event. */ - on(event: string, callback: Function): T { - return this as unknown as T; + 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 index fa984086..fc918117 100644 --- a/src/channel/null-encrypted-private-channel.ts +++ b/src/channel/null-encrypted-private-channel.ts @@ -3,11 +3,11 @@ import { NullChannel } from './null-channel'; /** * This class represents a null private channel. */ -export class NullEncryptedPrivateChannel extends NullChannel { +export class NullEncryptedPrivateChannel extends NullChannel { /** * Send a whisper event to other clients in the channel. */ - whisper(eventName: string, data: any): NullEncryptedPrivateChannel { + 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 5d9de43b..7bf64cb9 100644 --- a/src/channel/null-presence-channel.ts +++ b/src/channel/null-presence-channel.ts @@ -1,36 +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 c7b5e0db..862ac5c2 100644 --- a/src/channel/null-private-channel.ts +++ b/src/channel/null-private-channel.ts @@ -3,11 +3,11 @@ import { NullChannel } from './null-channel'; /** * This class represents a null private channel. */ -export class NullPrivateChannel extends NullChannel { +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/null-public-channel.ts b/src/channel/null-public-channel.ts deleted file mode 100644 index def66e1a..00000000 --- a/src/channel/null-public-channel.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { NullChannel } from './null-channel'; - -/** - * This class represents a null public channel. - */ -export class NullPublicChannel extends NullChannel { - -} diff --git a/src/channel/presence-channel.ts b/src/channel/presence-channel.ts index 7ad2a703..2b2063e2 100644 --- a/src/channel/presence-channel.ts +++ b/src/channel/presence-channel.ts @@ -3,24 +3,24 @@ import { Channel } from './channel'; /** * This interface represents a presence channel. */ -export interface PresenceChannel extends Channel { +export interface PresenceChannel extends Channel { /** * Register a callback to be called anytime the member list changes. */ - here(callback: Function): T; + here(callback: Function): this; /** * Listen for someone joining the channel. */ - joining(callback: Function): T; + joining(callback: Function): this; /** * Send a whisper event to other clients in the channel. */ - whisper(eventName: string, data: any): T; + whisper(eventName: string, data: any): this; /** * Listen for someone leaving the channel. */ - leaving(callback: Function): T; + leaving(callback: Function): this; } diff --git a/src/channel/pusher-channel.ts b/src/channel/pusher-channel.ts index 8cf21d5e..82506f76 100644 --- a/src/channel/pusher-channel.ts +++ b/src/channel/pusher-channel.ts @@ -1,16 +1,10 @@ import { EventFormatter } from '../util'; import { Channel } from './channel'; -import { PusherEncryptedPrivateChannel } from './pusher-encrypted-private-channel'; -import { PusherPresenceChannel } from './pusher-presence-channel'; -import { PusherPrivateChannel } from './pusher-private-channel'; -import { PusherPublicChannel } from './pusher-public-channel'; - -export type PusherChannels = PusherPublicChannel | PusherPrivateChannel | PusherEncryptedPrivateChannel | PusherPresenceChannel; /** * This class represents a Pusher channel. */ -export class PusherChannel extends Channel { +export class PusherChannel extends Channel { /** * The Pusher client instance. */ @@ -67,16 +61,16 @@ export class PusherChannel extends Channel { /** * Listen for an event on the channel instance. */ - listen(event: string, callback: Function): T { + listen(event: string, callback: Function): this { this.on(this.eventFormatter.format(event), callback); - return this as unknown as T; + return this as unknown as this; } /** * Listen for all events on the channel instance. */ - listenToAll(callback: Function): T { + listenToAll(callback: Function): this { this.subscription.bind_global((event, data) => { if (event.startsWith('pusher:')) { return; @@ -89,63 +83,63 @@ export class PusherChannel extends Channel { callback(formattedEvent, data); }); - return this as unknown as T; + return this; } /** * Stop listening for an event on the channel instance. */ - stopListening(event: string, callback?: Function): T { + stopListening(event: string, callback?: Function): this { if (callback) { this.subscription.unbind(this.eventFormatter.format(event), callback); } else { this.subscription.unbind(this.eventFormatter.format(event)); } - return this as unknown as T; + return this; } /** * Stop listening for all events on the channel instance. */ - stopListeningToAll(callback?: Function): T { + stopListeningToAll(callback?: Function): this { if (callback) { this.subscription.unbind_global(callback); } else { this.subscription.unbind_global(); } - return this as unknown as T; + return this; } /** * Register a callback to be called anytime a subscription succeeds. */ - subscribed(callback: Function): T { + subscribed(callback: Function): this { this.on('pusher:subscription_succeeded', () => { callback(); }); - return this as unknown as T; + return this; } /** * Register a callback to be called anytime a subscription error occurs. */ - error(callback: Function): T { + error(callback: Function): this { this.on('pusher:subscription_error', (status) => { callback(status); }); - return this as unknown as T; + return this; } /** * Bind a channel to an event. */ - on(event: string, callback: Function): T { + on(event: string, callback: Function): this { this.subscription.bind(event, callback); - return this as unknown as T; + return this; } } diff --git a/src/channel/pusher-encrypted-private-channel.ts b/src/channel/pusher-encrypted-private-channel.ts index 983d6d40..299e8da9 100644 --- a/src/channel/pusher-encrypted-private-channel.ts +++ b/src/channel/pusher-encrypted-private-channel.ts @@ -3,11 +3,11 @@ import { PusherChannel } from './pusher-channel'; /** * This class represents a Pusher private channel. */ -export class PusherEncryptedPrivateChannel extends PusherChannel { +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 7cc886b2..a1fc8cf6 100644 --- a/src/channel/pusher-presence-channel.ts +++ b/src/channel/pusher-presence-channel.ts @@ -1,15 +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])); }); @@ -20,7 +19,7 @@ export class PusherPresenceChannel extends PusherChannel i /** * Listen for someone joining the channel. */ - joining(callback: Function): PusherPresenceChannel { + joining(callback: Function): this { this.on('pusher:member_added', (member) => { callback(member.info); }); @@ -31,7 +30,7 @@ export class PusherPresenceChannel extends PusherChannel i /** * 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; @@ -40,7 +39,7 @@ export class PusherPresenceChannel extends PusherChannel i /** * 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 1f9b2e80..7952886d 100644 --- a/src/channel/pusher-private-channel.ts +++ b/src/channel/pusher-private-channel.ts @@ -3,11 +3,11 @@ import { PusherChannel } from './pusher-channel'; /** * This class represents a Pusher private channel. */ -export class PusherPrivateChannel extends PusherChannel { +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/pusher-public-channel.ts b/src/channel/pusher-public-channel.ts deleted file mode 100644 index 658ac9d3..00000000 --- a/src/channel/pusher-public-channel.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { PusherChannel } from './pusher-channel'; - -/** - * This class represents a Pusher public channel. - */ -export class PusherPublicChannel extends PusherChannel { - -} diff --git a/src/channel/socketio-channel.ts b/src/channel/socketio-channel.ts index 803de06a..47dc00c1 100644 --- a/src/channel/socketio-channel.ts +++ b/src/channel/socketio-channel.ts @@ -1,15 +1,10 @@ import { EventFormatter } from '../util'; import { Channel } from './channel'; -import { SocketIoPresenceChannel } from './socketio-presence-channel'; -import { SocketIoPrivateChannel } from './socketio-private-channel'; -import { SocketIoPublicChannel } from './socketio-public-channel'; - -export type SocketIoChannels = SocketIoPublicChannel | SocketIoPrivateChannel | SocketIoPresenceChannel; /** * This class represents a Socket.io channel. */ -export class SocketIoChannel extends Channel { +export class SocketIoChannel extends Channel { /** * The Socket.io client instance. */ @@ -79,43 +74,43 @@ export class SocketIoChannel extends Channel { /** * Listen for an event on the channel instance. */ - listen(event: string, callback: Function): T { + listen(event: string, callback: Function): this { this.on(this.eventFormatter.format(event), callback); - return this as unknown as T; + return this; } /** * Stop listening for an event on the channel instance. */ - stopListening(event: string, callback?: Function): T { + stopListening(event: string, callback?: Function): this { this.unbindEvent(this.eventFormatter.format(event), callback); - return this as unknown as T; + return this; } /** * Register a callback to be called anytime a subscription succeeds. */ - subscribed(callback: Function): T { + subscribed(callback: Function): this { this.on('connect', (socket) => { callback(socket); }); - return this as unknown as T; + return this; } /** * Register a callback to be called anytime an error occurs. */ - error(callback: Function): T { - return this as unknown as T; + error(callback: Function): this { + return this; } /** * Bind the channel's socket to an event and store the callback. */ - on(event: string, callback: Function): T { + on(event: string, callback: Function): this { this.listeners[event] = this.listeners[event] || []; if (!this.events[event]) { @@ -130,7 +125,7 @@ export class SocketIoChannel extends Channel { this.listeners[event].push(callback); - return this as unknown as T; + return this; } /** diff --git a/src/channel/socketio-presence-channel.ts b/src/channel/socketio-presence-channel.ts index ba8be355..cf0110fb 100644 --- a/src/channel/socketio-presence-channel.ts +++ b/src/channel/socketio-presence-channel.ts @@ -1,15 +1,14 @@ import { PresenceChannel } from './presence-channel'; -import { SocketIoChannel } from './socketio-channel'; import { SocketIoPrivateChannel } from './socketio-private-channel'; /** * This class represents a Socket.io presence channel. */ -export class SocketIoPresenceChannel extends SocketIoChannel implements PresenceChannel { +export class SocketIoPresenceChannel extends SocketIoPrivateChannel implements PresenceChannel { /** * 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)); }); @@ -20,7 +19,7 @@ export class SocketIoPresenceChannel extends SocketIoChannel callback(member.user_info)); return this; @@ -29,7 +28,7 @@ export class SocketIoPresenceChannel extends SocketIoChannel callback(member.user_info)); return this; diff --git a/src/channel/socketio-private-channel.ts b/src/channel/socketio-private-channel.ts index d92886d4..aa66ed3b 100644 --- a/src/channel/socketio-private-channel.ts +++ b/src/channel/socketio-private-channel.ts @@ -3,11 +3,11 @@ import { SocketIoChannel } from './socketio-channel'; /** * This class represents a Socket.io private channel. */ -export class SocketIoPrivateChannel extends SocketIoChannel { +export class SocketIoPrivateChannel extends SocketIoChannel { /** * Send a whisper event to other clients in the channel. */ - whisper(eventName: string, data: any): SocketIoPrivateChannel { + whisper(eventName: string, data: any): this { this.socket.emit('client event', { channel: this.name, event: `client-${eventName}`, diff --git a/src/channel/socketio-public-channel.ts b/src/channel/socketio-public-channel.ts deleted file mode 100644 index 2e350c17..00000000 --- a/src/channel/socketio-public-channel.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { SocketIoChannel } from './socketio-channel'; - -/** - * This class represents a Socket.io public channel. - */ -export class SocketIoPublicChannel extends SocketIoChannel { - -} diff --git a/src/connector/connector.ts b/src/connector/connector.ts index 4b3edac8..d5cd5b71 100644 --- a/src/connector/connector.ts +++ b/src/connector/connector.ts @@ -1,4 +1,6 @@ -export abstract class Connector { +import { Channel, PresenceChannel } from "../channel"; + +export abstract class Connector { /** * Default connector options. */ diff --git a/src/connector/null-connector.ts b/src/connector/null-connector.ts index a9211695..1e293fe6 100644 --- a/src/connector/null-connector.ts +++ b/src/connector/null-connector.ts @@ -1,10 +1,12 @@ import { Connector } from './connector'; -import { NullChannel, NullPrivateChannel, NullPresenceChannel, NullPublicChannel, NullEncryptedPrivateChannel, NullChannels } from './../channel'; +import { NullChannel, NullPrivateChannel, NullPresenceChannel, NullEncryptedPrivateChannel } from './../channel'; + +type AnyNullChannel = NullChannel | NullPrivateChannel | NullEncryptedPrivateChannel | NullPresenceChannel; /** * This class creates a null connector. */ -export class NullConnector extends Connector { +export class NullConnector extends Connector { /** * All of the subscribed channel names. */ @@ -20,14 +22,14 @@ export class NullConnector extends Connector { + listen(name: string, event: string, callback: Function): AnyNullChannel { return new NullChannel(); } /** * Get a channel instance by name. */ - channel(name: string): NullChannel { + channel(name: string): AnyNullChannel { return new NullChannel(); } diff --git a/src/connector/pusher-connector.ts b/src/connector/pusher-connector.ts index eb8de46b..121bf65e 100644 --- a/src/connector/pusher-connector.ts +++ b/src/connector/pusher-connector.ts @@ -1,17 +1,12 @@ import { Connector } from './connector'; -import { - PusherChannel, - PusherPrivateChannel, - PusherEncryptedPrivateChannel, - PusherPresenceChannel, - PusherPublicChannel, - PusherChannels, -} 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. */ @@ -45,14 +40,14 @@ export class PusherConnector extends Connector { + 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); } diff --git a/src/connector/socketio-connector.ts b/src/connector/socketio-connector.ts index 06cadca4..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, SocketIoPublicChannel, SocketIoChannels } from './../channel'; +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. */ @@ -13,7 +15,7 @@ export class SocketIoConnector extends Connector { + 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 a85622f1..f6853515 100644 --- a/src/echo.ts +++ b/src/echo.ts @@ -1,4 +1,4 @@ -import { Channel, NullEncryptedPrivateChannel, NullPresenceChannel, NullPrivateChannel, NullPublicChannel, PresenceChannel, PusherEncryptedPrivateChannel, PusherPresenceChannel, PusherPrivateChannel, PusherPublicChannel, SocketIoPresenceChannel, SocketIoPrivateChannel, SocketIoPublicChannel } 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'; /** @@ -210,28 +210,28 @@ export { EventFormatter } from './util'; type Broadcaster = { 'reverb': { connector: PusherConnector, - public: PusherPublicChannel, + public: PusherChannel, private: PusherPrivateChannel, encrypted: PusherEncryptedPrivateChannel, presence: PusherPresenceChannel, }, 'pusher': { connector: PusherConnector, - public: PusherPublicChannel, + public: PusherChannel, private: PusherPrivateChannel, encrypted: PusherEncryptedPrivateChannel, presence: PusherPresenceChannel, }, 'socket.io': { connector: SocketIoConnector, - public: SocketIoPublicChannel, + public: SocketIoChannel, private: SocketIoPrivateChannel, encrypted: never, presence: SocketIoPresenceChannel, }, 'null': { connector: NullConnector, - public: NullPublicChannel, + public: NullChannel, private: NullPrivateChannel, encrypted: NullEncryptedPrivateChannel, presence: NullPresenceChannel, From 05610edb658207ca57247b70d08188c8858934fa Mon Sep 17 00:00:00 2001 From: Dennis Prudlo Date: Fri, 1 Nov 2024 16:20:14 +0100 Subject: [PATCH 12/14] Remove unnecessary cast --- src/channel/pusher-channel.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/channel/pusher-channel.ts b/src/channel/pusher-channel.ts index 82506f76..07234239 100644 --- a/src/channel/pusher-channel.ts +++ b/src/channel/pusher-channel.ts @@ -64,7 +64,7 @@ export class PusherChannel extends Channel { listen(event: string, callback: Function): this { this.on(this.eventFormatter.format(event), callback); - return this as unknown as this; + return this; } /** From 24e75f74e82c01025e223f28ef7cba78deead301 Mon Sep 17 00:00:00 2001 From: Dennis Prudlo Date: Fri, 1 Nov 2024 16:28:42 +0100 Subject: [PATCH 13/14] Update quotes --- src/connector/connector.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/connector/connector.ts b/src/connector/connector.ts index d5cd5b71..0291ef70 100644 --- a/src/connector/connector.ts +++ b/src/connector/connector.ts @@ -1,4 +1,4 @@ -import { Channel, PresenceChannel } from "../channel"; +import { Channel, PresenceChannel } from '../channel'; export abstract class Connector { /** From 2b123dc7678b23f99afeaee165b3c8052d9f7937 Mon Sep 17 00:00:00 2001 From: Dennis Prudlo Date: Sat, 2 Nov 2024 18:16:32 +0100 Subject: [PATCH 14/14] Use NullChannel return type explicitly --- src/connector/null-connector.ts | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/connector/null-connector.ts b/src/connector/null-connector.ts index 1e293fe6..091550d4 100644 --- a/src/connector/null-connector.ts +++ b/src/connector/null-connector.ts @@ -1,8 +1,6 @@ import { Connector } from './connector'; import { NullChannel, NullPrivateChannel, NullPresenceChannel, NullEncryptedPrivateChannel } from './../channel'; -type AnyNullChannel = NullChannel | NullPrivateChannel | NullEncryptedPrivateChannel | NullPresenceChannel; - /** * This class creates a null connector. */ @@ -22,14 +20,14 @@ export class NullConnector extends Connector