CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-laravel-echo

Laravel Echo library for beautiful Pusher and Socket.IO integration

Pending
Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

SecuritybySnyk

Pending

The risk profile of this skill

Overview
Eval results
Files

connectors.mddocs/

Broadcasting Connectors

WebSocket client abstractions providing consistent APIs across different broadcasting services with automatic authentication and connection management.

Capabilities

Base Connector Class

Abstract base class providing common connector functionality for all broadcasting services.

/**
 * Base connector class for WebSocket broadcasting services
 */
abstract class Connector<TBroadcastDriver, TPublic, TPrivate, TPresence> {
  /** Default connector options */
  static readonly _defaultOptions: {
    auth: { headers: Record<string, string> };
    authEndpoint: string;
    userAuthentication: { endpoint: string; headers: Record<string, string> };
    csrfToken: string | null;
    bearerToken: string | null;
    host: string | null;
    key: string | null;
    namespace: string;
  };

  /** Connector options merged with defaults */
  options: EchoOptionsWithDefaults<TBroadcastDriver>;

  /** Create a new connector instance and automatically connect */
  constructor(options: EchoOptions<TBroadcastDriver>);

  /** Create a fresh connection to the WebSocket service */
  abstract connect(): void;
  
  /** Disconnect from the WebSocket service */
  abstract disconnect(): void;
  
  /** Get a public channel instance by name */
  abstract channel(channel: string): TPublic;
  
  /** Get a private channel instance by name */
  abstract privateChannel(channel: string): TPrivate;
  
  /** Get a presence channel instance by name */
  abstract presenceChannel(channel: string): TPresence;
  
  /** Leave the given channel and its variants */
  abstract leave(channel: string): void;
  
  /** Leave the specific channel */
  abstract leaveChannel(channel: string): void;
  
  /** Get the socket ID of the current connection */
  abstract socketId(): string | undefined;

  /** Listen for events on a channel by name */
  listen(name: string, event: string, callback: CallableFunction): TPublic;

  /** Merge custom options with defaults */
  protected setOptions(options: EchoOptions<TBroadcastDriver>): void;
  
  /** Extract CSRF token from the page or options */
  protected csrfToken(): string | null;
}

Pusher Connector

Connector for Pusher-based broadcasting services (Pusher, Reverb, Ably).

/**
 * Connector for Pusher-based broadcasting services
 */
class PusherConnector<T extends BroadcastDriver> extends Connector<
  T,
  PusherChannel<T>,
  PusherPrivateChannel<T>,
  PusherPresenceChannel<T>
> {
  /** The Pusher client instance */
  pusher: Pusher;
  
  /** All subscribed channel instances */
  channels: Record<string, PusherChannel<T> | PusherPrivateChannel<T> | PusherPresenceChannel<T>>;
  
  /** Pusher-specific options */
  declare options: PusherOptions<T>;

  /** Create a fresh Pusher connection */
  connect(): void;
  
  /** Get a public channel instance */
  channel(channel: string): PusherChannel<T>;
  
  /** Get a private channel instance */
  privateChannel(channel: string): PusherPrivateChannel<T>;
  
  /** Get an encrypted private channel instance */
  encryptedPrivateChannel(channel: string): PusherEncryptedPrivateChannel<T>;
  
  /** Get a presence channel instance */
  presenceChannel(channel: string): PusherPresenceChannel<T>;
  
  /** Leave channel and its variants */
  leave(channel: string): void;
  
  /** Leave specific channel */
  leaveChannel(channel: string): void;
  
  /** Get current socket ID */
  socketId(): string | undefined;
  
  /** Listen for events on a channel by name */
  listen(name: string, event: string, callback: CallableFunction): PusherChannel<T>;
  
  /** Disconnect from Pusher */
  disconnect(): void;
}

/** Pusher-specific configuration options */
interface PusherOptions<T extends BroadcastDriver> extends EchoOptionsWithDefaults<T> {
  key: string;
  Pusher?: typeof Pusher;
  cluster?: string;
  wsHost?: string;
  wsPort?: number;
  wssPort?: number;
  forceTLS?: boolean;
  enabledTransports?: string[];
  disabledTransports?: string[];
}

Usage Examples:

// The connector is typically used internally by Echo
// but can be accessed for advanced use cases

const echo = new Echo({
  broadcaster: "pusher",
  key: "your-pusher-key",
  cluster: "us2",
  wsHost: "ws.example.com",
  wsPort: 443,
  forceTLS: true,
});

// Access the underlying connector
const connector = echo.connector;

// Get raw Pusher instance for advanced features
// @ts-ignore - accessing internal property
const pusher = connector.pusher;

// Listen to connection state changes
pusher.connection.bind("state_change", (states) => {
  console.log("Connection state changed:", states);
});

Socket.IO Connector

Connector for Socket.IO broadcasting service.

/**
 * Connector for Socket.IO broadcasting service
 */
class SocketIoConnector extends Connector<
  "socket.io",
  SocketIoChannel,
  SocketIoPrivateChannel,
  SocketIoPresenceChannel
> {
  /** The Socket.IO client instance */
  socket: SocketIOClient.Socket;
  
  /** All subscribed channel instances */
  channels: Record<string, SocketIoChannel | SocketIoPrivateChannel | SocketIoPresenceChannel>;

  /** Create a fresh Socket.IO connection */
  connect(): void;
  
  /** Get a public channel instance */
  channel(channel: string): SocketIoChannel;
  
  /** Get a private channel instance */
  privateChannel(channel: string): SocketIoPrivateChannel;
  
  /** Get a presence channel instance */
  presenceChannel(channel: string): SocketIoPresenceChannel;
  
  /** Leave channel and its variants */
  leave(channel: string): void;
  
  /** Leave specific channel */
  leaveChannel(channel: string): void;
  
  /** Get current socket ID */
  socketId(): string | undefined;
  
  /** Listen for events on a channel by name */
  listen(name: string, event: string, callback: CallableFunction): SocketIoChannel;
  
  /** Disconnect from Socket.IO server */
  disconnect(): void;
}

Usage Examples:

const echo = new Echo({
  broadcaster: "socket.io",
  host: window.location.hostname + ":6001",
  namespace: "/chat",
});

// Socket.IO doesn't support encrypted private channels
// This will throw an error:
// echo.encryptedPrivate("sensitive-data"); // Error!

// Use regular private channels instead
echo.private("user.1").listen("PrivateMessage", (e) => {
  console.log("Private message:", e.message);
});

Null Connector

Mock connector for testing and development environments.

/**
 * Null/mock connector for testing purposes
 */
class NullConnector extends Connector<
  "null",
  NullChannel,
  NullPrivateChannel,
  NullPresenceChannel
> {
  /** Mock channel storage */
  channels: Record<string, NullChannel | NullPrivateChannel | NullPresenceChannel>;

  /** Mock connection (no-op) */
  connect(): void;
  
  /** Get a mock public channel */
  channel(channel: string): NullChannel;
  
  /** Get a mock private channel */
  privateChannel(channel: string): NullPrivateChannel;
  
  /** Get a mock encrypted private channel */
  encryptedPrivateChannel(channel: string): NullEncryptedPrivateChannel;
  
  /** Get a mock presence channel */
  presenceChannel(channel: string): NullPresenceChannel;
  
  /** Mock leave functionality */
  leave(channel: string): void;
  
  /** Mock leave channel functionality */
  leaveChannel(channel: string): void;
  
  /** Mock socket ID (returns null) */
  socketId(): string | undefined;
  
  /** Mock listen functionality (returns new NullChannel) */
  listen(name: string, event: string, callback: CallableFunction): NullChannel;
  
  /** Mock disconnect (no-op) */
  disconnect(): void;
}

Usage Examples:

// Useful for testing without real WebSocket connections
const echo = new Echo({
  broadcaster: "null",
  withoutInterceptors: true,
});

// All methods work but don't actually connect anywhere
echo.channel("test")
  .listen("TestEvent", (e) => {
    // This callback will never be called in null mode
    console.log("Test event:", e);
  });

// Null connector supports all channel types including encrypted
echo.encryptedPrivate("test").listen("Encrypted", (e) => {
  // Mock functionality - no actual encryption
});

Connector Configuration

Default Options

All connectors inherit these default options:

interface DefaultConnectorOptions {
  auth: {
    headers: Record<string, string>;
  };
  authEndpoint: string; // "/broadcasting/auth"
  userAuthentication: {
    endpoint: string; // "/broadcasting/user-auth"
    headers: Record<string, string>;
  };
  csrfToken: string | null;
  bearerToken: string | null;
  host: string | null;
  key: string | null;
  namespace: string; // "App.Events"
}

Authentication Configuration

Connectors automatically handle authentication for private and presence channels:

const echo = new Echo({
  broadcaster: "pusher",
  key: "your-key",
  
  // Custom auth endpoint
  authEndpoint: "/api/broadcasting/auth",
  
  // Additional auth headers
  auth: {
    headers: {
      "X-API-Key": "your-api-key",
    },
  },
  
  // Bearer token authentication
  bearerToken: "your-jwt-token",
  
  // Custom user authentication for presence channels
  userAuthentication: {
    endpoint: "/api/broadcasting/user-auth",
    headers: {
      "X-Custom-Header": "value",
    },
  },
});

CSRF Token Handling

Connectors automatically extract CSRF tokens from multiple sources:

// From Laravel meta tag
<meta name="csrf-token" content="your-csrf-token">

// From window.Laravel object
window.Laravel = {
  csrfToken: "your-csrf-token"
};

// Or explicitly in options
const echo = new Echo({
  broadcaster: "pusher",
  key: "your-key",
  csrfToken: "your-csrf-token",
});

Error Handling

Connectors provide error handling capabilities:

// Connection errors
echo.connector.connect();

// Channel subscription errors  
echo.channel("orders")
  .error((error) => {
    console.error("Channel subscription failed:", error);
  });

// Listen for connection state changes (Pusher)
if (echo.connector instanceof PusherConnector) {
  echo.connector.pusher.connection.bind("error", (error) => {
    console.error("Connection error:", error);
  });
}

docs

channels.md

connectors.md

echo-interface.md

index.md

tile.json